1. 程式人生 > 其它 >【STM32H7】第12章 ThreadX任務優先順序修改及其分配方案

【STM32H7】第12章 ThreadX任務優先順序修改及其分配方案

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

第12章 ThreadX任務優先順序修改及其分配方案

本章節主要為大家講解ThreadX任務優先順序設定的注意事項、任務優先順序的分配方案及其相關的一個例子,內容相對比較簡單。

12.1 任務優先順序說明

12.2 任務優先順序分配方案

12.3 中斷優先順序和任務優先順序的區別

12.4 任務優先順序修改函式tx_thread_priority_change

12.5 任務優先順序獲取函式tx_thread_info_get

12.6 實驗例程說明

12.7 總結

12.1 任務優先順序說明

下面對ThreadX優先順序相關的幾個重要知識點進行下說明,這些知識點在以後的使用中務必要掌握牢固。

1、 ThreadX中任務的最大優先順序數值是通過tx_port.h檔案中的TX_MAX_PRIORITIES進行配置的,使用者實際可以使用的優先順序範圍是0到configMAX_PRIORITIES – 1。比如我們配置此巨集定義為32,那麼使用者可以使用的優先順序號是0到31,不包含32,對於這一點,初學者要特別的注意。並且TX_MAX_PRIORITIES的巨集定義設定的數值必須是32的整數倍:

#define TX_MAX_PRIORITIES 32

2、 使用者配置任務的優先順序數值越小,那麼此任務的優先順序越低(0是最高優先順序任務),ThreadX沒有空閒任務,如果大家建立空閒任務,需要將其設定為最低優先順序。

3、 建議使用者配置巨集定義TX_MAX_PRIORITIES的最大值不要超過32,即使用者任務可以使用的優先順序範圍是0到31。

  • 因為對於CM核心的移植檔案,有專用的彙編指令CLZ(Count Leading Zeros),通過這些指令可以加速演算法執行速度。
  • 比通用方式高效。
  • ThreadX查詢最高優先順序任務是通過定義的32bit陣列,

ULONG _tx_thread_preempted_maps[TX_MAX_PRIORITIES/32];

如果TX_MAX_PRIORITIES設定為32,那麼僅需一個32bit變數就可以方便記錄32不同優先順序任務,程式執行時查詢最高優先順序任務也方便。

4、 ThreadX中處於執行狀態的任務永遠是當前能夠執行的最高優先順序任務。下一章節講解排程器,大家會對這個知識點有一個全面的認識。

12.2 任務優先順序分配方案

對於初學者,有時候會糾結任務優先順序設定為多少合適,因為任務優先順序設定多少是沒有標準的。對於這個問題,我們這裡為大家推薦一個標準,任務優先順序設定推薦方式如下圖所示:

  • IRQ任務:IRQ任務是指通過中斷服務程式進行觸發的任務,此類任務應該設定為所有任務裡面優先順序最高的。
  • 高優先順序後臺任務:比如按鍵檢測,觸控檢測,USB訊息處理,串列埠訊息處理等,都可以歸為這一類任務。
  • 低優先順序的時間片排程任務:比如GUI的介面顯示,LED數碼管的顯示等不需要實時執行的都可以歸為這一類任務。實際應用中使用者不必拘泥於將這些任務都設定為優先順序1的同優先順序任務,可以設定多個優先順序,只需注意這類任務不需要高實時性。
  • 空閒任務:空閒任務是系統任務。
  • 特別注意:IRQ任務和高優先順序任務必須設定為阻塞式(呼叫訊息等待或者延遲等函式即可),只有這樣,高優先順序任務才會釋放CPU的使用權,,從而低優先順序任務才有機會得到執行。

這裡的優先順序分配方案是我們推薦的一種方式,實際專案也可以不採用這種方法。調試出適合專案需求的才是最好的。

12.3 中斷優先順序和任務優先順序區別

部分初學者也容易在這兩個概念上面出現問題。簡單的說,這兩個之間沒有任何關係,不管中斷的優先順序是多少,中斷的優先順序永遠高於任何任務的優先順序,即任務在執行的過程中,中斷來了就開始執行中斷服務程式。

另外對於STM32來說,中斷優先順序的數值越小,優先順序越高。同樣,ThreadX的任務優先順序也是任務優先順序數值越小,任務優先順序越高。

12.4 任務優先順序修改函式tx_thread_priority_change

函式原型:

UINT tx_thread_priority_change(
    TX_THREAD *thread_ptr,
    UINT new_priority, 
    UINT *old_priority);

函式描述:

