日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

freeRtos学习笔记 (7)信号量

發布時間:2025/4/16 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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獲取成功
  • 注意 不同信號量使用不同的信號量獲取函數,互斥信號量不可以在中斷中使用,只能在任務中使用;

優先級翻轉問題

如果使用普通的二值信號量進行臨界資源保護會出現一下問題.

  • 有task1 task2 task3 三個任務,任務優先級 task1 > task2 > task3
  • task1和task2互斥訪問串口printf
  • task1執行完成后掛起,然后task3運行,task3運行時獲取了串口printf資源
  • task3運行過程中,task1由掛起態轉變為就緒態,task1運行需要獲取串口printf資源,由于task3已經獲取了該資源,task1因等待串口資源進入堵塞態.
  • task2就緒,由于task2優先級比task3高,所以task2運行.
  • task2運行結束掛起后,task3繼續執行
  • task3運行結束,釋放串口資源,task1恢復運行
  • 仔細觀察步驟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)信号量的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。