void vTaskDelayUntil( TickType_t * const pxPreviousWakeTime, const TickType_t xTimeIncrement ) { TickType_t xTimeToWake; BaseType_t xAlreadyYielded, xShouldDelay = pdFALSE; configASSERT( pxPreviousWakeTime ); configASSERT( ( xTimeIncrement > 0U ) ); configASSERT( uxSchedulerSuspended == 0 ); vTaskSuspendAll(); { /* Minor optimisation. The tick count cannot change in this block. */ const TickType_t xConstTickCount = xTickCount; /* Generate the tick time at which the task wants to wake. */ xTimeToWake = *pxPreviousWakeTime + xTimeIncrement; if( xConstTickCount < *pxPreviousWakeTime ) { /* The tick count has overflowed since this function was lasted called. In this case the only time we should ever actually delay is if the wake time has also overflowed, and the wake time is greater than the tick time. When this is the case it is as if neither time had overflowed. */ if( ( xTimeToWake < *pxPreviousWakeTime ) && ( xTimeToWake > xConstTickCount ) ) { xShouldDelay = pdTRUE; } else { mtCOVERAGE_TEST_MARKER(); } } else { /* The tick time has not overflowed. In this case we will delay if either the wake time has overflowed, and/or the tick time is less than the wake time. */ if( ( xTimeToWake < *pxPreviousWakeTime ) || ( xTimeToWake > xConstTickCount ) ) { xShouldDelay = pdTRUE; } else { mtCOVERAGE_TEST_MARKER(); } } /* Update the wake time ready for the next call. */ *pxPreviousWakeTime = xTimeToWake; if( xShouldDelay != pdFALSE ) { traceTASK_DELAY_UNTIL( xTimeToWake ); /* prvAddCurrentTaskToDelayedList() needs the block time, not the time to wake, so subtract the current tick count. */ prvAddCurrentTaskToDelayedList( xTimeToWake - xConstTickCount, pdFALSE ); } else { mtCOVERAGE_TEST_MARKER(); } } xAlreadyYielded = xTaskResumeAll(); /* Force a reschedule if xTaskResumeAll has not already done so, we may have put ourselves to sleep. */ if( xAlreadyYielded == pdFALSE ) { portYIELD_WITHIN_API(); } else { mtCOVERAGE_TEST_MARKER(); } }
时间: 2024-04-18 14:24:39 浏览: 156
这是 FreeRTOS 中的 `vTaskDelayUntil()` 函数的实现代码。
该函数用于使任务进入阻塞状态,直到指定的时间点(`pxPreviousWakeTime` + `xTimeIncrement`)到达或超过当前系统的 tick 计数器的值。
具体实现逻辑如下:
1. 首先,函数会进行一系列的断言检查,以确保参数的有效性和调用环境的正确性。
2. 然后,函数会挂起调度器,禁止任务切换。
3. 在挂起调度器的情况下,函数会获取当前系统的 tick 计数器的值,并计算出任务希望唤醒的时间点 `xTimeToWake`。
4. 如果当前系统的 tick 计数器发生了溢出,那么只有在唤醒时间也发生了溢出且唤醒时间大于 tick 计数器时,才会真正进行延迟操作。否则,不进行延迟操作。
5. 更新 `pxPreviousWakeTime` 的值为下一次调用时的唤醒时间。
6. 如果需要进行延迟操作,则将当前任务添加到延迟列表中。
7. 恢复调度器的状态,并根据是否已经执行了任务切换来决定是否强制进行一次任务切换。
总之,`vTaskDelayUntil()` 函数根据指定的时间点来决定是否阻塞任务,并在适当的时机进行任务切换,以实现精确的定时功能。
相关问题
逐句解释 static TickType_t prvSampleTimeNow( BaseType_t * const pxTimerListsWereSwitched ) { TickType_t xTimeNow; PRIVILEGED_DATA static TickType_t xLastTime = ( TickType_t ) 0U; /*lint !e956 Variable is only accessible to one task. */ xTimeNow = xTaskGetTickCount(); if( xTimeNow < xLastTime ) { prvSwitchTimerLists(); *pxTimerListsWereSwitched = pdTRUE; } else { *pxTimerListsWereSwitched = pdFALSE; } xLastTime = xTimeNow; return xTimeNow; }
这段代码是FreeRTOS中的prvSampleTimeNow函数,用于获取当前系统时间。下面是逐句解释:
```
static TickType_t prvSampleTimeNow( BaseType_t * const pxTimerListsWereSwitched )
```
定义了一个名为prvSampleTimeNow的静态函数,返回值为TickType_t类型,参数为指向BaseType_t类型的指针pxTimerListsWereSwitched。
```
{
TickType_t xTimeNow;
PRIVILEGED_DATA static TickType_t xLastTime = ( TickType_t ) 0U; /*lint !e956 Variable is only accessible to one task. */
xTimeNow = xTaskGetTickCount();
```
定义了两个TickType_t类型的变量xTimeNow和xLastTime,其中xLastTime为静态变量,初始值为0。然后调用xTaskGetTickCount()函数获取当前的时钟节拍计数器的值,赋值给xTimeNow。
```
if( xTimeNow < xLastTime )
{
prvSwitchTimerLists();
*pxTimerListsWereSwitched = pdTRUE;
}
else
{
*pxTimerListsWereSwitched = pdFALSE;
}
xLastTime = xTimeNow;
return xTimeNow;
}
```
如果xTimeNow小于xLastTime,调用prvSwitchTimerLists()函数切换定时器列表,并将pxTimerListsWereSwitched指针指向的值设为pdTRUE。否则,将pxTimerListsWereSwitched指针指向的值设为pdFALSE。最后将xLastTime赋值为xTimeNow,并返回xTimeNow。
阅读全文