Atmel SAM4S, SPI and WAIT power mode

ltflash wrote on Thursday, August 13, 2015:

I’ve got the following problem with my test FreeRTOS project. I’ve implemented a tickless code using RTT timer and vPortSetupTimerInterrupt plus vPortSuppressTicksAndSleep functions, all works fine. In my project I’m using TWI and SPI buses and the problem starts when I put the MCU into SAM_PM_SMODE_WAIT mode. Any mode above that one, i.e. SAM_PM_SMODE_SLEEP_WFI works fine - MCU goes to sleep, wakes up and continues to work. But if I put MCU into WAIT mode then after wake up SPI bus becomes unavailable. I’ve tried to re-initialize SPI bus using all the commands that I previously used during MCU start-up but that doesn’t help at all. At the same time TWI bus continues to work fine, as well as UART/USART modules, it’s only SPI I have an issue with.

Could anyone point out what I might be doing wrong? Any help is much appreciated.

ltflash wrote on Thursday, August 13, 2015:

By the way, I’ve also tested same project using Atmel SAM3S MCU and got exactly the same result. I’m using Atmel Studio 6.2 with the latest ASF library installed.

rtel wrote on Thursday, August 13, 2015:

The deeper the sleep mode, the more is turned off, so presumably that
sleep mode is doing something the SPI doesn’t like. I’m afraid I don’t
know the specifics of the sleep mode’s actions without getting the data
sheet out. Can you say what the differences are in the sleep mode that
is not working and the next highest mode that is?

Also, have you checked the chip’s errata. If it is just that peripheral
that is not happy them maybe there is an issue in the device?


ltflash wrote on Thursday, August 13, 2015:

Thanks a lot for your reply.
Yes, I’ve checked the datasheet about all the modes and furthermore, I’ve tried to re-initialize the SPI bus right after MCU wake-up, but with no luck. I’ve also tested same code on Atmel SAM3S MCU.

Here are some details from datasheet. Please take into account that I definitely tried to re-enable clocks to SPI peripheral after wake-up, but that didn’t help. I actually did the whole initialize procedure, please see below.

I have no issues with using Slepp mode, but after Wait mode I can’t read/write to SPI. I’m using a RTT as a wake-up and tick source for FreeRTOS.

Sleep Mode
The purpose of Sleep mode is to optimize power consumption of the device versus response time. In this mode,
only the core clock is stopped. The peripheral clocks can be enabled. The current consumption in this mode is
application dependent.
This mode is entered via Wait for Interrupt (WFI) or WFE instructions with bit LPM = 0 in PMC_FSMR.
The processor can be woken up from an interrupt if the WFI instruction of the Cortex-M4 is used or from an event
if the WFE instruction is used.

Wait Mode
The purpose of Wait mode is to achieve very low power consumption while maintaining the whole device in a
powered state for a startup time of less than 10 μs. Current consumption in Wait mode is typically 32 μA (total
current consumption) if the internal voltage regulator is used.
In this mode, the clocks of the core, peripherals and memories are stopped. However, the core, peripherals and
memories power supplies are still powered. From this mode, a fast start up is available.
This mode is entered by setting the WAITMODE bit to 1 in the PMC Clock Generator Main Oscillator Register
(CKGR_MOR) in conjunction with the Flash Low Power Mode field FLPM = 0 or FLPM = 1 in the PMC Fast Startup
Mode Register (PMC_FSMR) or by the WFE instruction.
The Cortex-M4 is able to handle external or internal events in order to wake-up the core. This is done by
configuring the external lines WKUP0–15 as fast startup wake-up pins (refer to Section 5.8 “Fast Start-up”). RTC
or RTT Alarm and USB wake-up events can be used to wake up the CPU.

Here’s my SPI init function that works perfectly well until I start using WAIT mode:

