freeRtos学习笔(4)消息队列
生活随笔
收集整理的這篇文章主要介紹了
freeRtos学习笔(4)消息队列
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
freeRtos學習筆記
freeRtos消息隊列
為什么要用消息隊列
消息隊列可以在任務與任務間,中斷與任務間傳遞信息。為什么不用全局數組?全局數組也可以傳遞信息,但是和消息隊列相比,消息隊列有一下優勢:
- 全局數組需要解決多任務訪問沖突,需要加臨界區保護
- 消息隊列可以實現超時機制
- 消息隊列可以實現FIFO和LIFO機制
消息隊列創建
QueueHandle_t xQueueCreate(UBaseType_t uxQueueLength, /* 消息個數 */UbaseType_t uxItemSize); /* 消息大小 單位字節 */函數 xQueueCreate 用于創建消息隊列。
- 第 1 個參數是消息隊列支持的消息個數。
- 第 2 個參數是每個消息的大小, 單位字節。
- 返回值,如果創建成功會返回消息隊列的句柄,如果由于 FreeRTOSConfig.h 文件中 heap 大小不足,
無法為此消息隊列提供所需的空間會返回 NULL。
需要注意,消息隊列傳遞消息是消息本身被copy到消息隊列中,而不是傳遞指針,因此消息盡量不要太大,否則可能會影響實時性。
消息隊列刪除
void vQueueDelete(QueueHandle_t xQueue);消息隊列刪除函數
- 第 1 個參數是消息隊列
- 注意,消息隊列刪除后,會釋放消息隊列的內存空間,但是如果刪除消息隊列時,有任務正在等待消息, 則不應
該進行刪除操作
消息隊列發送
BaseType_t xQueueSend(QueueHandle_t xQueue, /* 消息隊列 */const void* pvItemToQueue, /* 要發送消息地址 */TickType_t xTicksToWait); /* 如果消息隊列已滿,等待超時時間 *//* 和xQueueSend函數作用相同,將消息添加在消息隊列尾部 */ BaseType_t xQueueSendToBack(QueueHandle xQueue, const void* pvItemToQueue,TickType_t xTicksToWait);/* 將消息添加在消息隊列頭部 */ BaseType_t xQueueSendToFront(QueueHandle_t xQueue,const void* pvItemToQueue,TickType_t xTicksToWait);/* 在中斷中發送消息,為了實時性,中斷中不應該存在堵塞或者延時,因此這里沒有發送超時參數 */ BaseType_t xQueueSendFromISR(QueueHandle_t xQueue, /* 消息隊列 */const void* pvItemToQueue, /* 要發送消息地址 */BaseType_t* pxHigherPriorityTaskWoken); /* 消息發送后,是否有更高級別的任務就緒 */BaseType_t xQueueSendToBackFromISR(QueueHandle_t xQueue, /* 消息隊列 */const void* pvItemToQueue, /* 要發送消息地址 */BaseType_t* pxHigherPriorityTaskWoken); /* 消息發送后,是否有更高級別的任務就緒 */BaseType_t xQueueSendToFrontFromISR(QueueHandle_t xQueue, /* 消息隊列 */const void* pvItemToQueue, /* 要發送消息地址 */BaseType_t* pxHigherPriorityTaskWoken); /* 消息發送后,是否有更高級別的任務就緒 */消息隊列發送函數
- 第 1 個參數是消息隊列句柄。
- 第 2 個參數要傳遞數據地址,每次發送都是將消息隊列創建函數 xQueueCreate 所指定的單個消息大
小復制到消息隊列空間中。 - 在任務中 第 3 個參數是當消息隊列已經滿時,等待消息隊列有空間時的最大等待時間,單位系統時鐘節拍。
- 在中斷中 第 3 個參數是消息發送后,是否有更高級別的任務就緒,如果有更高級別任務就緒(優先級更高的任務堵塞在消息接收上,這里發送了消息,導致任務從堵塞態轉變為就緒態),則pxHigherPriorityTaskWoken變為pdTRUE,然后在中斷結束處調用taskYIELD()進行任務調度。
- 返回值, 如果消息成功發送返回 pdTRUE,否則返回 pdFALSE
使用消息隊列函數要注意以下問題:
消息隊列接收
BaseType_t xQueueReceive(QueueHandle_t xQueue, /* 消息隊列 */void* pvBuffer, /* 接收消息緩沖區 */TickType_t xTicksToWait); /* 如果消息隊列為空,等待超時時間 */BaseType_t xQueueReceiveFromISR(QueueHandle_t xQueue, /* 消息隊列 */void* pvBuffer, /* 接收消息緩沖區 */BaseType_t pxHigherPriorityTaskWoken); /* 消息接收后,是否有更高級別的任務就緒 */消息隊列接收函數
- 第 1 個參數是消息隊列句柄。
- 第 2 個參數消息接收地址,每次接收都是將消息隊列創建函數 xQueueCreate 所指定的單個消息大
小復制到消息接收地址中。 - 在任務中 第 3 個參數是當消息隊列為空時,等待消息隊列有消息的最大等待時間,單位系統時鐘節拍。
- 在中斷中 第 3 個參數是消息接收后,是否有更高級別的任務就緒,如果有更高級別任務就緒(消息隊列已滿,且有優先級更高的任務堵塞在消息發送上,這里接收了消息,導致該任務從堵塞態轉變為就緒態),則pxHigherPriorityTaskWoken變為pdTRUE,然后在中斷結束處調用taskYIELD()進行任務調度。
- 返回值, 如果接到到消息返回 pdTRUE,否則返回 pdFALSE。
使用消息隊列函數要注意以下問題:
消息隊列覆蓋式發送
BaseType_t xQueueOverWrite(QueueHandle_t xQueue, /* 消息隊列 */const void* pvItemToQueue); /* 要發送消息地址 */BaseType_t xQueueOverWriteFromISR(QueueHandle_t xQueue, /* 消息隊列 */const void* pvItemToQueue, /* 要發送消息地址 */BaseType_t *pxHigherPriorityTaskWoken); /* 消息發送后,是否有更高級別的任務就緒 */消息隊列覆蓋式發送函數
- 第 1 個參數是消息隊列句柄。
- 第 2 個參數要傳遞數據地址,每次發送都是將消息隊列創建函數 xQueueCreate 所指定的單個消息大
小復制到消息隊列空間中。 - 在中斷中 第 3 個參數是消息發送后,是否有更高級別的任務就緒,如果有更高級別任務就緒(優先級更高的任務堵塞在消息接收上,這里發送了消息,導致任務從堵塞態轉變為就緒態),則pxHigherPriorityTaskWoken變為pdTRUE,然后在中斷結束處調用taskYIELD()進行任務調度。
- 返回值, 只返回 pdTRUE
使用消息隊列函數要注意以下問題:
消息隊列消息預讀取
BaseType_t xQueuePeek(QueueHandle_t xQueue,void *pvBuffer,TickType_t xTicksToWait);BaseType_t xQueuePeekFromISR(QueueHandle_t xQueue,void *pvBuffer);消息隊列預讀取函數
- 第 1 個參數是消息隊列句柄。
- 第 2 個參數消息接收地址,每次接收都是將消息隊列創建函數 xQueueCreate 所指定的單個消息大
小復制到消息接收地址中。 - 在任務中 第 3 個參數是當消息隊列為空時,等待消息隊列有消息的最大等待時間,單位系統時鐘節拍。
- 返回值, 如果接到到消息返回 pdTRUE,否則返回 pdFALSE。
使用消息隊列預讀取函數要注意以下問題:
獲取消息隊列消息個數
/* 獲取消息隊列中可用消息個數 */ UBaseType_t uxQueueMessagesWaiting(const QueueHandle_t xQueue); UBaseType_t uxQueueMessagesWaitingFromISR(const QueueHandle_t xQueue);/* 獲取消息隊列剩余空間 */ UBaseType_t uxQueueSpacesAvailable( const QueueHandle_t xQueue );/* 獲取消息隊列是否為空 */ BaseType_t xQueueIsQueueEmptyFromISR( const QueueHandle_t pxQueue );/* 獲取消息隊列是否已滿 */ BaseType_t xQueueIsQueueFullFromISR( const QueueHandle_t pxQueue );消息隊列集
隊列集提供了一種機制,允許RTOS任務同時阻止(掛起)來自多個RTOS隊列或信號量的讀取操作。
/* 創建消息隊列集 參數:uxEventQueueLength 隊列設置存儲在集合中包含的隊列和信號量上的事件。 uxEventQueueLength指定一次可以排隊的最大事件數。為了絕對確定事件沒有丟失,必須將uxEventQueueLength設置為添加到集合的隊列長度的總和,其中二進制信號量和互斥量的長度為1,計數信號量的長度由其最大計數值設置。例如:如果隊列集要保存長度為5的隊列,另一個長度為12的隊列和一個二進制信號量,則uxEventQueueLength應設置為(5 + 12 + 1)。如果隊列集要保存三個二進制信號量,則uxEventQueueLength應設置為(1 + 1 + 1)。如果隊列集要保存最大計數為5的計數信號量,以及最大計數為3的計數信號量,則uxEventQueueLength應設置為(5 + 3)。 返回:如果成功創建了隊列集,則返回創建的隊列集的句柄。否則返回NULL。*/ QueueSetHandle_t xQueueCreateSet( const UBaseType_t uxEventQueueLength );/* 將消息隊列或者信號量添加到消息隊列集中 */ BaseType_t xQueueAddToSet( QueueSetMemberHandle_t xQueueOrSemaphore,QueueSetHandle_t xQueueSet );/* 獲取消息隊列集中哪一個IPC接收到了信號 */ QueueSetMemberHandle_t xQueueSelectFromSet( QueueSetHandle_t xQueueSet,const TickType_t xTicksToWait );QueueSetMemberHandle_t xQueueSelectFromSetFromISR( QueueSetHandle_t xQueueSet );先使用xQueueCreateSet()創建隊列集,然后使用xQueueAddToSet()將標準FreeRTOS隊列和信號量添加到集合中。最后使用xQueueSelectFromSet()來確定集合中包含的隊列或信號量中的哪一個(如果有)處于隊列讀取或信號量獲取操作成功的狀態。
注意:
將隊列和信號量添加到隊列集時,它們必須為空。
添加到隊列集的每個隊列中的每個空間都需要額外的4個字節的RAM。因此,不應將最大計數值較高的計數信號量添加到隊列集。
本文參考 freertos官方文檔 https://freertos.org/a00110.html
《安富萊 STM32-V6 開發板 FreeRTOS 教程》
總結
以上是生活随笔為你收集整理的freeRtos学习笔(4)消息队列的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: freeRtos学习笔(3)临界区管理
- 下一篇: freeRtos学习笔记 (5)事件组