CMSIS-RTOS RTX  Version 4.51
CMSIS-RTOS RTX: Real-Time Operating System for Cortex-M processor-based devices
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
Tick Timer Configuration

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.

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

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.

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.