UCOSIII學習(?)消息傳遞

有時候一個任務要和另外一個或者幾個任務進行“交流”,這個“交流”就是消息的傳遞,
也稱之爲任務間通信,在 UCOSIII 中消息可以通過消息隊列作爲中介發佈給任務,也可以直接
發佈給任務

消息隊列

消息一般包含:指向數據的指針,表明數據長度的變量和記錄消息發佈時刻的時間戳,指針指向的可以是一塊數據區或者甚至是一個函數,消息的內容必須一直保持可見性,因爲發佈數據採用的是引用傳遞是指針傳遞而不是值傳遞,也就說,發佈的數據本身不產生數據拷貝。

在 UCOSIII 中對於消息隊列的讀取既可以採用先進先出(FIFO)的方式,也可以採用後進先出(LIFO)的方式。當任務或者中斷服務程序需要向任務發送一條緊急消息時 LIFO 的機制就非常有用了。採用後進先出的方式,發佈的消息會繞過其他所有的已經位於消息隊列中的消息而最先傳遞給任務。

消息隊列中有一個列表,記錄了所有正在等待獲得消息的任務,如圖 11.1.2 所示爲多個任務可以在一個消息隊列中等待,當一則消息被髮布到隊列中時,最高優先級的等待任務將獲得該消息,發佈方也可以向消息隊列中所有等待的任務廣播一則消息。
在這裏插入圖片描述

消息隊列相關函數

創建消息隊列

void OSQCreate (OS_Q *p_q,
				CPU_CHAR *p_name,
				OS_MSG_QTY max_qty,
				OS_ERR *p_err)

p_q : 指向一個消息隊列,消息隊列的存儲空間必須由應用程序分配,我們採用如下的語句定義一個消息隊列。
OS_Q Msg_Que;
p_name : 消息隊列的名字。
max_qty : 指定消息隊列的長度,必須大於 0。當然,如果 OS_MSGs 緩衝池中沒有足夠多的 OS_MSGs 可用,那麼發送消息將會失敗,並且返回相應的錯誤碼,指明當前沒有可用的 OS_MSGs
p_err : 保存調用此函數後返回的錯誤碼

等待消息隊列

當一個任務想要從消息隊列中接收一個消息的話就需要使用函數 OSQPend()

void *OSQPend (OS_Q *p_q,
			   OS_TICK timeout,
               OS_OPT opt,
               OS_MSG_SIZE *p_msg_size,
               CPU_TS *p_ts,
               OS_ERR *p_err)

p_q : 指向一個消息隊列。
timeout : 等待消息的超時時間,如果在指定的時間沒有接收到消息的話,任務就會被喚醒,接着運行。這個參數也可以設置爲 0,表示任務將一直等待下去,直到接收到消息。
opt : 用來選擇是否使用阻塞模式,有兩個選項可以選擇。
OS_OPT_PEND_BLOCKING 如果沒有任何消息存在的話就阻塞任務,一直等待,直到接收到消息。
OS_OPT_PEND_NON_BLOCKING 如果消息隊列沒有任何消息的話任務就直接返回。
p_msg_size: 指向一個變量用來表示接收到的消息長度(字節數)。
p_ts : 指向一個時間戳,表明什麼時候接收到消息。如果這個指針被賦值爲NULL的話,說明用戶沒有要求時間戳。
p_err : 用來保存調用此函數後返回的錯誤碼。

如果消息隊列中沒有任何消息,並且參數 opt 爲 OS_OPT_PEND_NON_BLOCKING 時,那麼調用 OSQPend()函數的任務就會被掛起,直到接收到消息或者超時。如果有消息發送給消息隊列,但是同時有多個任務在等待這個消息,那麼UCOSIII將恢復等待中的最高優先級的任務。

向消息隊列發送消息

可以通過函數 OSQPost()向消息隊列發送消息

void OSQPost (OS_Q *p_q,
			  void *p_void,
			  OS_MSG_SIZE msg_size,
			  OS_OPT opt,
			  OS_ERR *p_err)

如果有多個任務在等待消息隊列的話,那麼優先級最高的任務將獲得這個消息。如果等待消息的任務優先級比發送消息的任務優先級高,則系統會執行任務調度,等待消息的任務立即恢復運行,而發送消息的任務被掛起。可以通過 opt 設置消息隊列是 FIFO 還是 LIFO。
如果有多個任務在等待消息隊列的消息,則 OSQPost()函數可以設置僅將消息發送給等待任務中優先級最高的任務(opt 設置爲 OS_OPT_POST_FIF 或者 OS_OPT_POST_LIFO),也可以將消息發送給所有等待的任務 (opt 設置爲 OS_OPT_POST_ALL)。 如果 opt 設置爲OS_OPT_POST_NO_SCHED,則在發送完消息後,會進行任務調度。
p_q : 指向一個消息隊列。
p_void : 指向實際發送的內容,p_void 是一個執行 void 類型的指針,其具體含義由用戶程序的決定。
msg_size : 設定消息的大小,單位爲字節數。
opt : 用來選擇消息發送操作的類型,基本的類型可以有下面四種。
OS_OPT_POST_ALL 將消息發送給所有等待該消息隊列的任務,需要和選項 OS_OPT_POST_FIFO 或者
OS_OPT_POST_LIFO 配合使用。
OS_OPT_POST_FIFO 待發送消息保存在消息隊列的末尾
OS_OPT_POST_LIFO 待發送的消息保存在消息隊列的開頭
OS_OPT_POST_NO_SCHED 禁止在本函數內執行任務調度。
我們可以使用上面四種基本類型來組合出其他幾種類型,如下:
OS_OPT_POST_FIFO + OS_OPT_POST_ALL
OS_OPT_POST_LIFO + OS_OPT_POST_ALL
OS_OPT_POST_FIFO + OS_OPT_POST_NO_SCHED
OS_OPT_POST_LIFO + OS_OPT_POST_NO_SCHED
OS_OPT_POST_FIFO + OS_OPT_POST_ALL + OS_OPT_POST_NO_SCHED
OS_OPT_POST_LIFO + OS_OPT_POST_ALL + OS_OPT_POST_NO_SCHED
p_err : 用來保存調用此函數後返回的錯誤碼

發佈了74 篇原創文章 · 獲贊 65 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章