FreeRTOS SPI API and Atmel SAM4S-EK

Hi, I am using Atmel SAM4S-EK EVB and FreeRTOS 7.3.0.
I want to work with the FreeRTOS SPI API. When worked with the Atmel driver: spi_write() and spi_read(), everything seemed to be OK.
I connected an oscilloscope to the MOSI and CLK pins and saw that when writing, I saw the 16bit of what I wrote, when reading, I saw nothing – OK. Now, I am using the FreeRTOS API: static void spi_master_transfer(void *p_buf, uint32_t size)
{
status_code_t returned_status;
const portTickType time_out_definition = (100UL / portTICK_RATE_MS);
uint16_t data16_tx, data16_rx;
uint8_t  str; memcpy(&data16_tx, p_buf, sizeof(data16_tx));
returned_status = freertos_spi_write_packet_async(freertos_spi, &data16_tx, sizeof(data16_tx), time_out_definition,NULL);
sprintf( str, “SPI master sent: 0x%x”, data16_tx );
puts(str); memset(&data16_rx, 0, sizeof(data16_rx));
returned_status = freertos_spi_read_packet(freertos_spi, &data16_rx, sizeof(data16_rx), time_out_definition);
sprintf( str, “SPI master received: 0x%xn”, data16_rx );
puts(str); sprintf( str, “SPI master received: 0x%xn”, *receive_buffer );
puts(str);
} My questions are:
1. What is the purpose of receive_buffer that give in the driver_options on the spi_master_initialize()?
I don’t see its content changes at all…
2. Why when I use freertos_spi_write_packet_async(), I see 16bits of my data written, and then another 16bits of ‘0’ written?
3. Why when I am using freertos_spi_read_packet_async(), I see also two times of 16bit of writes. 16 bits of ‘1’ and another 16bits of ‘0’…
Please assist… Thanks,
Assaf

FreeRTOS SPI API and Atmel SAM4S-EK

1. What is the purpose of receive_buffer that give in the driver_options on the spi_master_initialize()?
I don’t see its content changes at all…
See section 1.2 of the application note, and the commented examples provided in the ASF.
2. Why when I use freertos_spi_write_packet_async(), I see 16bits of my data written, and then another 16bits of ‘0’ written?
I have not seen that behaviour (not discounting it might have been present).  When you initialised the port did you have
the WAIT_TX_COMPLETE bit in freertos_driver_parameters.options_flags set or clear?  If you are using the _async() version it must be clear.
3. Why when I am using freertos_spi_read_packet_async(), I see also two times of 16bit of writes. 16 bits of ‘1’ and another 16bits of ‘0’…
Presumably this is as per point 2 as to perform a write is performed in order to read. Regards.

FreeRTOS SPI API and Atmel SAM4S-EK

Hi, Thanks for your fast reply.
Let me understand, when I call the freertos_spi_write_packet_async(), I write 16 bits (as this is my configuration), at the same time, I receive 16 bits – this is how SPI works… where these bits stored? how can I read them?
As when I use  freertos_spi_read_packet_async(), it looks like it writes another 16 bits and then read another 16 bits…
Is it because FreeRTOS tries to save me writing “dummy” words in order to read last transmission? So maybe my first question now is, when I call the freertos_spi_write_packet_async(), I write 16 bits and at the same time, I receive 16 bits – … where these bits stored? how can I read them? After I’ll understand this, I’ll return to understand the read issue… Thanks a lot.
Assaf

FreeRTOS SPI API and Atmel SAM4S-EK

