11 years, 6 months ago.

What is the maximum value for a periodic RTOS timer?

In my tests, it seems that if you choose any value for a periodic timer > ~ 66000 (i.e. 66 seconds) then it will be truncated.

I tested that I'm not going mad by changing the little test program to

#include "mbed.h"
#include "rtos.h"

DigitalOut LEDs[4] = {
    DigitalOut(LED1), DigitalOut(LED2), DigitalOut(LED3), DigitalOut(LED4)
};

void blink(void const *n) {
    LEDs[(int)n] = !LEDs[(int)n];
}

int main(void) {
    RtosTimer led_1_timer(blink, osTimerPeriodic, (void *)0);
    RtosTimer led_2_timer(blink, osTimerPeriodic, (void *)1);
    RtosTimer led_3_timer(blink, osTimerPeriodic, (void *)2);
    RtosTimer led_4_timer(blink, osTimerPeriodic, (void *)3);
    
    led_1_timer.start(120000);
    led_2_timer.start(60000);
    led_3_timer.start(30000);
    led_4_timer.start(15000);
    
    Thread::wait(osWaitForever);
}

and I recorded LED1 with a stopwatch, and it did indeed change after 66 seconds. Is this really true, and if so, A) why is this not documented and B) how do I work around it? I had working code using Tickers and Timers before, but had to rewrite the whole thing in order to use the new Ethernet/NTP libraries which don't seem to work anymore unless you use RTOS.

I noticed the same, it seems the internal handling of the RTOS-timer is limited to 2^16 (65536) ms, wich would explain your 66s measurement. You can avoid this by letting your timer start a timer or set a factor in your code to only react every x-times the timer sends a signal.

posted by Hannes Schenk 27 Mar 2014

1 Answer

10 years ago.

Hi there,

I've got the same observation with my test code where I try to set RTOS periodic timeout at 2 minute. Dwelling into ROTS code in rtx/rt_CMSIS.C line 400 to 410, there is a truncation at line 407.

possible time count truncation

/// Convert timeout in millisec to system ticks
static uint32_t rt_ms2tick (uint32_t millisec) {
  uint32_t tick;

  if (millisec == osWaitForever) return 0xFFFF; // Indefinite timeout
  if (millisec > 4000000) return 0xFFFE;        // Max ticks supported

  tick = ((1000 * millisec) + os_clockrate - 1)  / os_clockrate;
  if (tick > 0xFFFE) return 0xFFFE;   // TRUCATION HAPPENS HERE

  return tick;
}

I'm wondering if mbed dev team has notice this and it is really a bug for some kind of overflow protection?

Sorry for being late... This is not a bug, and the limitation is not in mbed but in CMSIS RTX. The Timer structures are defined as:

// Timer structures

typedef struct os_timer_cb_ {                   // Timer Control Block
  struct os_timer_cb_ *next;                    // Pointer to next active Timer
  uint8_t             state;                    // Timer State
  uint8_t              type;                    // Timer Type (Periodic/One-shot)
  uint16_t         reserved;                    // Reserved
  uint16_t             tcnt;                    // Timer Delay Count
  uint16_t             icnt;                    // Timer Initial Count
  void                 *arg;                    // Timer Function Argument
  osTimerDef_t       *timer;                    // Pointer to Timer definition
} os_timer_cb

Obviously, the limiting factors are the uint16_t elements in these structures.

posted by Istvan Cserny 25 Feb 2016