We are experimenting a big issue on FreRTOS porting for Cypress PSoC5LP in a firmware using power management features with both 1 and 2 configUSETICKLESSIDLE modes.
To allow easier diagnostics, we just prepared a simple demo targeted to Cypress evaluation board for PSoC5LP microcontroller (CY8CKIT-050). It should run (with possible exception concerning on-board led pinout) on any board equipped with microcontrollers of same family (e.g. freesoc board). Demo project (for PSoC Creator 3 with GCC toolchain) is located at https://dl.dropboxusercontent.com/u/7414592/ELock/ELock_Firmware.cywrk.Archive01.zip
In our firmware we have only one simple task, running a never-ending cycle inside which it just toggles a led.
Setting configUSETICKLESSIDLE to 1, we defined configPRESLEEPPROCESSING and configPOSTSLEEPPROCESSING as follows:
#define configPRE_SLEEP_PROCESSING( xModifiableIdleTime ) enterSleepMode(xModifiableIdleTime)
#define configPOST_SLEEP_PROCESSING(xModifiableIdleTime) exitFromSleepMode(xModifiableIdleTime)
where such functions are defined as follows:
static portTickType s_actualIdleTicks = (1<<SleepTimer_INTERVAL)/(1000/configTICK_RATE_HZ);
void enterSleepMode(uint32 xExpectedModifiableIdleTime)
void exitFromSleepMode(uint32 xExpectedIdleTime)
Here, we refer to a SleepTimer "creator" component configured in such a way to raise interrupt at awake time (as explained in Cypress application note) whose isr is defined as:
* This function must always be called (when the Sleep Timer's interrupt
* is disabled or enabled) after wake up to clear the ctw_int status bit.
* It is required to call SleepTimer_GetStatus() within 1 ms (1 clock cycle
* of the ILO) after CTW event occurred.
we set up such isr as follows:
// Inizializzazione FreeRTOS
/* Place your initialization/startup code here (e.g. MyInst_Start()) */
// Avvio del RTOS
/* Place your application code here. */
where setupRTOS() is standard initialization of vector table handlers provided by FreeRTOS "boilerplate" code:
/* Port layer functions that need to be copied into the vector table. */
extern void xPortPendSVHandler( void );
extern void xPortSysTickHandler( void );
extern void vPortSVCHandler( void );
extern cyisraddress CyRamVectors;
/* Install the OS Interrupt Handlers. */
CyRamVectors[ 11 ] = ( cyisraddress ) vPortSVCHandler;
CyRamVectors[ 14 ] = ( cyisraddress ) xPortPendSVHandler;
CyRamVectors[ 15 ] = ( cyisraddress ) xPortSysTickHandler;
/* Start-up the peripherals. */
Our (only and simple) task definition is:
static portTASK_FUNCTION( vSimpleTask, pvParameters )
/* The parameters are not used. */
( void ) pvParameters;
/* We need to initialise xLastFlashTime prior to the first call to
xLastTime = xTaskGetTickCount();
// Wait for 1 sec...
vTaskDelayUntil( &xLastTime, configTICK_RATE_HZ );
Now for the weird issue:
The strange issue we experiment is that led flashes with a absolutely random period! Often it seems blocked, but waiting for 10-15 secs we can see the led toggling! Also, it is non so infrequent to look at very quick (roughly .1 secs) togglings.
What could be the cause of such non-deterministic behavior? What should be the "right way" to manage power management in FreeRTOS applications targeted to PSoC5LP?
I'm not going to be able to help with anything chip specific, but before getting to the chip specific stuff some basic questions:
1) If you set configUSETICKLESSIDLE to 0 and leave everything else the same, is the LED blinking as you would expect?
2) If the answer to (1) above is yes, if you set configUSETICKLESSIDLE to 1 but take out the pre and post sleep macros, is the LED blinking as you would expect?
So the problem must be either with the use of xModifiableIdleTime, which is the parameter passed into configPRESLEEPPROCESSING(), or the use of the Cypress libraries.
Are you expecting the Cypress libraries to perform the actually sleep function? That is, call wfi or wfe? If so then you must set xModifiableIdleTime to zero so FreeRTOS does not also call wfi.
In enterSleepMode() you are setting xExpectedModifiableIdleTime to zero - are you expecting that to set xModifiableIdleTime() to zero? As it is, xExpectedModifiableIdleTime is local to your enterSleepMode() function, so setting it to zero seems to be an obsolete action. If you want it to set xModifiableIdleTime() to zero then you will have to modify your configPRESLEEPPROCESSING() macro to either pass xModifiableIdleTime into enterSleepMode() by reference so it can then be set to zero, or to set xModifiableIdleTime to zero explicitly as per the following:
#define configPRE_SLEEP_PROCESSING( xModifiableIdleTime ) xModifiableIdleTime = 0; enterSleepMode();
Are you using SysTick to generate the tick interrupts?
We tried both setting (the actual, indeed) modifiableIdleTime to zero and not doing it, with same result.
Since we didn't provide a custom vPortSetupTimerInterrupt(), we should be using SysTick as tick source.
We're using FreeRTOS 7.6.1.
Oh, I forgot to mention that while debugging (via SWD, by mean of evaluation board built-in debugger) everything runs as expected. Maybe debugging features prevent entering in sleep mode?
It does sound like there is something wrong with the inputs to the Cypress drivers, or how some hardware is managed when you wake.
You say it works when debugging, but not when you run it without the debugger? It is likely the debugger would interfere, especially if it is polling the cycle counter or some other live view variables, but I would expect it to be the other way around - that is - to work better without the debugger than with it. Still, it gives you a clue either way.
Exactly, maybe at some level debugging subsystem simply prevents power mode changing.
Any news? Did you try to run linked firmware project in order to verify the issue?
Thank you very much.
Sorry - I don't have anything more to add over and above my post two above this one. It does appear to be something inside the Cypress drivers are not functioning as you think they do, or are not being re-initialised/reset/updated when you leave sleep. Plus the debugger interference issue will be a hardware effect, not a FreeRTOS effect.