Also, I use only ( USE_TX_ACCESS_MUTEX | USE_RX_ACCESS_MUTEX ) in  freertos_driver_parameters.options_flags.
and I see fo sure two times of writings – two 16bits groups.
For the write, I see my 16bits sent data and after some clocks another group of 16 zeros.
For the read I see a write of group of 16 ‘1’ and then a write for 16 ‘0’…
I don’t understand it… This is my init function:
static void spi_master_initialize(void)
{
freertos_peripheral_options_t driver_options = { receive_buffer, /* The buffer used internally by the SPI driver to store incoming characters. */
RX_BUFFER_SIZE, /* The size of the buffer provided to the SPI driver to store incoming characters. */
configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY, /* The priority used by the SPI interrupts. */
SPI_MASTER, /* Configure the SPI for master. */
(USE_TX_ACCESS_MUTEX | USE_RX_ACCESS_MUTEX /*| WAIT_TX_COMPLETE | WAIT_RX_COMPLETE*/)
}; puts(”- Initialize SPI as masterrn”); is_spi_slave = false; /* Initialize the SPI interface as master. */
if ( NULL == freertos_spi)
{
freertos_spi = freertos_spi_master_init(SPI_MASTER_BASE, &driver_options);
/* Configure an SPI peripheral. */
spi_set_peripheral_chip_select_value(SPI_MASTER_BASE, SPI_CHIP_SEL);
spi_set_clock_polarity(SPI_MASTER_BASE, SPI_CHIP_SEL, SPI_CLK_POLARITY);
spi_set_clock_phase(SPI_MASTER_BASE, SPI_CHIP_SEL, SPI_CLK_PHASE);
spi_set_bits_per_transfer(SPI_MASTER_BASE, SPI_CHIP_SEL, SPI_CSR_BITS_16_BIT);
spi_set_baudrate_div(SPI_MASTER_BASE, SPI_CHIP_SEL, (sysclk_get_cpu_hz() / gs_ul_spi_clock));
spi_set_transfer_delay(SPI_MASTER_BASE, SPI_CHIP_SEL, SPI_DLYBS, SPI_DLYBCT);
spi_configure_cs_behavior(SPI_MASTER_BASE, SPI_CHIP_SEL, SPI_CS_KEEP_LOW);
spi_set_peripheral_chip_select_value(SPI_MASTER_BASE, SPI_CHIP_SEL);
spi_enable(SPI_MASTER_BASE);
}
} and this is my transfer function:
static void spi_master_transfer(void *p_buf, uint32_t size)
{
status_code_t returned_status;
const portTickType time_out_definition = (100UL / portTICK_RATE_MS);
uint16_t data16_tx, data16_rx;
uint8_t  str; memcpy(&data16_tx, p_buf, sizeof(data16_tx));
returned_status = freertos_spi_write_packet_async(freertos_spi, &data16_tx, sizeof(data16_tx), time_out_definition,NULL);
sprintf( str, “SPI master sent: 0x%x”, data16_tx );
puts(str); memset(&data16_rx, 0, sizeof(data16_rx));
returned_status = freertos_spi_read_packet(freertos_spi, &data16_rx, sizeof(data16_rx), time_out_definition);
sprintf( str, “SPI master received: 0x%xn”, data16_rx );
puts(str);
} I set a breakpoint on the write and read, then perform a step-over and catch the writes in the scope… thanks,

FreeRTOS SPI API and Atmel SAM4S-EK

Let me understand, when I call the freertos_spi_write_packet_async(), I write 16 bits (as this is my configuration), at the same time, I receive 16 bits – this is how SPI works.. where these bits stored? how can I read them?
I would have to double check, but presumably if you are writing out data then any data that happens to be on the input line is dropped (not read or buffered).  If you want to receive data then perform a read.  When you perform a read the driver will drive the clock by in effect writing out all 1’s while simultaneously placing data that is received into the buffer provided as a parameter to the read function. I don’t know why you are seeing another 16 bits on the bus after your initial 16-bit transfer. Are you using a standard dev board that I might have here so I can try it?  What is your SPI port connected to? Regards.

FreeRTOS SPI API and Atmel SAM4S-EK

Ok – noticed in your first post you are using a SAM4S-EK so ignore that question.  What are you talking to on the SAM4S-EK with the SPI port? Regards.

FreeRTOS SPI API and Atmel SAM4S-EK

Thanks.
I am using Atmels’ SAM4S-EK. I connected to pins PA11 to PA14 and GND. I monitor PA13 MOSI.
Now, reffering to your answer, my protocol is writing two words, word-address, then word-data, so, while writing these two words I receive two words that are dropped and get lost – if I am using FreeRTOS API…
If I’ll use the Atmel driver this is not happening… but I’ll need to configure the PDC myself and write another transfer function – more complicated one…

FreeRTOS SPI API and Atmel SAM4S-EK

I just set up a test on the same hardware. With spi_set_bits_per_transfer( spi_base, CHIP_SELECT,  SPI_CSR_BITS_8_BIT ); when I try to send two bytes I see exactly 8 clocks per byte on the scope – 16 in total. With spi_set_bits_per_transfer( spi_base, CHIP_SELECT, SPI_CSR_BITS_16_BIT ); I see 16 clocks per byte, 32 in total. I think if you configure to use 8 bit transfers you will get the results you expect. Regards.

