Atmel SAM4S, SPI and WAIT power mode

Hi, 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 SAMPMSMODEWAIT mode. Any mode above that one, i.e. SAMPMSMODESLEEP_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.

Atmel SAM4S, SPI and WAIT power mode

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.

Atmel SAM4S, SPI and WAIT power mode

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? Regards.

Atmel SAM4S, SPI and WAIT power mode

Hi, 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 (CKGRMOR) in conjunction with the Flash Low Power Mode field FLPM = 0 or FLPM = 1 in the PMC Fast Startup Mode Register (PMCFSMR) 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 spiinit() { const freertosperipheraloptionst driveroptions = { NULL, 0, configLIBRARYMAXSYSCALLINTERRUPTPRIORITY, SPIMASTER, ( USETXACCESSMUTEX | USERXACCESSMUTEX | WAITTXCOMPLETE | WAITRXCOMPLETE ) };
freertos_spi = freertos_spi_master_init( SPI, &driver_options );

pmc_enable_periph_clk(ID_PIOA);
pio_configure(PIOA,PIO_PERIPH_A,(PIO_PA12A_MISO | PIO_PA13A_MOSI | PIO_PA14A_SPCK | PIO_PA11A_NPCS0),PIO_DEFAULT);
pmc_enable_periph_clk(ID_SPI);

spi_disable(SPI);

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

spi_enable(SPI);
}

Atmel SAM4S, SPI and WAIT power mode

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. Regards.

Atmel SAM4S, SPI and WAIT power mode

Yes, I’m using pretty much same code to enter sleep mode of the MCU, using pmcsleep(SAMPMSMODEWAIT) 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…

Atmel SAM4S, SPI and WAIT power mode

Hi, 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 freertosobtainperipheralaccessmutex 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.

Atmel SAM4S, SPI and WAIT power mode

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.

Atmel SAM4S, SPI and WAIT power mode

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

Atmel SAM4S, SPI and WAIT power mode

I’ve put a printf(“Unable to obtain DMA mutexrn”); right befor returnvalue = ERRTIMEOUT, that’s why I can see that it fails in that function. And I can see return code ERRTIMOUT in freertosspi_send function.

Atmel SAM4S, SPI and WAIT power mode

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.

Atmel SAM4S, SPI and WAIT power mode

I’ve put a printf(“Unable to obtain DMA mutexrn”); right befor returnvalue = ERRTIMEOUT, that’s why I can see that it fails in that function. And I can see return code ERRTIMOUT in freertosspi_send function.
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). Regards.

Atmel SAM4S, SPI and WAIT power mode

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 pmcisperiph_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! 🙁 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.

Atmel SAM4S, SPI and WAIT power mode

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:
dma_event_control->peripheral_access_mutex
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.

Atmel SAM4S, SPI and WAIT power mode

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: http://www.freertos.org/low-power-tickless-rtos.html 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! Regards, Yury.

Atmel SAM4S, SPI and WAIT power mode

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