【freeRTOS】vTaskDelay 與 vTaskDelayUntil 的差異

以vTaskDelay()為例子

toggle LED1後以vTaskDelay()阻塞task 100ms,醒來後task A執行了30ms的迴圈

static void task_A (void * pvParameter)
{
    while (true)
    {
        LED1_TOGGLE();// (mark1)
        vTaskDelay( pdMS_TO_TICKS(100) ); 

        LED3_TOGGLE();// (mark2)     
        nrf_delay_ms(30); 
        LED3_TOGGLE();// (mark3)    
    }
}

從波形可以看到task A每執行一整個任週期要花費 100+30=130ms

(mark2)到(mark3)的30ms可當成是task在執行程式內容時所花費的時間,只要task程序時間小於週期長度

故依task程式內容而定,task的執行週期將不是固定時間長度




接下來以xTaskDelayUntil()為例子

toggle vTaskDelayUntil()阻塞task 100ms,醒來後task B執行了30ms的迴圈

static void task_B (void * pvParameter)
{
    TickType_t xLastWakeTime;
    const TickType_t xFrequency = pdMS_TO_TICKS(100);

    xLastWakeTime = xTaskGetTickCount();

    while (true)
    {
        LED2_TOGGLE();// mark1
        vTaskDelayUntil ( &xLastWakeTime, xFrequency );

        LED4_TOGGLE();// mark2
        nrf_delay_ms(30);     
        LED4_TOGGLE();// mark3
    }
}

可以明顯看出task的程式執行所花費時間並未去影響到下一個task B進入阻塞再喚醒



結論

vTaskDelay()就像是碼錶,每次執行後就重新計數

vTaskDelayUntil()則是像行事曆,依靠著系統時間訂定絕對的排程



這個例子是把上面的task A和B放在一起運行的結果


nrf_Delay_B falling edge表示task B結束100ms的阻塞,回到Running mode並取後系統使用權

rasing edge即task B完成程序並進入下一個100ms阻塞

因為 優先權 A > B ,會遇到幾個狀況,

1. task A正在使用系統,task B的程序被延後

2. task B執行到一半的程序被逼中斷,系統使用權回到task A身上

task B僅管遇到優先權的亂流,仍不影響整體的週期性表現