1. 程式人生 > 其它 >【STM32H7】第14章 ThreadX排程鎖,任務鎖和中斷鎖(排程閥值)

【STM32H7】第14章 ThreadX排程鎖,任務鎖和中斷鎖(排程閥值)

論壇原始地址(持續更新):http://www.armbbs.cn/forum.php?mod=viewthread&tid=99514

第14章 ThreadX排程鎖,任務鎖和中斷鎖(排程閥值)

本章教程為大家講解排程鎖,任務鎖和中斷鎖的概念,以及ThreadX排程鎖的使用。

14.1 排程鎖

14.2 中斷鎖

14.3 任務鎖

14.4 ThreadX排程閥值

14.5 實驗例程說明

14.6 總結

14.1 臨界段

程式碼的臨界段也稱為臨界區,一旦這部分程式碼開始執行,則不允許任何中斷打斷。為確保臨界段程式碼的執行不被中斷,在進入臨界段之前須關中斷,而臨界段程式碼執行完畢後,要立即開中斷。

如果原始碼中有臨界段的話,會給系統帶來什麼問題呢?比如此時某個任務正在呼叫系統API函式,而且此時中斷正好關閉了,也就是進入到了臨界區中,這個時候如果有一個緊急的中斷事件被觸發,這個中斷就不能得到及時執行,必須等到中斷開啟才可以得到執行,如果關中斷時間超過了緊急中斷能夠容忍的限度,危害是可想而知的。像uCOS-II,uCOS-III和FreeRTOS的原始碼中都是有臨界段的。

除了上面說的作業系統原始碼所帶的臨界段以外,使用者寫應用的時候也有臨界段的問題,比如以下兩種:

  • 讀取或者修改變數(特別是任務間通訊的全域性變數)的程式碼,一般來說這是最常見的臨界程式碼。
  • 呼叫公共函式的程式碼,特別是不可重入的函式,如果多個任務都訪問這個函式,結果是可想而知的。

總之,對於臨界段要做到執行時間越短越好,要不會影響系統的實時性。

14.2 中斷鎖

中斷鎖就是ThreadX提供的開關中斷函式:

#define TX_INTERRUPT_SAVE_AREA                  unsigned int  was_masked;
#define TX_DISABLE                              was_masked = __disable_irq();
#define TX_RESTORE                              if (was_masked == 0) __enable_irq();

14.3 任務鎖

簡單的說,為了防止當前任務的執行被其它高優先順序的任務打斷而提供的鎖機制就是任務鎖。實現任務鎖可以通過給排程器加鎖或者直接關閉RTOS核心定時器(就是前面一直說的系統滴答定時器)來實現。

  • 通過給排程器加鎖實現。

給排程器加鎖的話,就無法實現任務切換,高優先順序任務也就無法搶佔低優先順序任務的執行,同時高優先順序任務也是無法向低優先順序任務切換的。像uCOS-II和uCOS-III是採用的這種方法實現任務鎖。特別注意,這種方式只是禁止了排程器工作,並沒有關閉任何中斷。

  • 通過關閉RTOS核心定時器實現

關閉了RTOS核心定時器的話,也就關閉了通過RTOS核心定時器中斷實現任務切換的功能,因為在退出定時器中斷時需要檢測當前需要執行的最高優先順序任務,如果有高優先順序任務就緒的話需要做任務切換。RTX作業系統是採用的這種方式實現任務鎖的。

ThreadX有更好的方法實現,可以使用搶佔閥值。

14.4 排程鎖

排程鎖就是RTOS提供的排程器開關函式,如果某個任務呼叫了排程鎖開關函式,處於排程鎖開和排程鎖關之間的程式碼在執行期間是不會被高優先順序的任務搶佔的,即任務排程被禁止。這一點要跟臨界段的作用區分開,排程鎖只是禁止了任務排程,並沒有關閉任何中斷,中斷還是正常執行的。而臨界段進行了開關中斷操作。

與任務鎖一樣,也可以採用排程閥值實現。

