This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

RTOS/CC1310: Task delay until

Part Number: CC1310

Tool/software: TI-RTOS

Hi,

Currently I am using Task_sleep() to block a task for a given time.

But I would like to use some kind of "delay until" block, as I am used to do with FreeRTOS.

How can I do that using TI-RTOS?

The FreeRTOS provide a function to do that:

void vTaskDelayUntil( TickType_t *pxPreviousWakeTime, const TickType_t xTimeIncrement );

Delay a task until a specified time. This function can be used by periodic tasks to ensure a constant execution frequency.

This function differs from vTaskDelay() in one important aspect: vTaskDelay() specifies a time at which the task wishes to unblock relative to the time at which vTaskDelay() is called, whereas vTaskDelayUntil() specifies an absolute time at which the task wishes to unblock.

vTaskDelay() will cause a task to block for the specified number of ticks from the time vTaskDelay() is called. It is therefore difficult to use vTaskDelay() by itself to generate a fixed execution frequency as the time between a task unblocking following a call to vTaskDelay() and that task next calling vTaskDelay() may not be fixed [the task may take a different path though the code between calls, or may get interrupted or preempted a different number of times each time it executes].

Whereas vTaskDelay() specifies a wake time relative to the time at which the function is called, vTaskDelayUntil() specifies the absolute (exact) time at which it wishes to unblock.

// Perform an action every 10 ticks.
 void vTaskFunction( void * pvParameters )
 {
 TickType_t xLastWakeTime;
 const TickType_t xFrequency = 10;

     // Initialise the xLastWakeTime variable with the current time.
     xLastWakeTime = xTaskGetTickCount();

     for( ;; )
     {
         // Wait for the next cycle.
         vTaskDelayUntil( &xLastWakeTime, xFrequency );

         // Perform action here.
     }
 }

 

 

  • One way to achieve this is to use the Clock and Semaphore modules.  You would create a Clock_Object that runs at your desired frequency, and its function posts a Semaphore on which the Task is pending.

    Here's some pseudo-code:

    /*
     * clockFxn is the service function for a Clock_Object that has been
     * created to run at the desired frequency.
     */
    Void clockFxn()
    {
        Semaphore_post(clockSem);
    }

    Void taskFxn()
    {
        for (;;) {
            /* Wait for next cycle. */
            Semaphore_pend(clockSem, BIOS_WAIT_FOREVER);

            /* Perform action here. */
        }
    }

    I don't know the semantics of vTaskDelayUntil() when it is called when the "until" time has already occurred, as could happen when the Task action takes longer than the frequency, but in the above code, the Semaphore_pend() will return immediately (since the Clock function posted the Semaphore while no Task was waiting on it).  I would expect vTaskDelayUntil() to do the same thing.

    Regards,

    - Rob

  • Robert Tivy said:

    I don't know the semantics of vTaskDelayUntil() when it is called when the "until" time has already occurred, as could happen when the Task action takes longer than the frequency, but in the above code, the Semaphore_pend() will return immediately (since the Clock function posted the Semaphore while no Task was waiting on it).  I would expect vTaskDelayUntil() to do the same thing.

    Regards,

    - Rob

    It should be noted that vTaskDelayUntil() will return immediately (without blocking) if it is used to specify a wake time that is already in the past.

    Is the following approach viable?

    #define DELAY 100
    
    uint32_t startTick;
    uint32_t endTick;
    
    void some_task(void)
    {
        while(1)
        {
            startTick = Clock_getTicks();
            
            /* Do something here */
            
            endTick = Clock_getTicks();
            
            Task_sleep(milli_to_ticks(DELAY) - (endTick - startTick));
        }
    }
    
    

  • Yes, that approach looks good.  I had the same thought after posting my previous reply.

    It would be wise to make sure you don't pass a "negative" or 0 value to Task_sleep().  If the sleep time ends up being <= 0, probably means it's time to "do something here" again.

    Regards,

    - Rob