描述
消息 傳遞是線程之間的另一種基本通信模型。在消息傳遞模型中,一個線程顯式發送數據,而另一個線程接收數據。該操作更像是某種I / O,而不是直接訪問要共享的信息。在CMSIS-RTOS中,此機制稱爲s 消息 隊列。數據以類似FIFO的操作從一個線程傳遞到另一個線程。使用消息隊列功能,您可以控制,發送,接收或等待消息。要傳遞的數據可以是整數或指針類型:
與內存池相比,消息隊列通常效率較低,但是可以解決更廣泛的問題。有時,線程沒有公共的地址空間,或者共享內存的使用引發了諸如互斥之類的問題。
注意:
可以從中斷服務例程中調用函數osMessageQueuePut,osMessageQueueGet,osMessageQueueGetCapacity,osMessageQueueGetMsgSize,osMessageQueueGetCount,osMessageQueueGetSpace。
有關RTX5配置選項, 請參閱消息隊列配置。
數據結構
/// /消息隊列結構體.
typedef struct {
const char *name; ///< 消息隊列的名稱
uint32_t attr_bits; ///< 屬性位
void *cb_mem; ///< 控制塊內存
uint32_t cb_size; ///< 爲控制塊提供的內存大小
void *mq_mem; ///< 用於數據存儲的內存
uint32_t mq_size; ///< 爲數據存儲提供的內存大小
} osMessageQueueAttr_t;
主要函數API解析
1.創建並初始化消息隊列對象。
osMessageQueueId_t osMessageQueueNew(
uint32_t msg_count,
uint32_t msg_size,
const osMessageQueueAttr_t * attr
)
參數:
[in] msg_count 隊列中的最大消息數。 [in] msg_size 最大消息大小(以字節爲單位)。 [in] attr 消息隊列屬性;NULL:默認值。
返回值:
消息隊列ID以供其他功能參考,如果出錯,則爲NULL。
函數osMessageQueueNew創建並初始化消息隊列對象。如果發生錯誤,該函數將返回消息隊列對象標識符或NULL。
在內核使用osKernelInitialize初始化之後,可以調用該函數。在使用osKernelStart啓動RTOS內核之前,可以創建消息隊列對象。
消息隊列數據所需的內存總量至少爲msg_count * msg_size。所述msg_size被向上舍入到雙偶數,確保存儲塊的32位對齊。
從消息隊列分配的內存塊具有使用參數定義的固定大小msg_size。
注意:
不能從中斷服務程序中調用此函數。
代碼示例:
請參考 osMessageQueuePut();
2.獲取消息隊列對象的名稱。
const char * osMessageQueueGetName(osMessageQueueId_t mq_id)
參數:
mq_id 爲 osMessageQueueNew()獲得的消息隊列ID 。
返回值:
名稱爲以null終止的字符串。
出現錯誤時,函數osMessageQueueGetName返回指向由參數mq_id或NULL標識的消息隊列的名稱字符串的指針。
注意:
不能從中斷服務程序中調用此函數。
3.消息放入隊列
osStatus_t osMessageQueuePut(
osMessageQueueId_t mq_id,
const void * msg_ptr,
uint8_t msg_prio,
uint32_t timeout
)
參數:
[in] mq_id osMessageQueueNew獲得的消息隊列ID 。 [in] msg_ptr 指向要放入隊列的消息的緩衝區的指針。 [in] msg_prio 消息優先級。 [in] timeout 超時值;如果沒有超時,則爲 0。
返回值:
狀態代碼,指示功能的執行狀態。
阻塞函數osMessageQueuePut將msg_ptr指向的消息放入參數mq_id指定的消息隊列中。參數msg_prio用於根據插入時消息的優先級(數字越高表示優先級越高)對消息進行排序。
參數timeout指定系統等待將消息放入隊列的時間。在系統等待時,正在調用此函數的線程進入BLOCKED狀態。
參數超時可以具有以下值:
- 當timeout爲0時,該函數立即返回(即嘗試語義)。
- 當超時設置爲osWaitForever時,該函數將等待無限的時間,直到消息被傳遞爲止(即,等待語義)。
- 所有其他值在內核滴答中指定一個超時時間(即,定時等待語義)。
可能的osStatus_t返回值:
- osOK:消息已放入隊列。
- osErrorTimeout:無法在給定的時間內將消息放入隊列(等待定時的語義)。
- osErrorResource:隊列中沒有足夠的空間(嘗試語義)。
- osErrorParameter:參數mq_id爲NULL或ISR中指定的無效非零超時。
注意:
如果參數超時設置爲0,則可以從中斷服務例程中調用。
代碼示例:
#include "cmsis_os2.h" // CMSIS RTOS header file
/*----------------------------------------------------------------------------
* Message Queue creation & usage
*---------------------------------------------------------------------------*/
#define MSGQUEUE_OBJECTS 16 // number of Message Queue Objects
typedef struct // object data type
{
uint8_t Buf[32];
uint8_t Idx;
} MSGQUEUE_OBJ_t;
osMessageQueueId_t mid_MsgQueue; // message queue id
osThreadId_t tid_Thread_MsgQueue1; // thread id 1
osThreadId_t tid_Thread_MsgQueue2; // thread id 2
void Thread_MsgQueue1(void *argument); // thread function 1
void Thread_MsgQueue2(void *argument); // thread function 2
int Init_MsgQueue(void)
{
mid_MsgQueue = osMessageQueueNew(MSGQUEUE_OBJECTS, sizeof(MSGQUEUE_OBJ_t), NULL);
if (mid_MsgQueue == NULL)
{
; // Message Queue object not created, handle failure
}
tid_Thread_MsgQueue1 = osThreadNew(Thread_MsgQueue1, NULL, NULL);
if (tid_Thread_MsgQueue1 == NULL)
{
return (-1);
}
tid_Thread_MsgQueue2 = osThreadNew(Thread_MsgQueue2, NULL, NULL);
if (tid_Thread_MsgQueue2 == NULL)
{
return (-1);
}
return (0);
}
void Thread_MsgQueue1(void *argument)
{
MSGQUEUE_OBJ_t msg;
while (1)
{
; // Insert thread code here...
msg.Buf[0] = 0x55U; // do some work...
msg.Idx = 0U;
osMessageQueuePut(mid_MsgQueue, &msg, 0U, 0U);
osThreadYield(); // suspend thread
}
}
void Thread_MsgQueue2(void *argument)
{
MSGQUEUE_OBJ_t msg;
osStatus_t status;
while (1)
{
; // Insert thread code here...
status = osMessageQueueGet(mid_MsgQueue, &msg, NULL, 0U); // wait for message
if (status == osOK)
{
; // process data
}
}
}
4.從隊列中獲取消息
osStatus_t osMessageQueueGet(
osMessageQueueId_t mq_id,
void *msg_ptr,
uint8_t *msg_prio,
uint32_t timeout
)
參數:
[in] mq_id osMessageQueueNew獲得的消息隊列ID 。 [out] msg_ptr 指向從隊列中獲取消息的緩衝區的指針。 [out] msg_prio 指向消息優先級或NULL的緩衝區的指針。 [in] timeout 超時值;如果沒有超時,則爲 0。
返回值:
狀態代碼,指示功能的執行狀態。
函數osMessageQueueGet從參數mq_id指定的消息隊列中檢索一條消息,並將其保存到參數msg_ptr指向的緩衝區中。如果不是令牌{NULL},則消息優先級存儲到參數msg_prio。
參數timeout指定系統等待從隊列中檢索消息的時間。在系統等待時,正在調用此函數的線程進入BLOCKED狀態。
參數超時可以具有以下值:
- 當timeout爲0時,該函數立即返回(即嘗試語義)。
- 當超時設置爲osWaitForever時,該函數將等待無限的時間,直到檢索到消息爲止(即,等待語義)。
- 所有其他值在內核滴答中指定一個超時時間(即,定時等待語義)。
可能的osStatus_t返回值:
- osOK:已從隊列中檢索到消息。
- osErrorTimeout:在給定的時間內無法從隊列中檢索消息(定時等待語義)。
- osErrorResource:從隊列中什麼也得不到(嘗試語義)。
- osErrorParameter:參數mq_id爲NULL或ISR中指定的無效非零超時。
注意:
如果參數超時設置爲0,則可以從中斷服務例程中調用。
代碼示例:
請參考osMessageQueuePut
5.獲取消息隊列中的最大消息數
uint32_t osMessageQueueGetCapacity(osMessageQueueId_t mq_id)
參數:
[in] mq_id osMessageQueueNew獲得的消息隊列ID 。
返回值:
最大消息數。
函數osMessageQueueGetCapacity返回錯誤消息中由參數mq_id指定的消息隊列對象中的最大消息數或0。
注意:
可以從中斷服務程序中調用此函數。
6.獲取內存池中的最大消息大小
uint32_t osMessageQueueGetMsgSize(osMessageQueueId_t mq_id)
參數:
[in] mq_id osMessageQueueNew獲得的消息隊列ID 。
返回值:
最大消息大小(以字節爲單位)。
函數osMessageQueueGetMsgSize返回錯誤消息中由參數mq_id指定的消息隊列對象的最大消息大小(以字節爲單位)或0。
注意:
可以從中斷服務程序中調用此函數。
7.獲取消息隊列中排隊的消息數
uint32_t osMessageQueueGetCount (osMessageQueueId_t mq_id)
參數:
[in] | mq_id | osMessageQueueNew獲得的消息隊列ID 。 |
返回值:
排隊的消息數。
該函數osMessageQueueGetCount返回排隊的消息在由參數指定的消息隊列對象的數目mq_id或0中的錯誤的情況下。
注意:
可以從中斷服務程序中調用此函數
8.獲取消息隊列中消息的可用插槽數
uint32_t osMessageQueueGetSpace(osMessageQueueId_t mq_id)
參數:
[in] mq_id osMessageQueueNew獲得的消息隊列ID 。
返回值:
消息的可用插槽數。
該函數osMessageQueueGetSpace返回數字可用時隙用於在由參數指定的消息隊列對象消息mq_id或0中的錯誤的情況下。
注意
可以從中斷服務程序中調用此函數。
9.將消息隊列重置爲初始空狀態
osStatus_t osMessageQueueReset(osMessageQueueId_t mq_id)
參數:
[in] mq_id osMessageQueueNew獲得的消息隊列ID 。
返回值:
狀態代碼,指示功能的執行狀態。
函數osMessageQueueReset重置由參數mq_id指定的消息隊列。
可能的osStatus_t返回值:
- osOK:消息隊列已停止。
- osErrorParameter:參數mq_id爲NULL或無效。
- osErrorResource:消息隊列處於無效狀態。
- osErrorISR: 不能從中斷服務例程中調用osMessageQueueReset。
注意
不能從中斷服務程序中調用此函數。
10.刪除消息隊列對象
osStatus_t osMessageQueueDelete (osMessageQueueId_t mq_id)
參數:
[in] mq_id osMessageQueueNew獲得的消息隊列ID 。
返回值:
狀態代碼,指示功能的執行狀態。
函數osMessageQueueDelete刪除由參數mq_id指定的消息隊列對象。它釋放爲消息隊列處理而獲得的內部存儲器。調用之後,mq_id不再有效,無法使用。可以使用osMessageQueueNew函數再次創建消息隊列。
可能的osStatus_t返回值:
- osOK:消息隊列對象已被刪除。
- osErrorParameter:參數mq_id爲NULL或無效。
- osErrorResource:消息隊列處於無效狀態。
- osErrorISR: 不能從中斷服務例程中調用osMessageQueueDelete。
注意
不能從中斷服務程序中調用此函數。