AnsweredAssumed Answered

osTimer arguments not functional

Question asked by Richard Lowe on Sep 15, 2017
Latest reply on Mar 28, 2018 by Rostyslav S

When creating a RTOS timer in CMSIS the documentation is clear: Timer Management 

 

When it states for creating a timer is described as:

osTimerId osTimerCreate     (const osTimerDef_t * timer_def, os_timer_type type, void *argument)          

The part that isn't working is the argument portion:

 

Here's an example:

#include "cmsis_os.h"

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

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

osTimerDef(blink_0, blink);
osTimerDef(blink_1, blink);
osTimerDef(blink_2, blink);
osTimerDef(blink_3, blink);

int main(void) {
    osTimerId timer_0 = osTimerCreate(osTimer(blink_0), osTimerPeriodic, (void *)0);
    osTimerId timer_1 = osTimerCreate(osTimer(blink_1), osTimerPeriodic, (void *)1);
    osTimerId timer_2 = osTimerCreate(osTimer(blink_2), osTimerPeriodic, (void *)2);
    osTimerId timer_3 = osTimerCreate(osTimer(blink_3), osTimerPeriodic, (void *)3);
   
    osTimerStart(timer_0, 2000);
    osTimerStart(timer_1, 1000);
    osTimerStart(timer_2,  500);
    osTimerStart(timer_3,  250);
   
    osDelay(osWaitForever);
}

 If you try this, it won't work.

 

Problem is when you follow the code from CMSIS you notice the void* argument is treated as an identifier in FreeRTOS. 

 

The

void* argument

is populated on the pvTimerID member of the xTIMER struct in FreeRTOS.

/* The definition of the timers themselves. */
typedef struct tmrTimerControl
{
     const char                    *pcTimerName;          /*<< Text name.  This is not used by the kernel, it is included simply to make debugging easier. */ /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
     ListItem_t                    xTimerListItem;          /*<< Standard linked list item as used by all kernel features for event management. */
     TickType_t                    xTimerPeriodInTicks;/*<< How quickly and often the timer expires. */
     UBaseType_t                    uxAutoReload;          /*<< Set to pdTRUE if the timer should be automatically restarted once expired.  Set to pdFALSE if the timer is, in effect, a one-shot timer. */
     void                          *pvTimerID;               /*<< An ID to identify the timer.  This allows the timer to be identified when the same callback is used for multiple timers. */
     TimerCallbackFunction_t     pxCallbackFunction;     /*<< The function that will be called when the timer expires. */
     #if( configUSE_TRACE_FACILITY == 1 )
          UBaseType_t               uxTimerNumber;          /*<< An ID assigned by trace tools such as FreeRTOS+Trace */
     #endif

     #if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
          uint8_t                ucStaticallyAllocated; /*<< Set to pdTRUE if the timer was created statically so no attempt is made to free the memory again if the timer is later deleted. */
     #endif
} xTIMER;

 

So the following code is what I've implemented:

/* USER CODE BEGIN RTOS_TIMERS */
    /* start timers, add new ones, ... */
    // Heartbeat
    osTimerDef(heartbeat, status_feedback);
    feedback_heartbeat = osTimerCreate(osTimer(heartbeat), osTimerOnce, (void*)0);
    // Approved
    osTimerDef(approved, status_feedback);
    feedback_approved = osTimerCreate(osTimer(approved), osTimerOnce, (void*)1);
    // Denied
    osTimerDef(denied, status_feedback);
    feedback_denied = osTimerCreate(osTimer(denied), osTimerOnce, (void*)2);
    /* USER CODE END RTOS_TIMERS */

 

I should be able to use something like:

 

void status_feedback(void const* args)
{
    switch((int)args)
    {
        case 0:
             // Here
             break;
    }
}

 But no.

 

When examining the args variable I discovered that it is the address of the timer object. So this works:

 

void status_feedback(void const* args)
{
    if( args == feedback_heartbeat )
    {
       //here
    }
}

 

Long story short. Arguments don't work when creating an osTimer. Or have I got it wrong?

Outcomes