freeRtos学习笔记 (7)信号量
freeRtos學習筆記
freeRtos信號量
信號量種類
信號量分為四種:二值信號量,互斥信號量,計數信號量和遞歸互斥信號量,其中計數信號量用于管理系統多個共享資源,用計數值表示可用資源數目;二值信號量是一種特殊的計數信號量,和事件組類似,相當于裸機中的標志位,常用于任務之間的同步;互斥信號量和二值信號量類似,相比二值信號量避免了任務優先級翻轉問題,因此常用來保護臨界資源,但是互斥信號量不可以在中斷中使用,只能在任務中使用;遞歸互斥信號量是一種特殊的互斥信號量,如果任務獲取到遞歸互斥信號量后,該任務中不需要等待遞歸互斥信號量釋放就可以再次獲取遞歸互斥信號量,只需遞歸層數加一.
計數信號量創建
SemaphoreHandle_t xSemaphoreCreateCounting(UBaseType_t uxMaxCount, /* 支持最大計數值 */UBaseType_t uxInitialCount);/* 初始計數值 */創建計數信號量函數
- 第一個參數設置技術信號量最大計數值
- 第二個參數設置初始計數值
- 返回值 如果創建成功會返回計數信號量句柄,如果heap不足則返回NULL
- 注意 信號量底層都是調用消息隊列實現的
二值信號量創建
SemaphoreHandle_t xSemaphoreCreateBinary( void );二值信號量創建函數
- 返回值 如果創建成功會返回計數信號量句柄,如果heap不足則返回NULL
- 注意 創建成功后 二值信號量初始值為0
- 一般使用任務消息通知來代替二值信號量,效率會更高
互斥信號量創建
SemaphoreHandle_t xSemaphoreCreateMutex( void );互斥信號量創建函數
- 返回值 如果創建成功會返回計數信號量句柄,如果heap不足則返回NULL
- 注意 創建成功后 互斥信號量初始值為0
- 一般用來保護任務中的臨界資源
遞歸互斥信號量創建
SemaphoreHandle_t xSemaphoreCreateRecursiveMutex( void )遞歸互斥信號量創建函數
- 返回值 如果創建成功會返回計數信號量句柄,如果heap不足則返回NULL
- 注意 創建成功后 互斥信號量初始值為0
釋放信號量
/* 釋放一個信號量, 該函數適用于計數信號量 二值信號量 互斥信號量 */ BaseType_t xSemaphoreGive(SemphoreHandle_t xSemaphore)/* 在中斷中釋放一個信號量, 該函數適用于計數信號量 二值信號量 */ BaseType_t xSemaphoreGiveFromISR(SemphoreHandle_t xSemaphore, BaseType_t * const pxHigherPriorityTaskWoken)/* 釋放一個信號量, 該函數適用于遞歸互斥信號量 */ BaseType_t xSemaphoreGiveRecursive( SemaphoreHandle_t xMutex )釋放信號量函數
- 第一個參數信號量句柄
- 在中斷中使用FormISR結尾的函數,在中斷中 第 2 個參數是釋放信號量后,是否有更高級別的任務就緒,如果有更高級別任務就緒(優先級更高的任務堵塞在獲取信號量上,這里釋放了信號量,導致任務從堵塞態轉變為就緒態),則pxHigherPriorityTaskWoken變為pdTRUE,然后在中斷結束處可以調用taskYIELD()進行任務調度。
- 返回值 pdTRUE釋放成功
- 注意 不同信號量使用不同的信號量釋放函數,互斥信號量不可以在中斷中使用,只能在任務中使用;
獲取信號量
/* 獲取一個信號量, 該函數適用于計數信號量 二值信號量 互斥信號量 */ BaseType_t xSemaphoreTake( SemaphoreHandle_t xSemaphore,TickType_t xTicksToWait );/* 在中斷中獲取一個信號量, 該函數適用于計數信號量 二值信號量 */ BaseType_t xSemaphoreTakeFromISR(SemaphoreHandle_t xSemaphore,signed BaseType_t *pxHigherPriorityTaskWoken)/* 獲取一個信號量, 該函數適用于遞歸互斥信號量 */ BaseType_t xSemaphoreTakeRecursive( SemaphoreHandle_t xMutex,TickType_t xTicksToWait );獲取信號量函數
- 第一個參數信號量句柄
- 第二個參數為等待時間,信號量底層調用消息隊列實現,如果消息隊列滿,則進行等待的時間
- 在中斷中 第 2 個參數是獲取信號量后,是否有更高級別的任務就緒,如果有更高級別任務就緒(優先級更高的任務堵塞在釋放信號量上,這里獲取了一個信號量,導致該任務從堵塞態轉變為就緒態),則pxHigherPriorityTaskWoken變為pdTRUE,然后在中斷結束處可以調用taskYIELD()進行任務調度。
- 返回值 pdTRUE獲取成功
- 注意 不同信號量使用不同的信號量獲取函數,互斥信號量不可以在中斷中使用,只能在任務中使用;
優先級翻轉問題
如果使用普通的二值信號量進行臨界資源保護會出現一下問題.
仔細觀察步驟5 6 7會發現,task2優先級明明比task1低,但是task2卻先執行,這就是任務優先級翻轉
互斥信號量為了解決這個問題,在二值信號量的基礎上增加了優先級繼承功能. 在步驟4 task1由掛起態轉變為就緒態獲取串口資源時,會將正在持有該資源的task3優先級改為和task1一樣高. 步驟5 task2就緒,但是task3的優先級已經和task1一樣,所以task3繼續執行,task3執行完畢后,釋放串口資源時,會將task3優先級改會原來,然后task1得到執行,taks1執行結束后task2才會得到執行.
本文參考 freertos官方文檔 https://freertos.org/a00110.html
《安富萊 STM32-V6 開發板 FreeRTOS 教程》
總結
以上是生活随笔為你收集整理的freeRtos学习笔记 (7)信号量的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: keil 使用AC6 中文警告解决办法
- 下一篇: freeRtos学习笔记 (8) 任务