Quality RTOS & Embedded Software

 Real time embedded FreeRTOS RSS feed 
Quick Start Supported MCUs PDF Books Trace Tools Ecosystem


Loading

SPI with Atmel SAM4S-EK and FreeRTOS 7.3.0

Posted by Goldie13 on April 22, 2013
Hi,

I am trying to operate a SPI interface on SAM4S-EK.
Can someone tell me why when I am using this function:

static void spi_master_transfer(void *p_buf, uint32_t size)
{
uint32_t i;
uint8_t uc_pcs;
static uint16_t data;
uint8_t *p_buffer;
uint32_t *p_buffer32;
uint8_t *str;

p_buffer = p_buf;
p_buffer32 = p_buf;

sprintf( str, "SPI master sent: 0x%x",(*p_buffer32) );
puts(str);
for (i = 0; i < size; i++)
{
spi_write(SPI_MASTER_BASE, p_buffer, 0, 0);
/* Wait transfer done. */
while ((spi_read_status(SPI_MASTER_BASE) & SPI_SR_RDRF) == 0);
spi_read(SPI_MASTER_BASE, &data, &uc_pcs);
p_buffer = data;
}
sprintf( str, "SPI master received: 0x%x\n",(*p_buffer32) );
puts(str);
}

Using only Atmels’ SPI driver, everything works OK.
But, when I am using the next function, using the FreeRTOS (7.3.0) SPI API,
The ‘freertos_spi_read_packet’ doesn’t return, instead I get to ‘Dummy_Handler’ indicating some exception occurred…

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);
uint8_t *p_buffer;
uint32_t *p_buffer32;
uint8_t *str;

p_buffer = p_buf;
p_buffer32 = p_buf;


returned_status = freertos_spi_write_packet(freertos_spi, p_buffer, size, time_out_definition);
sprintf( str, "SPI master sent: 0x%x",(*p_buffer32) );
puts(str);
returned_status = freertos_spi_read_packet(freertos_spi, p_buffer, size, time_out_definition);
sprintf( str, "SPI master received: 0x%x\n",(*p_buffer32) );
puts(str);
}

I appreciate your help.

Thanks,
Assaf

RE: SPI with Atmel SAM4S-EK and FreeRTOS 7.3.0

Posted by Richard on April 22, 2013
The Atmel ASF includes working examples for the FreeRTOS ASF SPI functions - and an application note. Have you tried using those?

In this case:
- Have you created the SPI port using a call to freertos_spi_master_init()? That should install the interrupt handler.
- If you have called freertos_spi_master_init() please determine which interrupt is being called (dummy_handler is installed on all unused interrupts I think). Knowing which interrupt is executing will help track down why the interrupt is being triggered.

Regards.

RE: SPI with Atmel SAM4S-EK and FreeRTOS 7.3.0

Posted by Goldie13 on April 23, 2013
Thank you for your reply.
1. Actually the ASF peripheral example does not contain SPI for SAM4S-EK, Anyway, as I follow the FreeRTOS API description, this code of mine, should work...
2. I did use the freertos_spi_master_init(), sorry for no mentioning it before.
3. So back to the original problem – I found the reason the freertos_spi_read_packet has crashed, Now I can’t understand why it doesn’t operate has expected:
I have a SPI slave device that return the 32bit of data it receives.
With Atmels’ driver only, I do see that I get back the data that I send:

static void spi_master_transfer(void *p_buf, uint32_t size)
{
uint32_t i;
uint8_t uc_pcs;
static uint16_t data;
uint8_t *p_buffer;
uint32_t *p_buffer32;
uint8_t *str;

p_buffer = p_buf;
p_buffer32 = p_buf;

sprintf( str, "SPI master sent: 0x%x",(*p_buffer32) );
puts(str);
for (i = 0; i < size; i++)
{
spi_write(SPI_MASTER_BASE, p_buffer, 0, 0);
/* Wait transfer done. */
while ((spi_read_status(SPI_MASTER_BASE) & SPI_SR_RDRF) == 0);
spi_read(SPI_MASTER_BASE, &data, &uc_pcs);
p_buffer = data;
}
sprintf( str, "SPI master received: 0x%x\n",(*p_buffer32) );
puts(str);
}

But using FreeRTOS API, I receive all kind of mixed data…

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);
uint32_t data32_tx, data32_rx;

memcpy(&data32_tx, p_buf, sizeof(data32_tx));
returned_status = freertos_spi_write_packet(freertos_spi, &data32_tx, sizeof(data32_tx), time_out_definition);

memset(&data32_rx, 0, sizeof(data32_rx));
returned_status = freertos_spi_read_packet(freertos_spi, &data32_rx, sizeof(data32_rx), time_out_definition);
}

I mean, I call this function couple of times.
I expect to read on the second time, the data I wrote the first time.

Nothing else but this function has changed in the program, and the slave device is the same too…

Can someone explain me why?...

Thanks,
Assaf

RE: SPI with Atmel SAM4S-EK and FreeRTOS 7.3.0

Posted by MEdwards on April 23, 2013
In this code you are clocking out SPI data then clocking in SPI data and expecting to receive what you sent. Is that correct? If so, I guess you have the SPI set into loopback mode, which I doubt the FreeRTOS driver does.

RE: SPI with Atmel SAM4S-EK and FreeRTOS 7.3.0

Posted by Goldie13 on April 24, 2013
Hi,

No. I am not using SPI loopback mode.
My setup include two devices, the SAM4S-EK set as SPI master and another device set to SPI slave. I am using Chip-Select 0.
The SPI slave device writes back the data it receives.
I am working on the SAM4S-EK master device.
Here is my master 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 master\r\n");

