FreeRTOS任務(wù)通知 基于STM32
一、任務(wù)通知簡介
FreeRTOS 從 V8.2.0 版本開始提供任務(wù)通知這個功能,每個任務(wù)都有一個 32 位的通知 值,在大多數(shù)情況下,任務(wù)通知可以替代二值信號量、計數(shù)信號量、事件組,也可以替代 長度為 1 的隊列(可以保存一個 32位整數(shù)或指針值)。
相對于以前使用 FreeRTOS 內(nèi)核通信的資源,必須創(chuàng)建隊列、二進(jìn)制信號量、計數(shù)信 號量或事件組的情況,使用任務(wù)通知顯然更靈活。
按照 FreeRTOS 官方的說法,使用任務(wù) 通知比通過信號量等 ICP 通信方式解除阻塞的任務(wù)要快 45%,并且更加省 RAM 內(nèi)存空間 (使用 GCC 編譯器,-o2 優(yōu)化級別),任務(wù)通知的使用無需創(chuàng)建隊列。想要使用任務(wù)通知, 必須將 FreeRTOSConfig.h 中的宏定義
configUSE_TASK_NOTIFICATIONS 設(shè)置為 1,其實 FreeRTOS 默認(rèn)是為 1 的,所以任務(wù)通知是默認(rèn)使能的。
FreeRTOS 提供以下幾種方式發(fā)送通知給任務(wù) :
發(fā)送通知給任務(wù), 如果有通知未讀,不覆蓋通知值。
發(fā)送通知給任務(wù),直接覆蓋通知值。
發(fā)送通知給任務(wù),設(shè)置通知值的一個或者多個位,可以當(dāng)做事件組來使用。
發(fā)送通知給任務(wù),遞增通知值,可以當(dāng)做計數(shù)信號量使用。 通過對以上任務(wù)通知方式的合理使用,可以在一定場合下替代 FreeRTOS 的信號量, 隊列、事件組等。
當(dāng)然,凡是都有利弊,不然的話 FreeRTOS 還要內(nèi)核的 IPC 通信機(jī)制干嘛,消息通知 雖然處理更快,RAM 開銷更小,但也有以下限制 :
只能有一個任務(wù)接收通知消息,因為必須指定接收通知的任務(wù)。。
只有等待通知的任務(wù)可以被阻塞,發(fā)送通知的任務(wù),在任何情況下都不會因為發(fā) 送失敗而進(jìn)入阻塞態(tài)。
二、任務(wù)通知的運作機(jī)制
顧名思義,任務(wù)通知是屬于任務(wù)中附帶的資源,所以在任務(wù)被創(chuàng)建的時候,任務(wù)通知 也被初始化的,而在分析隊列和信號量的章節(jié)中,我們知道在使用隊列、信號量前,必須 先創(chuàng)建隊列和信號量,目的是為了創(chuàng)建隊列數(shù)據(jù)結(jié)構(gòu)。
比如使用 xQueueCreate()函數(shù)創(chuàng)建 隊列,用 xSemaphoreCreateBinary()函數(shù)創(chuàng)建二值信號量等等。再來看任務(wù)通知,由于任務(wù) 通知的數(shù)據(jù)結(jié)構(gòu)包含在任務(wù)控制塊中,只要任務(wù)存在,任務(wù)通知數(shù)據(jù)結(jié)構(gòu)就已經(jīng)創(chuàng)建完畢, 可以直接使用,所以使用的時候很是方便。
任務(wù)通知可以在任務(wù)中向指定任務(wù)發(fā)送通知,也可以在中斷中向指定任務(wù)發(fā)送通知, FreeRTOS 的每個任務(wù)都有一個 32 位的通知值,任務(wù)控制塊中的成員變量 ulNotifiedValue 就是這個通知值。
只有在任務(wù)中可以等待通知,而不允許在中斷中等待通知。如果任務(wù)在等待的通知暫時無效,任務(wù)會根據(jù)用戶指定的阻塞超時時間進(jìn)入阻塞狀態(tài),我們可以將等 待通知的任務(wù)看作是消費者;其它任務(wù)和中斷可以向等待通知的任務(wù)發(fā)送通知,發(fā)送通知 的任務(wù)和中斷服務(wù)函數(shù)可以看作是生產(chǎn)者,當(dāng)其他任務(wù)或者中斷向這個任務(wù)發(fā)送任務(wù)通知, 任務(wù)獲得通知以后,該任務(wù)就會從阻塞態(tài)中解除,這與 FreeRTOS 中內(nèi)核的其他通信機(jī)制 一致。
三、任務(wù)通知的函數(shù)接口講解
1. xTaskGenericNotify()
我們先看一下發(fā)送通知 API 函數(shù)。這類函數(shù)比較多,有 6 個。但仔細(xì)分析會發(fā)現(xiàn)它們 只能完成 3 種操作,每種操作有兩個 API 函數(shù),分別為帶中斷保護(hù)版本和不帶中斷保護(hù)版 本。FreeRTOS 將 API 細(xì)分為帶中斷保護(hù)版本和不帶中斷保護(hù)版本是為了節(jié)省中斷服務(wù)程 序處理時間,提升性能。
通過前面通信機(jī)制的學(xué)習(xí),相信大家都了解了 FreeRTOS 的風(fēng)格, 這里的任務(wù)通知發(fā)送函數(shù)也是利用宏定義來進(jìn)行擴(kuò)展的,所有的函數(shù)都是一個宏定義,在 任務(wù)中發(fā)送任務(wù)通知的函數(shù)均是調(diào)用 xTaskGenericNotify()函數(shù)進(jìn)行發(fā)送通知,xTaskGenericNotify()函數(shù)是一個通用的任務(wù)通知發(fā)送函數(shù),在任務(wù)中發(fā)送通知的 API 函 數(shù) , 如 xTaskNotifyGive() 、 xTaskNotify() ,xTaskNotifyAndQuery() , 都 是 以 xTaskGenericNotify()為原型的,只不過指定的發(fā)送方式不同而已。
2.xTaskNotifyGive()
xTaskNotifyGive()是一個宏,宏展開是調(diào)用函數(shù) xTaskNotify( ( xTaskToNotify ), ( 0 ), eIncrement ),即向一個任務(wù)發(fā)送通知,并將對方的任務(wù)通知值加 1。該函數(shù)可以作為二值 信號量和計數(shù)信號量的一種輕量型的實現(xiàn),速度更快,在這種情況下對象任務(wù)在等待任務(wù) 通 知 的 時 候 應(yīng) 該 是 使 用 函 數(shù) ulTaskNotifyTake() 而不是 xTaskNotifyWait() 。xTaskNotifyGive() 不 能 在 中 斷 里 面 使 用 , 而 是 使 用 具 有 中 斷 保 護(hù) 功 能 的 vTaskNotifyGiveFromISR()來代替。
xTaskNotifyGive()函數(shù)說明
xTaskNotifyGive()函數(shù)應(yīng)用舉例
static void prvTask1( void *pvParameters ); static void prvTask2( void *pvParameters ); /*定義任務(wù)句柄 */ static TaskHandle_t xTask1 = NULL, xTask2 = NULL; /* 主函數(shù):創(chuàng)建兩個任務(wù),然后開始任務(wù)調(diào)度 */ void main( void ) {
xTaskCreate(prvTask1, "Task1", 200, NULL, tskIDLE_PRIORITY, &xTask1);
xTaskCreate(prvTask2, "Task2", 200, NULL, tskIDLE_PRIORITY, &xTask2);
vTaskStartScheduler();
} /*-----------------------------------------------------------*/ static void prvTask1( void *pvParameters ) { for ( ;; ) { /* 向 prvTask2()發(fā)送一個任務(wù)通知,讓其退出阻塞狀態(tài) */ xTaskNotifyGive( xTask2 ); /* 阻塞在 prvTask2()的任務(wù)通知上
如果沒有收到通知,則一直等待*/ ulTaskNotifyTake( pdTRUE, portMAX_DELAY );
}
} /*-----------------------------------------------------------*/ static void prvTask2( void *pvParameters ) { for ( ;; ) { /* 阻塞在 prvTask1()的任務(wù)通知上
如果沒有收到通知,則一直等待*/ ulTaskNotifyTake( pdTRUE, portMAX_DELAY ); /* 向 prvTask1()發(fā)送一個任務(wù)通知,讓其退出阻塞狀態(tài) */ xTaskNotifyGive( xTask1 );
}
}
完整代碼可進(jìn)群免費領(lǐng)取!!!
嵌入式物聯(lián)網(wǎng)的學(xué)習(xí)之路非常漫長,不少人因為學(xué)習(xí)路線不對或者學(xué)習(xí)內(nèi)容不夠?qū)I(yè)而錯失高薪offer。不過別擔(dān)心,我為大家整理了一份150多G的學(xué)習(xí)資源,基本上涵蓋了嵌入式物聯(lián)網(wǎng)學(xué)習(xí)的所有內(nèi)容。點擊下方鏈接,0元領(lǐng)取學(xué)習(xí)資源,讓你的學(xué)習(xí)之路更加順暢!記得點贊、關(guān)注、收藏、轉(zhuǎn)發(fā)哦!
- 贊