FreeRTOS SPI API and Atmel SAM4S-EK

I don’t understand, doesn’t i this functions suppose to set how many bits to send in one transfer?
So if you give a uint16_t variable to freertos_spi_write_packet() and configure with SPI_CSR_BITS_8_BIT  it will transmit it in two times while if you configure it with SPI_CSR_BITS_16_BIT it will transmit it in one time?
Anyway, I’ll change my init configuration with SPI_CSR_BITS_8_BIT and test it.
I’ll update you on the results.
Thanks.

FreeRTOS SPI API and Atmel SAM4S-EK

OK. Indeed when configured with SPI_CSR_BITS_8_BIT there are 8 clocks per byte.
Nevertheless, in both configurations  SPI_CSR_BITS_8_BIT  and SPI_CSR_BITS_16_BIT there is a very big gap between the two bytes… why is that…

FreeRTOS SPI API and Atmel SAM4S-EK

Sorry. I understood it… it because spi_set_transfer_delay() configuration.
Thanks. Anyway, isn’t there a way to keep the data received back when I call freertos_spi_write_packet()?
because when I’ll use the freertos_spi_write_packet() it will write again, and the previous data will be lost and I’ll read new data…

FreeRTOS SPI API and Atmel SAM4S-EK

Once you have pointed the PDC (DMA) at the data the hardware is responsible for the data transmission without any software intervention,  so any observed spacing between transferred bytes is down to the hardware. Regards.

FreeRTOS SPI API and Atmel SAM4S-EK

isn’t there a way to keep the data received back when I call freertos_spi_write_packet()?
because when I’ll use the freertos_spi_write_packet() it will write again, and the previous data will be lost and I’ll read new data…

FreeRTOS SPI API and Atmel SAM4S-EK

Maybe that would be a good enhancement.  Can you provide a scenario where you would want to receive data as data is being written – that is when real data is actually being transmitted to an external device (EEPROM, LCD, whatever) so the device is receiving data as opposed to transmitting just 1’s to a device purely for the purpose of having the device itself send data back. Regards.

FreeRTOS SPI API and Atmel SAM4S-EK

For example, every time you write, you can get back (read) from the other device, your previous sent data, and compare it to check for errors in the communication… Also, I see that the byte order is switched in writing e.g.  if I want to write 0x8800, I see it actually transmitted 0x0088.
Is something configurable or I should write a macro to switch the bytes order?
  

FreeRTOS SPI API and Atmel SAM4S-EK

I have only ever used the system to send 8-bit data, in which case the bytes are transmitted byte for byte and there cannot be any byte swapping.  The PDC requires that the data being transmitted is in RAM, so when sending data I have copied the data into a RAM buffer as a sequence of bytes.  If your sequence of bytes contains data that is 16 or 32 bits wide then you will have to ensure that the endian of the data transmission matches the endian expected by the receiving device.  If you are using 16-bit transfers then you may be able to setup the SPI peripheral to do that for your, but if you are using 8-bit transfers then the data being sent will already have to be in the correct order. Regards.

FreeRTOS SPI API and Atmel SAM4S-EK

Referring to our previous correspondences, I want to use the FreeRTOS SPI API as I enjoy its PDC configuration and use, but again, its functionality drops the received buffer on the use of freertos_spi_write_packet().
If you think on it, this “divides” the clock by two…
I would like to receive a status back upon my write operation and further data upon read…
Can you explain me maybe, how can I add/tweak the FreeRTOS write function so It will not drop the received buffer so maybe I could read it with regular ASF spi_read function… or something..? Thanks, 

FreeRTOS SPI API and Atmel SAM4S-EK

I think I got it myself. I will use only freertos_spi_read_packet(), the ‘data’ will be my data to send,  I removed the ‘memset((void *)data, 0xff, (size_t)len);’, and I get back in ‘data’ the received buffer… How does it sounds to you? have you have a better idea…? Thanks a lot

FreeRTOS SPI API and Atmel SAM4S-EK

I don’t think it is that simple because I don’t think bytes on the serial in line are buffered anywhere when the SAM is writing on the serial out line. I have just checked two datasheets, both for eeproms, and both say the serial in line will be high impedance (i.e. tri-stated, not containing any data) when the serial out line is being driven so there is no data to receive at that time. Regards.