14.5 ThreadX的搶佔閥值

為了緩解搶佔式排程存在的一些固有問題,ThreadX 提供了一個獨特的高階功能---搶佔閾值。

搶佔閾值允許任務指定禁止搶佔的優先順序上限。優先順序高於上限的任務仍可以執行搶佔,但不允許優先順序低於上限的任務執行搶佔。

例如,假設優先順序為 20 的任務只與一組優先順序介於 15 到 20 之間的任務進行互動。 在其關鍵部分中,優先順序為 20 的任務可將其搶佔閾值設定為 15,從而防止該任務和與之互動的所有任務發生搶佔。 這仍允許(優先順序介於 0和 14 之間)真正重要的任務在其關鍵部分處理中搶佔此任務的資源,這會使處理的響應速度更快。

而且可以將搶佔閾值設定為 0 來禁止所有任務搶佔。同時,使用者也可以在執行時更改搶佔閾值。注:使用搶佔閾值會禁止指定執行緒的時間排程。

舉個例子,方便大家使用,比如一個任務的優先順序是5,我們希望執行某程式碼期間禁止優先順序0-4的任務搶佔。

TX_THREAD my_thread;
UINT my_old_threshold;
UINT status;

status = tx_thread_preemption_change(&my_thread,
           0, &my_old_threshold);

 使用者可以在此處執行關鍵程式碼。

status = tx_thread_preemption_change(&my_thread,
           5, &my_old_threshold);

通過這種方式就可以方便的實現排程鎖和任務鎖。

14.6 實驗例程

配套例子:

V7-3009_ThreadX Preemption Threshold

實驗目的:

  1. 學習ThreadX搶佔閥值。
  2. 通過搶佔閥值可以方便的實現任務鎖,排程鎖的功能

實驗內容:

1、共建立瞭如下幾個任務,通過按下按鍵K1可以通過串列埠或者RTT列印任務堆疊使用情況

========================================================

OS CPU Usage = 1.05%

========================================================

任務優先順序 任務棧大小 當前使用棧 最大棧使用 任務名

Prio StackSize CurStack MaxStack Taskname

2 4092 303 459 App Task Start

30 1020 303 303 App Task STAT

31 1020 87 71 App Task IDLE

5 4092 167 167 App Msp Pro

4 4092 167 167 App Task UserIF

5 4092 167 167 App Task COM

0 1020 191 191 System Timer Thread

串列埠軟體可以使用SecureCRT或者H7-TOOL RTT檢視列印資訊。

App Task Start任務 :啟動任務,這裡用作BSP驅動包處理。

App Task MspPro任務 :訊息處理,這裡用作LED閃爍。

App Task UserIF任務 :按鍵訊息處理。

App Task COM任務 :這裡用作LED閃爍。

App Task STAT任務 :統計任務

App Task IDLE任務 :空閒任務

System Timer Thread任務:系統定時器任務

2、(1) 凡是用到printf函式的全部通過函式App_Printf實現。

(2) App_Printf函式做了訊號量的互斥操作,解決資源共享問題。

3、預設上電是通過串列埠列印資訊,如果使用RTT列印資訊

(1) MDK AC5,MDK AC6或IAR通過使能bsp.h檔案中的巨集定義為1即可

#define Enable_RTTViewer 1

(2) Embedded Studio繼續使用此巨集定義為0, 因為Embedded Studio僅製作了除錯狀態RTT方式檢視。

串列埠列印資訊方式(AC5,AC6和IAR):

波特率 115200,資料位 8,奇偶校驗位無,停止位 1

RTT列印資訊方式(AC5,AC6和IAR):

Embedded Studio僅支援除錯狀態RTT列印:

由於Embedded Studio不支援中文,所以中文部分顯示亂碼,不用管。

程式執行框圖:

14.7 總結

本章節是ThreadX作業系統的核心,初學者要深入理解的話需要多花些時間。當然,如果有其它

RTOS的基礎的話,這個學起來也是很快的。