在FreeRTOS中,任務進入阻塞狀態通常是因為等待某個事件或資源。以下是常用的使任務進入阻塞態的API及其分類:
1. 任務延時
-
vTaskDelay(pdMS_TO_TICKS(ms))
將任務阻塞固定時間(相對延時,從調用時開始計算)。
示例:vTaskDelay(pdMS_TO_TICKS(100))
阻塞100毫秒。 -
vTaskDelayUntil(&xLastWakeTime, pdMS_TO_TICKS(ms))
按固定頻率阻塞任務(絕對時間,用于周期性任務)。
示例:實現精確的10ms周期任務。
2. 隊列操作
-
xQueueReceive(xQueue, &buffer, pdMS_TO_TICKS(timeout))
從隊列讀取數據,若隊列為空則阻塞,直到數據到達或超時。 -
xQueuePeek(xQueue, &buffer, pdMS_TO_TICKS(timeout))
查看隊列數據(不移除),若隊列為空則阻塞。 -
xQueueSend(xQueue, &data, pdMS_TO_TICKS(timeout))
向隊列發送數據,若隊列滿則阻塞,直到空間可用或超時。
3. 信號量
xSemaphoreTake(xSemaphore, pdMS_TO_TICKS(timeout))
獲取信號量,若信號量不可用則阻塞,常用于互斥量、二進制信號量。
4. 事件組
xEventGroupWaitBits(xEventGroup, uxBitsToWaitFor, xClearOnExit, xWaitForAllBits, pdMS_TO_TICKS(timeout))
等待事件組中的特定位被置位,滿足條件前任務阻塞。
5. 任務通知
-
ulTaskNotifyTake(pdTRUE, pdMS_TO_TICKS(timeout))
等待任務通知(類似二進制信號量),通知值減1。 -
xTaskNotifyWait(0, ULONG_MAX, &ulValue, pdMS_TO_TICKS(timeout))
等待任務通知并獲取通知值,支持更復雜場景。
6. 流緩沖區和消息緩沖區
-
xStreamBufferReceive(xStreamBuffer, &data, size, pdMS_TO_TICKS(timeout))
從流緩沖區讀取數據,緩沖區為空時阻塞。 -
xMessageBufferReceive(xMessageBuffer, &msg, size, pdMS_TO_TICKS(timeout))
從消息緩沖區接收完整消息,無消息時阻塞。
關鍵區別
- 阻塞與掛起:阻塞是等待事件(自動恢復),掛起需手動恢復(
vTaskSuspend
/vTaskResume
)。 - 超時參數:上述API通常含
timeout
參數,設為portMAX_DELAY
會無限阻塞(需配置INCLUDE_vTaskSuspend
為1)。
示例場景
// 等待信號量,最多阻塞500ms
if (xSemaphoreTake(xSemaphore, pdMS_TO_TICKS(500)) == pdTRUE) {// 成功獲取信號量
}// 從隊列接收數據,無限阻塞
xQueueReceive(xQueue, &data, portMAX_DELAY);
這些API通過讓任務等待特定條件,有效管理了CPU資源,適用于事件驅動或同步操作的設計。