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.
> 

Reply via email to