![]() |
CMSIS-RTOS RTX
Version 4.51
CMSIS-RTOS RTX: Real-Time Operating System for Cortex-M processor-based devices
|
The CMSIS-RTOS RTX functions provide delays in units of milliseconds that are derived from RTX Timer Tick. It is therefore recommended to configure the RTX Timer tick to generate a 1 millisecond interval. Configuring a longer RTX Timer Tick may reduce energy consumption, but has impacts on the granularity of the timeouts.
The value #define OS_CLOCK specifies the Cortex-M processor clock frequency in Hz. This value is used to calculate the RTX kernel timer reload value.
The value #define OS_TICK specifies the RTX Timer Tick frequency in Hz. This value is used to calculate timeout values and to configure the Cortex-M SysTick timer. It is therefore recommended to configure the RTX Timer tick to 1000 Hz which results in a timeout granularity of 1 millisecond.
With #define OS_SYSTICK 1 the Cortex-M SysTick core timer is selected as RTX kernel timer. In this case, the RTX kernel configures the SysTick timer clock source as processor clock. Therefore the value OS_CLOCK should be identical with the value of the CMSIS variable SystemCoreClock.
With #define OS_SYSTICK 0 an alternative timer is selected as RTX kernel timer.
Three functions in the RTX_Conf_CM.c Configuration File need to be adapted for using an alternative hardware timer.
Configuration Code:
The system thread os_idle_demo 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 a 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 */
}
}
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.
Configuration 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 */
}
}