CMSIS-RTOS: Configuration for Low-Power Modes

| CMSIS-RTOS Version 1.03 Real-Time Operating System: API and RTX Reference Implementation.

- Main Page
- Usage and Description
- Reference

All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
Configuration for Low-Power Modes

The system thread os_idle_demon can be use to switch the system into a low-power mode. The easiest form to enter a low-power mode is the execution of the `__WFE` function that puts the processor into a sleep mode where it waits for an event.

Configuration Example:

#include "device.h" /* Device definitions */
void os_idle_demon (void) {
/* The idle demon is a system thread, running when no other thread is */
/* ready to run. */
for (;;) {
__WFE(); /* Enter sleep mode */
}
}

Note
  `__WFE()` is not available at every Cortex-M implementation. Check device manuals for availability.

# Tick-less operation

CMSIS-RTOS RTX provides extension for tick-less operation which is useful for applications that use extensively low-power modes where the SysTick timer is also disabled. To provide a time-tick in such power-saving modes a wake-up timer is used to derive timer intervals. The RTX functions os_suspend and os_resume control the tick-less operation.

Using this functions allows the RTX thread scheduler to stop the periodic kernel tick interrupt. When all active threads are suspended, the system enters power-down and calculates how long it can stay in this power-down mode. In the power-down mode the processor and potentially peripherals can be switched off. Only a wake-up timer must remain powered, because this timer is responsible to wake-up the system after the power-down period expires.

The tick-less operation is controlled from the os_idle_demon thread. The wake-up timeout value is set before the system enters the power-down mode. The function os_suspend calculates the wake-up timeout measured in RTX Timer Ticks; this value is used to setup the wake-up timer that runs during the power-down mode of the system.

Once the system resumes operation (either by a wake-up time out or other interrupts) the RTX thread scheduler is started with the function os_resume. The parameter sleep_time specifies the time (in RTX Timer Ticks) that the system was in power-down mode.

Code Example

#include "LPC11Uxx.h" /* LPC11Uxx definitions */
void os_idle_demon (void) {
/* The idle demon is a system thread, running when no other thread is */
/* ready to run. */
unsigned int sleep;
unsigned int tc;
LPC_SYSCON->SYSAHBCLKCTRL |= (1UL << 15) | /* Enable clock for WWDT */
(1UL << 19); /* Enable clock for Pin IRQ */
LPC_SYSCON->PINTSEL[0] = 1; /* P0.1 selected as INT0 IRQ */
LPC_SYSCON->STARTERP0 |= (1UL << 0); /* Enable INT0 wake-up */
LPC_SYSCON->STARTERP1 |= (1UL << 12); /* Enable WWDT wake-up */
LPC_SYSCON->WDTOSCCTRL = (3 << 0) | /* WDOSC DIVSEL=3 */
(2 << 5); /* WDOSC FREQ=0.8MHz */
LPC_SYSCON->PDRUNCFG &= ~(1UL << 6); /* Power-up WDT Oscillator */
LPC_SYSCON->PDSLEEPCFG &= ~(1UL << 6); /* Power WDT Oscillator in PD */
LPC_WWDT->CLKSEL = (1UL << 0) | /* Select WDOSC as Clock */
(1UL << 31); /* Lock selection */
LPC_WWDT->WARNINT = 1000; /* WDT Warning IRQ value */
LPC_WWDT->MOD = (1UL << 0); /* Enable WDT */
NVIC_EnableIRQ(FLEX_INT0_IRQn); /* Enable INT0 IRQ (wake-up) */
NVIC_EnableIRQ(WDT_IRQn); /* Enable WWDT IRQ (wake-up) */
for (;;) {
/* HERE: include optional user code to be executed when no task runs.*/
sleep = os_suspend(); /* Suspend RTX thread scheduler */
if (sleep) { /* How long can we sleep? */
/* "sleep" is in RTX Timer Ticks which is 10ms in this configuration */
/* Setup WDT wake-up: WDT ticks @25kHz (FREQ/2/(DIVSEL+1)/4) */
tc = (sleep * 250) + 1000;
LPC_WWDT->TC = tc;
LPC_WWDT->FEED = 0xAA;
LPC_WWDT->FEED = 0x55;
/* Enter Power-down mode */
LPC_SYSCON->PDAWAKECFG = LPC_SYSCON->PDRUNCFG; /* Power after wake-up */
LPC_PMU->PCON = 0x02; /* Select Power-down mode */
SCB->SCR = (1UL << 2); /* Set SLEEPDEEP */
__WFE(); /* Enter Power-down mode */
/* After Wake-up */
sleep = (tc - LPC_WWDT->TV) / 250;
}
os_resume(sleep); /* Resume RTX thread scheduler */
}
}

Note
  `__WFE()` is not available at every Cortex-M implementation. Check device manuals for availability.