There is nothing in the OS to delay until a specific OS time or to cause the scheduler to periodically wake up at a certain rate. There are different ways to go about doing this and it really depends on what you want. Using a task to guarantee timing can be tricky. Some things to be aware of (which I am sure you all are):
1) Unless you are the highest priority task, other tasks can run which could cause delays, and thus you are not waking up at the desired time. 2) Using os_time_delay() and os_callout_reset() gives you a 1 os time tick resolution, so if your ticks are 10 msecs, you will be off by up to 9 msecs. A 1 msec ticker gets you off by up to 1 msec. Using a task to post another task is a bit heavyweight; I would use a timer or a callout to do this. A timer would solve your “tick resolution” issue but would not solve the problem of a task wake up getting delayed. It would not be hard to add an API to os_callout.c that could be used for this. Something like “os_callout_reset_at” or “os_callout_reset_tick” which you could pass in a specified os tick. Not sure what the API should do if you missed the os tick (return -1 and not post the task)? This would be simple code to use; just add the sample rate to the last time and call the new os_calllout API. Will > On Dec 26, 2016, at 6:30 AM, Kevin Townsend <[email protected]> wrote: > > Hi Fabio, > > Thanks for the feedback and suggestion. > > I didn't think to have separate sync and read tasks. It does add a decent > amount of code when this could be solved with one or two lines and a built in > helper class, but it's a workable and reliable solution today. > > I also tested the code below but there are several potential problems with it: > > static void > blinky_task_handler(void *arg) > { > static os_time_t start; > static os_time_t stop; > hal_gpio_init_out(LED_BLINK_PIN, 1); > > while (1) { > /* Measure the starting tick */ > start = os_time_get(); > > /* Toggle the LED */ > hal_gpio_toggle(LED_BLINK_PIN); > > /* Measure the ending tick */ > stop = os_time_get(); > > /* Check for overflow in tick counter */ > if (stop >= start) { > os_time_delay(OS_TICKS_PER_SEC/BLINKY_RATE_HZ - (stop - > start)); > } else { > /* Overflow occured */ > os_time_delay(OS_TICKS_PER_SEC/BLINKY_RATE_HZ - stop + > (UINT_MAX - start) ); > } > } > } > > This doesn't account for situations where the read event might run /over/ the > desired rate either, which will require a check before the overflow test if > 'stop-start > OS_TICKS_PER_SECOND/BLINKY_RATE_HZ', at which point you > probably want to flag the timing overrun and maybe get a new sample right > away. There are likely other issues I'm not seeing as well, such as making > sure we don't exceed 1/2 the OS time epoch in our delay. > > Having a single helper function would let you encapsulate all these edge > cases in one call might be useful, but perhaps someone has a suggestion about > the naming or some other helpers that are worth considering ... or disagrees > that this should be included in the core at all!? > > FreeRTOS, for example, has vTaskDelayUntil(): > http://www.freertos.org/vtaskdelayuntil.html > > K. >
