原文地址:http://www.cnblogs.com/god-of-death/p/6917837.htmlhtml
用於任務之間的同步,即一個任務 give token,另外一個任務 take token數組
特別提醒:函數
因爲中斷服務函數越短越好(處理時間越短越好),把關鍵處理放中斷服務函數,其餘放到外面,外面能夠是一個任務(靈活性大,由於會用到二值信號量或計數信號量,須要爲每一個信號量建立一個任務,耗用資源多),也能夠是定時器守護任務的回調函數xTimerPendFunctionCallFromISR()(定時器守護任務使用到一個命令隊列,只要向隊列發送信號就能夠執行相應代碼,因此能夠實現「中斷推遲處理」功能;只用到定時器守護任務這一個任務,節省資源,但建議回調函數執行時間短一些,不然影響其餘定時器回調函數的執行週期)spa
任務通知優勢:更快、佔用RAM少htm
任務通知缺點:數據不能從任務發送到ISR(也就是ISR中不能讀取任務通知);接收處理任務通知只能在本任務中;任務通知只能經過32位無符號整數傳遞數據;當任務爲「pending」,發送任務通知API不會等待任務變爲「not-pending」而阻塞,也就是數據可能丟失blog
任務狀態:接收到通知爲處理爲「pending」,讀取通知值狀態變爲「not-pending」遞歸
xTaskNotifyGive() 是xTaskNotify() 的閹割版token
ulTaskNotifyTake() 是xTaskNotifyWait() 的閹割版
隊列
調用發送函數產生的影響:事件
調用xTaskNotifyGive()後,通知值加一,ucNotifyState變爲"pending"
調用xTaskNotify()後,通知值能夠不變、指定位置1、加1、強制重寫通知值或者ucNotifyState爲"not-pending"狀態時寫通知值,ucNotifyState變爲"pending"。第三個參數若是是eSetBits ,是使 notification value 的某一位置一,能夠同時對notification value 的某幾位置一,而後同時處理幾件事情;若是第三個參數是eSetValueWithOverwrite ,是設置 notification value 爲某個值。
接收函數如何判斷是否接收到未讀通知:
ulTaskNotifyTake()判斷是否有未讀通知是根據通知值ulNotifiedValue是否爲零,該函數能夠實現通知值減一或清零。相對來講,該函數實現主要是針對信號量那種類型(xClearCountOnExit 爲pdTRUE替代二值信號量;爲pdFALSE替代計數信號量);
xTaskNotifyWait()判斷是否有通知是依據通知狀態ucNotifyState, 該函數能夠實現清除指定位。這裏,通知值纔算真正承載了有用的通知內容。
使用互斥可能出現的問題:
一、互斥可能會致使高優先級任務等待低優先級任務,以下圖:
二、也可能致使互鎖,兩個任務都各自持有對方想要的互斥信號,致使兩個任務都沒法進行,因此建議任務等待互斥信號的時間不要無限長,超時能夠作一些處理,能夠發現死鎖狀況
三、也可能致使自鎖,好比某個函數對任務進行遞歸調用;能夠經過遞歸互斥(recursive mutexes)解決
四、也可能某個任務一直沒執行,以下圖,可是能夠經過調用taskYIELD() 解決
互斥量是爲了保護「打印機」類型的事件不被破壞,看門人任務和隊列或者計數信號量配合也能夠實現這個功能,具體就是隻有看門人任務能夠直接使用「打印機」,看門人任務大多時間阻塞等待打印數據到來,任何其餘任務想使用打印機只能向看門人任務發送打印數據
可使用的API以下:
一、taskDISABLE_INTERRUPTS() 和 taskENABLE_INTERRUPTS()
屏蔽可屏蔽中斷,包括調度器也不能工做(即不能任務切換,由於調度器也是基於中斷),保證某個代碼段不被打斷的執行;可是不支持嵌套(即若是調用了兩個DISABLE,調用一個ENABLE也可使中斷正常工做,嵌套的意思是一對DISABLE和ENABLE裏面包含了其餘對DISABLE和ENABLE);當調度器掛起,FreeRTOS API不能夠被調用
二、taskENTER_CRITICAL() 和 taskEXIT_CRITICAL()
和1的區別就是支持嵌套,即調用了幾個ENTER,就要調用幾個EXIT才能使能中斷;當調度器掛起,FreeRTOS API不能夠被調用
三、vTaskSuspendAll() 和 xTaskResumeAll()
只是不能進行任務切換,可是沒有屏蔽中斷;1和2不只不能任務切換,還不能響應中斷;當調度器掛起,FreeRTOS API不能夠被調用
一、不一樣於二值信號量和計數信號量,隊列的原理是FIFO,能夠存放數據
二、建立隊列時隊列的元素個數和元素的類型就已經肯定了,只能往隊列存放規定的元素類型
三、能夠建立隊列集合,隊列集合裏面能夠放隊列、計數信號量或二值信號量,使用隊列集合適用於多個任務向某個任務發送數據,而數據類型不相同,不一樣數據類型的數據存放在不一樣的隊列集合成員裏。
四、隊列能夠實現郵箱功能,即多個任務能夠讀取長度爲1的隊列裏的數據,但不會清除數據,即便隊列有數據但沒有更新,調用xQueuePeek()也不會阻塞;任務往此隊列寫數據是覆蓋裏面的數據。適用於向多個任務發送數據,即一對多通訊,即廣播。
事件組能夠用於某個任務等待幾個條件都知足或某個條件知足才解除阻塞的情景(多個發送,一個接收,即多對一通訊),或者幾個任務互相等待條件知足才進一步執行任務,好比task A,B,C須要進一步執行各自的任務,須要task A,B,C都知足條件(多個發送,多個接收,即多對多通訊)。
調用這個函數xEventGroupSetBitsFromISR() ,實際是在定時器守護任務中執行,說有configUSE_TIMERS 和 INCLUDE_xTimerPendFunctionCall 須要置一
若是單片機的RAM比較小,分配給FreeRTOS的heap比較少,可使用內存動態申請pvPortMalloc定義大數組,從而減少分配給任務棧的大小