Creating a sequence of intervals with xTimer

Hi, I have to roll out some actions at predefined points in time. Here my idea to implement that: Starting point, only called once. ~~~~ static void startSequence( void ) { p = ipIntervals; // set p to the beginning of the list if ( p != NULL ) // if list is not empty { xTimerChangePeriod( myAlarmTimer, PERIODEMS( p->delay ), 0); // call some non blocking function, like set/reset a GPIO … p = p->nextNode; } } ~~~~ Callback: ~~~~ static inline void vTimerCallback( xTimerHandle pxTimer ) {
if ( p != NULL ) { xTimerChangePeriod( myAlarmTimer, PERIODEMS( p->delay ), 0); // call some non blocking function, like set/reset a GPIO … p = p->nextNode; } else done(); } ~~~~ Is this a good idea, or were there better implementation patterns available? How precise will be the time interval between my lets say set/reset operations in ticks? The length of the list, the functions and the delays were defined by command line inputs, so every possible sequence can take place .. With best regards Gerhard

Creating a sequence of intervals with xTimer

So each time a timer expires, you are resetting the period to the period required by the next timer? So are you setting the period of the next timer to be relative to when the first timer expires? Don’t forget that resetting the timer period will also reset the timer’s count (that is, will restart the timer). If you have lots of timers the above might be workable, if you can calculate the relative times ok. Otherwise, if you don’t have many timers, you could just create a unique timer for each action that needs to occur at some time in the future. The timers themselves are quite small objects, and you could still use the same callback function as the handle of the timer that actually expired is passed into the callback function. If each timer has a unique action you could even use the timer’s handle as a pointer to a function that performs the action.

Creating a sequence of intervals with xTimer

Ok, lets see I got it right: First I run through my list and create a timer for each node, setting the interval of this timer to be calculated relative to the starting point. As step one is 100 and step two should start 100 after step 1 I have to set the timer for step 2 to 200, ok? Now, all timer were running, and the callbacks appear at the points in time as setup. To have all timers started at the same point in time, I better should raise the tasks priority during initialisation phase, right? For your info, 100 means 100ms not 100 ticks, but still it would be fine to have the trigger points as precise as possible. Thanks a lot Gerhard

Creating a sequence of intervals with xTimer

I think, from your code and explanation, you have n actions that need to be performed at some point, but are only using a single software timer. Then when timer x expires, you are using the timer callback function to reset the timer so it expires at the correct timer for timer (x+1). If I have that correct, and the action to be performed when the timer expires for the first time needs to be performed at time 100, and the action that needs to be performed when the timer expires for the second time needs to be performed at time 150, the the timer would originally be set to expire after a timer of 100, and in the first callback function it would be set to expire again after a further 50 (ms, in your case). Therefore the first timer would expire at time 100, and the second would expire at time 100+50=150. Alternatively, and probably more simply, you could use two separate software timers, start them both at the same time, and have the period of the first timer set to 100 and the period of the second timer set to 150. The first timer would then still expire at time 100, and the second 50ms later. If you want to start both at once you could indeed temporarily raise the priority of the task that calls xTimerStart() while the timers are started, and then lower it again. Remember that timer commands go into the timer command queue, so if you raise the priority of the task so it is higher than the priority of the timer task then the commands will remain in the queue until the task’s priority is lowered again – so you need to ensure the queue is long enough.

Creating a sequence of intervals with xTimer

Ok. Yes, my first idea were to use/reuse one software timer. You told me, a software timer is a resource with small footprint, so I can use a seperate timer for each step. As far as I know, the list will have 10 to 20 intervals, as it is part of a scientific project doing basic research, nobody actually knows what will come next. How can I find out the priority of the TmrSvc task? I better should have the priotity, even temporarily lower than that task .. Thanks for hlping. With best regards Gerhard

Creating a sequence of intervals with xTimer

See the following: http://www.freertos.org/a00110.html#configTIMERTASKPRIORITY http://www.freertos.org/a00110.html#configTIMERQUEUELENGTH http://www.freertos.org/a00110.html#configTIMERTASKSTACK_DEPTH

Creating a sequence of intervals with xTimer

This might be better: http://www.freertos.org/Configuring-a-real-time-RTOS-application-to-use-software-timers.html

Creating a sequence of intervals with xTimer

Ok, nice, got it. But now my probably last question. If I use an individual timer for each of my steps, I have to accociate the function pointer and the arguments for that function somehow with each timer. In my callback I can write (func)(arg); but from where I get the correct ‘func’ and ‘arg’ values if some of my timers expires and calls the callback function? Thanks for helping again. With best regards Gerhard

Creating a sequence of intervals with xTimer

Each timer has a pointer associated with it, confusingly and for historic reasons call the timer’s ID. You can use the pointer for whatever you like – so you could use it as a pointer to a function. The initial value for the ID is passed into the xTimerCreate() API function using the pvTimerID parameter. You can then query the ID value using pvTimerGetTimerID(). There is also a set timer ID equivalent should you wish to change it.

Creating a sequence of intervals with xTimer

.. ah, ok, see that (void*) 0, parameter in samples, but as you mention wondering about this construction to pass a number, as the terminus ‘id’ suggests. Oh, really nice, so I will recraft all to go with that, thanks. So I let this ‘id’ point to the list node were the parameters and function pointer sits to define the action rolled out now. In the callback I retrieve this pointer and use it for my action, like: p = pvTimerGetTimerID(); (p->handler)(p->arg); And that is all I need. I will put the timer handles right into my list nodes, so when the list will be deleted I am able to delete the timers too. This way all the alloceted memory should be freed properly (and hopfully). With best regards Gerhard

Creating a sequence of intervals with xTimer

.. one more problem. How can a task wait for completition of all this actions, which will be started by its timers? With best regards Gerhard

Creating a sequence of intervals with xTimer

What about xTaskNotifyGive() and xTaskNotifyWait() or ulTaskNotifyTake() ? When the timer goes off, you function will be called. Your function can set a semaphore, send a message to a queue or use the TaskNotify function.

Creating a sequence of intervals with xTimer

Thanks Hein, as I only have FreeRTOS 7.3, I decide to use a queue. This way I also have the possibility to get a report from my actions, no error or what error if any. And I only need one queue doesn’t matter how many actions running. And as the actions by design doesnt likly end at the same point in time, there were only less queued items around. So this should also have a reasonable small footprint in memory. I start with a variable which is incremented whenever an action is started. When the timer expires, the (delayed) action is kicked off. If this is a fast operation (setting a GPIO ..) a report item is queued up. If this is a longer operation, the queue handle is handed over to whatever (task …) and than there a report item is queued up. The supervisorr task just tries to receive a report, do error checking, and if it gets one,it decremented the variable counting the active jobs. The loop in which the queue is maintained is canceled, after the variable holding the count of activ jobs get zero. Thanks for helping. With best regards Gerhard