CMSIS-RTOS RTX  Version 4.75
CMSIS-RTOS RTX: Real-Time Operating System for Cortex-M processor-based devices
RTX Kernel Tick Timer Configuration

The CMSIS-RTOS RTX functions provide delays in units of milliseconds that are derived from the 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 interval in microseconds (us). This value is used to calculate timeout values. When the SysTick core timer is enabled the value is also used to configure the SysTick timer. It is recommended to configure the RTX Timer tick to 1000 us which results in a timeout granularity of 1 millisecond.

Usage of the Cortex-M SysTick timer as RTX kernel timer

With #define OS_SYSTICK 1 the Cortex-M SysTick 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.

Usage of an alternative timer as RTX kernel timer.

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.

  • int os_tick_init (void) provides the initialization function for the alternative hardware timer.
  • void os_tick_irqack (void) is an interrupt acknowledge function that is called to confirm the alternative hardware timer interrupt.
  • OS_Tick_Handler needs to be called as the hardware timer interrupt function; the startup code should be modified to this function.

Configuration Code:

/*--------------------------- os_tick_init ----------------------------------*/
int os_tick_init (void) {
/* Initialize alternative hardware timer as RTX kernel timer. */
/* ... */
return (-1); /* Return IRQ number of timer (0..239) */
}
/*--------------------------- os_tick_irqack --------------------------------*/
void os_tick_irqack (void) {
/* Acknowledge timer interrupt. */
/* ... */
}

Configuration for Low-Power modes

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

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  */
  }
}
Note
__WFE() is not available at every Cortex-M implementation. Check device manuals for availability.