在中斷服務例程中使用佇列,
選擇在中斷回呼函式中填充帶有中斷模式的佇列,
API
xQueueSendToFrontFromISR();
xQueueSendToBackFromISR();
xQueueReceiveFromISR();
專門用于中斷服務例程
信號量用于事件通信,而佇列不僅可以用于事件通信,還可以用來傳遞資料,
parameters 佇列句柄,訊息指標,是否切換調度更到任務優先級的任務
由于在創建佇列時設定了佇列中資料單元的長度,所以會從該指標指向的空間復制對應長度的資料到佇列的存盤區域,所以是拷貝傳遞!
當佇列已滿而無法將資料寫入時,則回傳errQUEUE_FULL
所以在填充佇列時需要進行檢驗
兩種高效佇列讀取串口模型
- 將接收到的字符先快取在記憶體中,當接收到一個傳輸完成訊息,或是檢測到傳輸完成后,使用信號量讓某個任務解除阻塞,這個任務將對資料快取進行處理,
- 在中斷服務中直接決議收到的字符,然后通過佇列將決議后的命令發送到處理任務中,
多任務系統中由于競爭存在死鎖的風險,訪問外設、讀-改-寫操作、變數的非原子訪問、函式重入
更新結構體的多個成員變數,或是更新的變數的長度超過了架構體系的自然長度均是非原子操作,
每個任務都單獨維護自己的堆疊空間以及自身在處理器內核中暫存器組中的值,保護背景關系,但是如果一個函式除了訪問自己堆疊空間上分配的資料或者處理器內核暫存器中的資料外,不能去訪問其他任何記憶體,那么這個函式就是可重入的!!!
互斥的關鍵就是需要考慮這片記憶體是否會被多任務共享!
當訪問一個被多任務共享,或是被任務與中斷共享的資源時,需要采用互斥來保證資料在任何時候都要保持一致性,這樣做的目的是要確保任務從開始訪問資源就具有排他性,直至這個資源有恢復到完整狀態,
FreeRTOS 提供了多種特性來實作互斥,
基本臨界區
taskENTER_CRITICAL()、taskEXIT_CRITCAL()
之間的代碼被保護成為臨界區間,只有一個入口!
用法
taskENTER_CRITICAl();
xxxxxxx
xxxxxx 需要保護的操作或資源
xxxxxxx
taskEXIT_CRITCAL();
一個典型例子,如果是使用串口輸出除錯資訊,需要保護串口重入函式,
臨界區必須只具有很短的時間,臨界區是可以嵌套的,因為FreeRTOS 內核維護一個嵌套深度計數器,只有當遞回退出時,才可以真正的退出臨界區!
掛起調度器
也可以通過掛起調度器來創建臨界區,通過這種方式創建的被保護區間是不能被其他任務打斷,但是可以被中斷打斷,
但是開關調度器需要一定開銷!
API
vTaskSuspendAll(void) 掛起調度器
portBASE_TYPE vTaskResumeAll(void) 喚醒調度器
注意:
當一個中斷服務在調度器掛起程序中請求背景關系
切換,那么這個請求將被掛起,直到調度器被喚醒 后才會執行,在調度器處于掛起時,不能呼叫任何 FreeRTOS API
互斥量及二值信號量
互斥量是一種特殊的二值信號量,用于控制在兩個或多個任務之間訪問共享資源,一個任務只有獲得了相應的互斥鎖才可以合法的去訪問共享資源,否則是堅決不允許去訪問,
用于互斥的信號量必須歸還;
用于同步的信號量通常是完成同步之后便丟棄,不用歸還!
API
xSemaphoreCreateMutex()
FreeRTOS 中所有種類的信號量的句柄都保存在型別為 xSemaphoreHandle 的變數中
互斥量在使用前必須先創建,
創建失敗回傳
否則回傳互斥量句柄
有時候我們回創建多個優先級不同的任務,所以在運行時低優先級的任務會被高優先級的任務搶占,但是使用互斥量可以保證調度器不會打斷低優先級的任務訪問共享資源,
優先級繼承只是暫時地將互斥量持有者的優先級提升為所有等待此互斥量的任務中優先級最高的那個級別,因此被稱為優先級繼承,
當多個互斥量存在時,死鎖風險提升!!!
守護任務
守護任務提供了一種干凈利落的方法來實作互斥功能,
守護任務是對某個資源具有唯一所有權的任務,只有守護任務才可以直接訪問其守護的資源---其它任務要想訪問該資源只能間接地通過守護任務提供的服務,
在創建 FreeRTOS_Inti 中創建佇列時,系統內核還沒有運行起來,不能使用同步手段!
采用 臨界區手段 來保護最頂層的 PWM 設定呼叫!
創建一個臨界區使用系統鎖關閉調度和中斷!
資料傳輸 BUG 當第一個位元組保存 01 時 沒有辦法拷貝 !!!記憶體訪問的問題!
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/24361.html
標籤:C
上一篇:2.安裝Visual Studio插件Visual Assist
下一篇:【物體移動_C語言版】【持續更新】