函式tx_thread_priority_change用於實現ThreadX任務優先順序的修改。

  • 第1個引數thread_ptr是任務控制代碼,用於區分不同的任務。
  • 第2個引數new_priority是新任務優先順序(0 至 (TX_MAX_PRIORITIES-1))。0表示最高優先順序。
  • 第3個引數old_priority是任務之前的優先順序。

注意事項:

  1. 允許在任務和定時器組裡面呼叫。
  2. 指定任務的搶佔閾值自動設定為新的優先順序。如果需要新的閾值,則必須在此呼叫之後使用函式tx_thread_preemption_change。
  3. 第二個引數數值不可大於等於tx_port.h檔案中的巨集定義:#define TX_MAX_PRIORITIES 配置的數值。

使用舉例:

TX_THREAD   AppTaskUserIFTCB;
UINT OldPriority;

/*優先順序將其設定為6 */
tx_thread_priority_change(&AppTaskUserIFTCB, 6, &OldPriority);

12.5 任務優先順序獲取函式tx_thread_info_get

函式原型:

UINT tx_thread_info_get(
    TX_THREAD *thread_ptr, 
    CHAR **name,
    UINT *state, 
    ULONG *run_count,
    UINT *priority,
    UINT *preemption_threshold,
    ULONG *time_slice,
    TX_THREAD **next_thread,
    TX_THREAD **suspended_thread);

函式描述:

函式tx_thread_info_get不僅僅可用於獲取ThreadX任務優先順序。還可以獲取其它相關資訊。

1、 第1個引數thread_ptr是任務控制代碼,用於區分不同的任務。

2、 第2個引數name用於獲取任務名。

3、 第3個引數state用於獲取任務狀態,可能的值如下所示。

  • TX_READY (0x00)
  • TX_COMPLETED (0x01)
  • TX_TERMINATED (0x02)
  • TX_SUSPENDED (0x03)
  • TX_SLEEP (0x04)
  • TX_QUEUE_SUSP (0x05)
  • TX_SEMAPHORE_SUSP (0x06)
  • TX_EVENT_FLAG (0x07)
  • TX_BLOCK_MEMORY (0x08)
  • TX_BYTE_MEMORY (0x09)
  • TX_MUTEX_SUSP (0x0D)

4、 第4個引數run_count用於獲取任務執行計數。

5、 第5個引數priority用於獲取任務優先順序。

6、 第6個引數preemption_threshold用於獲取搶佔閥值。

7、 第7個引數time_slice用於獲取時間片。

8、 第8個引數next_thread指向下一個建立的任務控制代碼。

9、 第9個引數suspended_thread指向掛起列表中下一個任務控制代碼。

10、 返回值

  • TX_SUCCESS:(0X00) 成功檢索任務資訊。
  • TX_THREAD_ERROR:(0x0E) 任務控制指標無效。

注意事項:

  • 可以在初始化階段,任務,定時器組和中斷服務程式裡面呼叫。

使用舉例:

TX_THREAD  AppTaskUserIFTCB;
CHAR *name;
UINT state;
ULONG run_count;
UINT priority;
UINT preemption_threshold;
UINT time_slice;
TX_THREAD *next_thread;
TX_THREAD *suspended_thread;
UINT status;

status = tx_thread_info_get(&AppTaskUserIFTCB, 
&name,
                            &state, 
&run_count,
                            &priority, 
&preemption_threshold,
                            &time_slice, 
&next_thread,
&suspended_thread);

12.6 實驗例程

配套例子:

V7-3007_ThreadX Task Priority Change

實驗目的:

  1. 學習ThreadX的開關中斷使用BasePri暫存器方案,這樣使用ThreadX可以僅開關受ThreadX管理的中斷,從而可以讓高優先順序中斷實現零中斷延遲。

實驗內容:

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

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

OS CPU Usage = 1.94%

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

Prio StackSize CurStack MaxStack Taskname

2 4092 383 391 App Task Start

3 4092 543 659 App Msp Pro

4 4092 391 391 App Task UserIF

5 4092 543 659 App Task COM

30 1020 519 519 App Task STAT

31 1020 143 71 App Task IDLE

0 1020 391 391 System Timer Thread

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

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

App Task MspPro任務 :訊息處理,這裡未使用。

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方式檢視。

實驗操作:

  1. K1按鍵按下列印任務執行情況,按下K2和K3設定優先順序後,可以按K1檢視任務最新優先順序是否設定成功。
  2. K2按鍵按下,設定任務App Task UserIF的優先順序為6。
  3. K3按鍵按下,設定任務App Task UserIF的優先順序為4。

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

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

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

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

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

程式執行框圖:

12.7 總結

本章節內容相對比較容易,重點是學習任務優先順序分配方案,隨著後面的學習,初學者需要慢慢積累這方面的經驗。