static void spi_init()
const freertos_peripheral_options_t driver_options = {

freertos_spi = freertos_spi_master_init( SPI, &driver_options );


spi_set_clock_polarity(SPI, CHIP_SELECT, CLOCK_POLARITY);
spi_set_clock_phase(SPI, CHIP_SELECT, CLOCK_PHASE);
spi_set_bits_per_transfer(SPI, CHIP_SELECT, SPI_CSR_BITS_8_BIT);
spi_set_baudrate_div(SPI, CHIP_SELECT,(sysclk_get_cpu_hz() / BAUD_RATE));
spi_configure_cs_behavior(SPI, CHIP_SELECT, SPI_CS_KEEP_LOW);

spi_set_peripheral_chip_select_value(SPI, spi_get_pcs(CHIP_SELECT));



rtel wrote on Thursday, August 13, 2015:

I’m afraid I’m not going to be much help on this - its a bit chip
specific. Are you calling Atmel sleep manager code to place the CPU
into wait mode? If so I would suggest stepping into the code to see if
that gives any clues - it might be that you have to register the SPI
with a software sleep management library so it is not disabled when
entering sleep mode.

I don’t know if looking at the SAM4L
demo would give any clues.


ltflash wrote on Thursday, August 13, 2015:

Yes, I’m using pretty much same code to enter sleep mode of the MCU, using pmc_sleep(SAM_PM_SMODE_WAIT) in vPortSuppressTicksAndSleep function. The problem is that I can’t really debug this situation because MCU stops responding to debug commands as soon as it enters WAIT mode, it can’t even be detected by J-Link programmer/debugger…

ltflash wrote on Friday, August 14, 2015:

I’ve actually done some debugging and found that FreeRTOS is unable to obtain peripheral access mutex after MCU goes to sleep and then wakes up. I’ve traced it into freertos_obtain_peripheral_access_mutex function and it fails right here, returning ERR_TIMEOUT error:

	/* Wait to get exclusive access to the peripheral. */
	if (xSemaphoreTake(dma_event_control->peripheral_access_mutex,
			*max_block_time_ticks) == pdFAIL) {
		return_value = ERR_TIMEOUT;

Any ideas why that might be happening? Thanks a lot in advance.

ltflash wrote on Friday, August 14, 2015:

I’ve also checked the SAM4S datasheet and PDCA controllers are always on, you don’t need to enable or disable them and that can’t actually be done.

rtel wrote on Friday, August 14, 2015:

How do you know it has not actually timed out when attempting to take
the mutex?


ltflash wrote on Friday, August 14, 2015:

I’ve put a printf(“Unable to obtain DMA mutex\r\n”); right befor return_value = ERR_TIMEOUT, that’s why I can see that it fails in that function. And I can see return code ERR_TIMOUT in freertos_spi_send function.

ltflash wrote on Friday, August 14, 2015:

Can it somehow be related to the fact that Atmel’s ASF still uses a FreeRTOS 7.3.0? Maybe I need to upgrade it to the latest release for my project? If yes - how can I do that properly in order to keep all the compatibility with Atmel SAM4S MCU? Thanks.

rtel wrote on Friday, August 14, 2015:

I’ve put a printf(“Unable to obtain DMA mutex\r\n”); right befor
return_value = ERR_TIMEOUT, that’s why I can see that it fails in that
function. And I can see return code ERR_TIMOUT in freertos_spi_send

I understand it is timing out, but my question was, why do you think the
time out is not genuine?

[incidentally, calling printf() can be dangerous, depending where it is
called from, how it is implemented, and where the output goes]

Can it somehow be related to the fact that Atmel’s ASF still uses a
FreeRTOS 7.3.0?

If you were to update then you would probably have to change the mutexes
to instead be binary semaphores - as later versions restrict the use of
a mutex in an interrupt. You could just try updating the port layer
(the files in FreeRTOS/source/portable/GCC/ARM_CM3/4).


ltflash wrote on Friday, August 14, 2015:

In regards to time out - I’ve put the whole SPI initialization block in my task that uses SPI, so it disables clocks, then re-enables clocks to SPI, reconfigures SPI completely and only after that it tries to read/write the SPI using FreeRTOS functions. I’ve checked the PMC to make sure that clocks are enabled for SPI and PIOA controllers (using pmc_is_periph_enabled) and it returns all ok, peripheral is enabled. And after all that code program fails when it tries to obtain mutex while trying to send data over to SPI. I’ve also used a logic analyzer and can see that there’s nothing happening on SPI bus. Unfortunately, I’ve run out of ideas what might be wrong and why is that mutex can’t be obtained! :frowning:

I’ll try to upgrade the port to see what happens but I can’t see specific SAM3/4 port in the latest FreeRTOS distribution so I probably just use ARM_CM3/4.

heinbali01 wrote on Saturday, August 15, 2015:

Hi Yury,

If I may summarise: you bring your CPU in a deep sleep and after that the SPI doesn’t work any more.
At first you thought of a hardware problem (I would have thought also), but then you saw that a mutex (semaphore) can not be taken.

That sounds like a solvable problem, doesn’ it?

Would it be possible to administer every action that happens on this variable:


I would register things like:

- The physical address of the mutex (maybe it gets corrupted ?)
- The action: xSemaphoreTake, xSemaphoreGive, or xSemaphoreGiveFromISR
- The name of the function from where it is called
- The return code of the API

Do not use printf() but store these data in a circular array of strings or so. When the debuggers stops you will be able to see e.g. the last 10 actions on that mutex.

Good luck.

ltflash wrote on Sunday, August 16, 2015:

Hi Hein,
Thanks a lot for your reply!

Do you mean - to register these parameters befor MCU goes to sleep and then to compare them after? I can try to do that, but I really doubt that that would give any clue, as MCU retains all the RAM in WAIT mode. Furthermore, after MCU goes into WAIT mode debugger is unable to speak to it any more so I won’t be able to read any values, that’s why I was printing them out using UART. The strangest thing about all this is that UART and TWI buses are working perfectly fine after return from WAIT mode

My current suspicion is that FreeRTOS might be putting MCU into sleep between SPI cycles and that actually breaks everything. I was successful in compiling FreeRTOS 8.2.2 (latest one I found) with ASF library and I’m going to try this code to see if it works or not:

Previously I couldn’t compile it because it was throwing and error during compilation on this string:

/* Ensure it is still ok to enter the sleep mode. */
eSleepStatus = eTaskConfirmSleepModeStatus();

if( eSleepStatus == eAbortSleep )

So I just commented that part of code out. Maybe that’s the reason.

Anyway, thanks a lot for your help, everyone, I’ll keep you updated on my results!


ltflash wrote on Sunday, August 16, 2015:

Unfortunately, that code just doesn’t compile with the latest FreeRTOS…