maiorfi wrote on Wednesday, February 19, 2014:
Hi everybody.
We are experimenting a big issue on FreRTOS porting for Cypress PSoC5LP in a firmware using power management features with both 1 and 2 configUSE_TICKLESS_IDLE 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 configUSE_TICKLESS_IDLE to 1, we defined configPRE_SLEEP_PROCESSING and configPOST_SLEEP_PROCESSING as follows:
#define configPRE_SLEEP_PROCESSING( xModifiableIdleTime ) enterSleepMode(xModifiableIdleTime)
#define configPOST_SLEEP_PROCESSING(xModifiableIdleTime) exitFromSleepMode(xModifiableIdleTime)
where such functions are defined as follows:
#include <project.h>
#include "FreeRTOS.h"
#include "task.h"
static portTickType s_actualIdleTicks = (1<<SleepTimer_INTERVAL)/(1000/configTICK_RATE_HZ);
void enterSleepMode(uint32 xExpectedModifiableIdleTime)
{
xExpectedModifiableIdleTime=0;
CyPmSaveClocks();
CyPmSleep(PM_SLEEP_TIME_NONE,PM_SLEEP_SRC_CTW);
}
void exitFromSleepMode(uint32 xExpectedIdleTime)
{
CyPmRestoreClocks();
vTaskStepTick(s_actualIdleTicks);
}
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:
CY_ISR(WakeupIsr)
{
/***************************************************************************
* 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.
***************************************************************************/
SleepTimer_GetStatus();
}
we set up such isr as follows:
int main()
{
// Inizializzazione FreeRTOS
setupRTOS();
isr_SleepTimer_StartEx(WakeupIsr);
SleepTimer_Start();
/* Place your initialization/startup code here (e.g. MyInst_Start()) */
vStartSimpleTask(tskIDLE_PRIORITY+5);
// Avvio del RTOS
vTaskStartScheduler();
CyGlobalIntEnable;
for(;;)
{
/* Place your application code here. */
}
}
where setupRTOS() is standard initialization of vector table handlers provided by FreeRTOS “boilerplate” code:
void setupRTOS()
{
/* 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 )
{
portTickType xLastTime;
/* The parameters are not used. */
( void ) pvParameters;
/* We need to initialise xLastFlashTime prior to the first call to
vTaskDelayUntil(). */
xLastTime = xTaskGetTickCount();
uint8 toggler=1;
for(;;)
{
LED_Write(toggler);
toggler=!toggler;
// 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?
Thanks!