FreeRTOS vTaskDelayUntil()立即完成

时间:2017-01-14 16:28:25

标签: c freertos stm32f4

我有一个问题,即vTaskDelayUntil()函数没有延迟但是立即完成。这是代码:

TickType_t xLastWakeTime = xTaskGetTickCount();
while(1){
    if (xSemaphoreTake(xSemaphoreRS485, portMAX_DELAY) == pdTRUE) {
        printf("S display data %d\n", xTaskGetTickCount());
        sendDisplayData();
        printf("E display data %d\n", xTaskGetTickCount());
        xSemaphoreGive(xSemaphoreRS485);
        printf("W display data %d\n", xLastWakeTime);
        vTaskDelayUntil(&xLastWakeTime, 2000);
    }
}

从此我得到以下输出:

S display data 29928
E display data 30534
W display data 3919
S display data 30534
E display data 31140
W display data 5919
S display data 31140
E display data 31746
W display data 7919
S display data 31746
E display data 32352
W display data 9919

函数sendDisplayData()执行大约需要670毫秒,而xTaskGetTickCount()会确认它。然后任务应该在1230毫秒左右等待,因此整个迭代可能需要2000毫秒。但vTaskDelayUntil()立即完成。第一次执行在30534结束,第二次执行也从30534开始。 xTaskGetTickCount()返回的值证明vTaskDelayUntil()没有引入延迟。我也可以通过sendDisplayData()的输出频率来看。

第二个有趣的事情是xLastWakeTime显示完全不同的值,并且这些值实际上增加了2000.它不应该存储xTaskGetTickCount()返回的类似值吗?

2 个答案:

答案 0 :(得分:5)

在你的第一次迭代中,xLastWakeTime的值为3919,你请求增加2000,所以延迟到5919,但是你在30534时调用它。

来自vTaskDelayUntil()

的文档
  

应该注意的是,如果vTaskDelayUntil()用于指定已经过去的唤醒时间,则会立即返回(不会阻塞)。

您的任务花费了26009个刻度(29928 - 3919)在初始信号量上被阻止。您的目标2000滴答增量早已过去。

我建议以下内容至少接近你的意图

for(;;)
{
    if (xSemaphoreTake(xSemaphoreRS485, portMAX_DELAY) == pdTRUE)  // Lock
    {
        TickType_t xLastWakeTime = xTaskGetTickCount();
        sendDisplayData();
        xSemaphoreGive(xSemaphoreRS485); // Unlock

        vTaskDelayUntil(&xLastWakeTime, 2000);
}

这将使循环迭代总计需要2000个滴答,包括执行sendDisplayData() 加上等待RS485资源可用的时间所花费的时间,这就是我想你的意思意图。

答案 1 :(得分:1)

如上所述,如果指定的唤醒时间已经过去,则vTaskDelayUntil()将立即返回。建议改为使用vTaskDelay()