freertos_spi = freertos_spi_master_init(SPI_MASTER_BASE, &driver_options);

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_8_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);
}

Here is the slave init function:

static void spi_slave_initialize(void)
{
puts("- Initialize SPI as slave \r");
/* Configure an SPI peripheral. */
spi_enable_clock(SPI_SLAVE_BASE);
spi_disable(SPI_SLAVE_BASE);
spi_reset(SPI_SLAVE_BASE);
spi_set_slave_mode(SPI_SLAVE_BASE);
spi_disable_mode_fault_detect(SPI_SLAVE_BASE);
spi_set_peripheral_chip_select_value(SPI_SLAVE_BASE, SPI_CHIP_SEL);
spi_set_clock_polarity(SPI_SLAVE_BASE, SPI_CHIP_SEL, SPI_CLK_POLARITY);
spi_set_clock_phase(SPI_SLAVE_BASE, SPI_CHIP_SEL, SPI_CLK_PHASE);
spi_set_bits_per_transfer(SPI_SLAVE_BASE, SPI_CHIP_SEL, SPI_CSR_BITS_8_BIT);
spi_enable_interrupt(SPI_SLAVE_BASE, SPI_IER_RDRF);
spi_enable(SPI_SLAVE_BASE);

/* Start waiting command. */
spi_slave_transfer();
}

Now, I am transmitting and receiving 32 bits of data.
I repeat this couple of times, let’s say three times:

for( i = 0 ; i < 3 ; i++ )
{
cmd = ul_cmd_list;
spi_master_transfer(&cmd, sizeof(cmd));
}

I expect that on the first time, I’ll write 32bits of data, and read zero’s or some junk…
On the second time, I’ll write another 32bits of data, and receive back the 32bits I wrote the first time…
On the third time, I’ll write another 32bits of data, and receive back the 32bits I wrote the second time…

So again, when I am using transfer function option 1 (below), with clean Atmel’s driver everything works as expected,
But when I am using transfer function option 2, I get back mixed data and junk…
Nothing else but the transfer function was changed in the configuration… The slave device wasn’t changed at all and in the master I replaced only the transfer function to option 2…


Can you explain me the difference…?
Is it something related to ‘spi_set_bits_per_transfer(…)’ configuration? It should be the same for both master and slave, right?
Can you explain me what’s wrong?

Option 1:
static void spi_master_transfer(void *p_buf, uint32_t size)
{
uint32_t i;
uint8_t uc_pcs;
static uint16_t data;
uint8_t *p_buffer;
uint32_t *p_buffer32;
uint8_t *str;

p_buffer = p_buf;
p_buffer32 = p_buf;

sprintf( str, "SPI master sent: 0x%x",(*p_buffer32) );
puts(str);
for (i = 0; i < size; i++)
{
spi_write(SPI_MASTER_BASE, p_buffer, 0, 0);
/* Wait transfer done. */
while ((spi_read_status(SPI_MASTER_BASE) & SPI_SR_RDRF) == 0);
spi_read(SPI_MASTER_BASE, &data, &uc_pcs);
p_buffer = data;
}
sprintf( str, "SPI master received: 0x%x\n",(*p_buffer32) );
puts(str);
}

Option2:
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);
uint32_t data32_tx, data32_rx;

memcpy(&data32_tx, p_buf, sizeof(data32_tx));
returned_status = freertos_spi_write_packet(freertos_spi, &data32_tx, sizeof(data32_tx), time_out_definition);

memset(&data32_rx, 0, sizeof(data32_rx));
returned_status = freertos_spi_read_packet(freertos_spi, &data32_rx, sizeof(data32_rx), time_out_definition);
}

Thanks,
Assaf

RE: SPI with Atmel SAM4S-EK and FreeRTOS 7.3.0

Posted by Richard on April 24, 2013
Without being able to try this myself at the moment I'm not sure what to suggest.

“Actually the ASF peripheral example does not contain SPI for SAM4S-EK, Anyway, as I follow the FreeRTOS API description, this code of mine, should work...”


You can find an example in the \thirdparty\freertos\demo\peripheral_control\demo-tasks\SPI-FLASH-task.c file. It might be that it is not included in the SAM4S-EK demo project because the SAM4S-EK does not include the same SPI flash as found on other EK boards but reviewing the code there may still assist.

Regards.


[ Back to the top ]    [ About FreeRTOS ]    [ Privacy ]    [ Sitemap ]    [ ]


Copyright (C) Amazon Web Services, Inc. or its affiliates. All rights reserved.

Latest News

NXP tweet showing LPC5500 (ARMv8-M Cortex-M33) running FreeRTOS.

Meet Richard Barry and learn about running FreeRTOS on RISC-V at FOSDEM 2019

Version 10.1.1 of the FreeRTOS kernel is available for immediate download. MIT licensed.

View a recording of the "OTA Update Security and Reliability" webinar, presented by TI and AWS.


Careers

FreeRTOS and other embedded software careers at AWS.



FreeRTOS Partners

ARM Connected RTOS partner for all ARM microcontroller cores

Espressif ESP32

IAR Partner

Microchip Premier RTOS Partner

RTOS partner of NXP for all NXP ARM microcontrollers

Renesas

STMicro RTOS partner supporting ARM7, ARM Cortex-M3, ARM Cortex-M4 and ARM Cortex-M0

Texas Instruments MCU Developer Network RTOS partner for ARM and MSP430 microcontrollers

OpenRTOS and SafeRTOS

Xilinx Microblaze and Zynq partner