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 */ } }