以下內容主要注重應用,對源碼不做分析,對源碼有興趣的可參考官方具體文檔,相關鏈接:https://doc.micrium.com/display/ucos/
編譯環境:Atollic TrueSTUDIO for STM32 9.3.0
硬件:基於STM32F103VET6單片機(使用HAL庫)
一、介紹
要啟用coitoc /OS-II互斥服務,必須在OS_CFG.H中設置配置常量。當OS_MUTEX_EN設置為0時,禁止互斥服務;將OS_MUTEX_EN設置為1時,啟動互斥服務。
任務使用互斥信號量或簡單的互斥量來獲得對資源的獨占訪問。互斥量是二進制信號量,它具有超出由μC /OS-II提供的普通信號量機制的額外特性。
應用程序代碼使用互斥鎖來減少優先級倒置問題,如實時系統概念中所述。當低優先級任務擁有高優先級任務所需的資源時,就會發生優先級反轉。為了減少優先級反轉,內核可以將低優先級任務的優先級增加到高優先級任務的優先級,直到低優先級任務用完資源。
下圖顯示了一個流程圖來說明任務和互斥之間的關系。互斥鎖只能被任務訪問。注意,用來表示互斥鎖的符號是一個“key”。“key”符號表示互斥鎖是用來訪問共享資源的。
二、創建一個互斥信號量,OSMutexCreate()
一個互斥信號量使用前需要被創建,通過調用OSMutexCreate()來創建互斥信號量。互斥信號量的初始值總是設置為1,表示資源可用。函數原型為:
1、OS_EVENT *OSMutexCreate (INT8U prio, INT8U *err)
- prio是指互斥信號量的優先級(即當一個任務獲取該互斥信號量后,任務的優先級會臨時變成該互斥信號量的優先級,因為互斥信號量的優先級和任務的優先級屬於同一類,通常建議該互斥信號量的優先級高於所有任務優先級);
- err是存放錯誤類型;
- 返回與互斥信號量相關聯的指向事件控制塊的指針。
三、獲取互斥信號量,OSMutexPend()
獲取互斥信號量,函數原型為:
1、void
OSMutexPend (OS_EVENT *pevent, INT16U timeout, INT8U *err)。
- pevent是互斥信號量相關聯的指向事件控制塊的指針;
- timeout等待時長(如果是0將一直等下去,直到有可用的互斥信號量);
- err保存錯誤類型。
四、釋放互斥信號量,OSMutexPost()
釋放獲取的互斥信號量,函數原型為:
1、INT8U OSMutexPost (OS_EVENT *pevent)。
- pevent是互斥信號量相關聯的指向事件控制塊的指針;
- 返回值是錯誤類型。
五、使用注意事項
1、互斥信號量只能在任務中使用;
2、互斥信號量創建完成就有資源可用,與信號量創建需指定可用的資源數目不同;
3、互斥信號量的優先級和任務優先級屬於同一類,在不支持同級任務優先級的操作系統中尤其要注意;
4、當一個任務獲取到一個互斥信號量后會把優先級暫時變成互斥信號量的優先級,釋放互斥信號量的時候恢復。
六、示例代碼
1、啟動互斥服務配置
#define OS_MUTEX_EN 1 /* Enable (1) or Disable (0) code generation for MUTEX */ #define OS_MUTEX_ACCEPT_EN 1 /* Include code for OSMutexAccept() */ #define OS_MUTEX_DEL_EN 1 /* Include code for OSMutexDel() */ #define OS_MUTEX_QUERY_EN 1 /* Include code for OSMutexQuery() */
2、定義一個互斥信號量事件指針:
/* 定義一個互斥信號量事件指針 */ OS_EVENT *MutexSemp;
3、創建互斥信號量,並設置互斥信號量的優先級
/* 創建互斥信號量,指定優先級為2 */ MutexSemp = OSMutexCreate(2, &err);
4、在兩個任務中分別使用同一個互斥信號量:
static void AppTaskLed1(void *p_arg) { INT8U err; (void)p_arg; while(1) { /* 獲取互斥信號量 */ OSMutexPend(MutexSemp, 0, &err); HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_0); /* 釋放互斥信號量 */ OSMutexPost(MutexSemp); OSTimeDlyHMSM(0, 0, 1, 0); } } static void AppTaskLed2(void *p_arg) { INT8U err; (void)p_arg; while(1) { /* 獲取互斥信號量 */ OSMutexPend(MutexSemp, 0, &err); HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_5); /* 釋放互斥信號量 */ OSMutexPost(MutexSemp); OSTimeDlyHMSM(0, 0, 2, 0); } }
#endif