FreeRTOS 消息緩存(Message Buffer)的使用
介紹
在實時操作系統(RTOS)中,任務之間的通信是一個非常重要的方面。FreeRTOS 提供了多種機制來實現任務間通信,其中之一就是消息緩存(Message Buffer)。消息緩存非常適合傳遞長度可變的消息,并且在性能和靈活性方面提供了很大的優勢。
什么是消息緩存?
消息緩存是 FreeRTOS 提供的一種數據結構,用于在任務之間傳遞變長消息。與隊列不同,隊列適合固定長度的數據項,而消息緩存可以處理長度可變的消息。這使得消息緩存非常適用于需要傳遞不同長度消息的場景,比如傳輸字符串或結構化數據。
消息緩存的工作原理
消息緩存的基本操作包括創建、發送和接收消息。以下是其主要操作:
- 創建消息緩存:使用
xMessageBufferCreate
函數創建一個新的消息緩存。 - 發送消息到消息緩存:任務使用
xMessageBufferSend
將消息發送到緩存中。 - 從消息緩存接收消息:任務使用
xMessageBufferReceive
從緩存中接收消息。
實例:使用 FreeRTOS 消息緩存進行任務通信
下面是一個使用消息緩存在兩個任務之間傳遞消息的完整示例。在這個示例中,一個任務負責發送消息,另一個任務負責接收消息。
#include <Arduino.h>
#include <FreeRTOS.h>
#include <message_buffer.h>// 消息緩存句柄
MessageBufferHandle_t xMessageBuffer;// 發送任務
void vSenderTask(void *pvParameters) {const char *message = "Hello, FreeRTOS!";while (1) {// 發送消息size_t bytesSent = xMessageBufferSend(xMessageBuffer, message, strlen(message), pdMS_TO_TICKS(1000));if (bytesSent < strlen(message)) {Serial.println("Failed to send complete message");}// 每 2 秒發送一次vTaskDelay(pdMS_TO_TICKS(2000));}
}// 接收任務
void vReceiverTask(void *pvParameters) {char buffer[50];while (1) {// 接收消息size_t bytesReceived = xMessageBufferReceive(xMessageBuffer, buffer, sizeof(buffer), portMAX_DELAY);if (bytesReceived > 0) {buffer[bytesReceived] = '\0'; // 確保字符串以 NULL 結尾Serial.print("Received: ");Serial.println(buffer);} else {Serial.println("Failed to receive message");}}
}void setup() {// 初始化串口Serial.begin(115200);while (!Serial) {}// 創建消息緩存xMessageBuffer = xMessageBufferCreate(1024);if (xMessageBuffer == NULL) {Serial.println("Failed to create message buffer");while (1) {}}// 創建發送和接收任務xTaskCreate(vSenderTask, "Sender", 1024, NULL, 1, NULL);xTaskCreate(vReceiverTask, "Receiver", 1024, NULL, 1, NULL);// 啟動調度器vTaskStartScheduler();
}void loop() {// 主循環應為空,因為 FreeRTOS 任務在運行
}
API
1. 創建消息緩存
要創建一個消息緩存,使用 xMessageBufferCreate
函數:
MessageBufferHandle_t xMessageBufferCreate(size_t xBufferSizeBytes);
參數:
xBufferSizeBytes
:消息緩存的大小(字節數)。
返回值:
- 成功時返回消息緩存的句柄(非 NULL);失敗時返回 NULL。
示例:
MessageBufferHandle_t xMessageBuffer = xMessageBufferCreate(1024);
if (xMessageBuffer == NULL) {// 創建失敗,處理錯誤
}
2. 發送消息到消息緩存
使用 xMessageBufferSend
將消息發送到緩存中:
size_t xMessageBufferSend(MessageBufferHandle_t xMessageBuffer, const void *pvTxData, size_t xDataLengthBytes, TickType_t xTicksToWait);
參數:
xMessageBuffer
:消息緩存的句柄。pvTxData
:要發送的消息指針。xDataLengthBytes
:發送的消息長度(字節數)。xTicksToWait
:等待時間(滴答數)。
返回值:
- 成功發送的字節數。如果返回值小于
xDataLengthBytes
,則表示在xTicksToWait
時間內沒有足夠的空間發送所有消息。
示例:
const char *message = "Hello, FreeRTOS!";
size_t bytesSent = xMessageBufferSend(xMessageBuffer, message, strlen(message), portMAX_DELAY);
if (bytesSent < strlen(message)) {// 發送的數據不完整,處理錯誤
}
3. 從消息緩存接收消息
使用 xMessageBufferReceive
從緩存中接收消息:
size_t xMessageBufferReceive(MessageBufferHandle_t xMessageBuffer, void *pvRxData, size_t xBufferLengthBytes, TickType_t xTicksToWait);
參數:
xMessageBuffer
:消息緩存的句柄。pvRxData
:接收消息的緩沖區指針。xBufferLengthBytes
:接收緩沖區的大小(字節數)這設置了可以接收的消息的最大長度。xTicksToWait
:等待時間(滴答數)。
返回值:
- 成功接收的字節數。如果返回值小于
xBufferLengthBytes
,則表示在xTicksToWait
時間內沒有接收到足夠的消息。
示例:
char buffer[50];
size_t bytesReceived = xMessageBufferReceive(xMessageBuffer, buffer, sizeof(buffer), portMAX_DELAY);
if (bytesReceived > 0) {buffer[bytesReceived] = '\0'; // 確保字符串以 NULL 結尾Serial.println(buffer);
} else {// 接收失敗,處理錯誤
}
其他消息緩存 API
1. xMessageBufferCreateStatic
創建一個靜態分配的消息緩存。
MessageBufferHandle_t xMessageBufferCreateStatic(size_t xBufferSizeBytes, uint8_t *pucMessageBufferStorageArea, StaticMessageBuffer_t *pxStaticMessageBuffer);
參數:
xBufferSizeBytes
:消息緩存的大小(字節數)。pucMessageBufferStorageArea
:指向預先分配的緩存存儲區。pxStaticMessageBuffer
:指向預先分配的StaticMessageBuffer_t
結構。
返回值:
- 成功時返回消息緩存的句柄(非 NULL);失敗時返回 NULL。
2. xMessageBufferReset
重置消息緩存,使其變為空。
BaseType_t xMessageBufferReset(MessageBufferHandle_t xMessageBuffer);
參數:
xMessageBuffer
:消息緩存的句柄。
返回值:
- 如果成功重置消息緩存,則返回 pdPASS;如果在消息緩存上有任務阻塞,則返回 pdFAIL。
示例:
if (xMessageBufferReset(xMessageBuffer) == pdPASS) {// 重置成功
} else {// 重置失敗,處理錯誤
}
3. xMessageBufferSpacesAvailable
獲取消息緩存中可用的空閑空間(字節數)。
size_t xMessageBufferSpacesAvailable(MessageBufferHandle_t xMessageBuffer);
參數:
xMessageBuffer
:消息緩存的句柄。
返回值:
- 消息緩存中當前可用的空閑空間,以字節為單位。
示例:
size_t spaceAvailable = xMessageBufferSpacesAvailable(xMessageBuffer);
Serial.print("Space available: ");
Serial.println(spaceAvailable);
4. xMessageBufferNextLengthBytes
獲取消息緩存中下一個消息的長度(字節數)。
size_t xMessageBufferNextLengthBytes(MessageBufferHandle_t xMessageBuffer);
參數:
xMessageBuffer
:消息緩存的句柄。
返回值:
- 下一個消息的長度,以字節為單位。
示例:
size_t nextMessageLength = xMessageBufferNextLengthBytes(xMessageBuffer);
Serial.print("Next message length: ");
Serial.println(nextMessageLength);
5. vMessageBufferDelete
刪除消息緩存,釋放分配的內存。
void vMessageBufferDelete(MessageBufferHandle_t xMessageBuffer);
參數:
xMessageBuffer
:消息緩存的句柄。
返回值:
- 無返回值。
示例:
vMessageBufferDelete(xMessageBuffer);
總結
FreeRTOS 消息緩存通過在發送和接收消息時記錄和讀取消息長度,確保了消息的完整傳遞。這樣的設計使得發送的數據和接收的數據大小相等,從而保證了任務間通信的一致性和可靠性。