1. 程式人生 > 其它 >【STM32F429】第16章 ThreadX原裝任務統計分析功能實現(含IAR的ThreadX外掛使用)

【STM32F429】第16章 ThreadX原裝任務統計分析功能實現(含IAR的ThreadX外掛使用)

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

第16章 ThreadX原裝任務統計分析功能實現(含IAR的ThreadX外掛使用)

本章節為大家講解ThreadX原裝任務統計分析功能的實現,支援MDK,IAR和GCC。

16.1 ThreadX的任務統計分析實現原理

16.2 ThreadX的任務統計分析功能移植

16.3 IAR的ThreadX外掛實現

16.4 實驗例程說明

16.5 總結

16.1 ThreadX的任務統計分析實現原理

對於Cortex-M核心,帶有DWT時鐘週期計數器,比如晶片主頻是100MHz,那麼DWT統計的時鐘週期解析度就是10ns。

ThreadX就是藉助此功能實現任務統計分析,使用簡單,僅需使能就可以使用。M3,M4和M7核心都帶這個功能,而M0核心不帶,使用中要注意。

16.2 ThreadX的任務統計分析功能移植

這裡以移植到MDK為例進行說明,其它IAR,GCC的移植方法是一樣的。

16.2.1 新增任務分析程式碼

從ThreadX 核心V6.1.7版本開始,加入了任務統計分析功能,位於原始碼軟體包的如下路徑:

ThreadX\utility\execution_profile_kit 。

按照前面章節的移植方法,升級ThreadX核心的版本到V6.1.7後,新增此檔案即可。

別忘了新增相應路徑:

16.2.2 設定巨集定義

C檔案要新增巨集定義:TX_EXECUTION_PROFILE_ENABLE, TX_CORTEX_M_EPK

彙編檔案要新增巨集定義:TX_EXECUTION_PROFILE_ENABLE,TX_ENABLE_EXECUTION_CHANGE_NOTIFY

對於MDK AC5,Misc Controls加上 –cpreproc

16.2.3 使能DWT時鐘週期計時器

預設情況下,ThreadX的移植檔案tx_initialize_low_level.s帶了DWT時鐘週期計數器的使能:

    /* Enable the cycle count register.  */

    LDR     r0, 
=0xE0001000 ; Build address of DWT register LDR r1, [r0] ; Pickup the current value ORR r1, r1, #1 ; Set the CYCCNTENA bit STR r1, [r0] ; Enable the cycle count register

保險起見,在bsp.c檔案也呼叫了函式bsp_InitDWT()做初始化。

16.2.4 展示任務統計方法

Threadx提供了三個64bit的全域性變數統計時間資訊,單位是系統時鐘計數器,比如主頻是100MHz,那麼單位就是10ns。

  • _tx_execution_thread_time_total

統計從上電開始,所有任務總的執行時間。

  • _tx_execution_idle_time_total

統計從上電開始,總的空閒時間。

  • _tx_execution_isr_time_total

統計從上電開始,中斷服務程式總的執行實現。

為了方便統計CPU利用率,可以採用:

_tx_execution_thread_time_total/(_tx_execution_thread_time_total + _tx_execution_idle_time_total + _tx_execution_isr_time_total)

但這種統計不能反應CPU利用率瞬時變化,所以做了一個瞬時的統計方法,每200ms統計一次:

/*
*********************************************************************************************************
*    函 數 名: AppTaskStart
*    功能說明: 啟動任務。
*    形    參: thread_input 是在建立該任務時傳遞的形參
*    返 回 值: 無
    優 先 級: 2
*********************************************************************************************************
*/
static  void  AppTaskStart (ULONG thread_input)
{
    EXECUTION_TIME TolTime, IdleTime, deltaTolTime, deltaIdleTime;
    uint32_t uiCount = 0;
    (void)thread_input;
    

    /* 核心開啟後,恢復HAL裡的時間基準 */
    HAL_ResumeTick();
    
    /* 外設初始化 */
    bsp_Init();
    
    /* 建立任務 */
    AppTaskCreate(); 

    /* 建立任務間通訊機制 */
    AppObjCreate();    

    /* 計算CPU利用率 */
    IdleTime = _tx_execution_idle_time_total;
    TolTime = _tx_execution_thread_time_total + _tx_execution_isr_time_total + _tx_execution_idle_time_total;
    while (1)
    {  
        /* 需要週期性處理的程式,對應裸機工程呼叫的SysTick_ISR */
        bsp_ProPer1ms();
        
        /* CPU利用率統計 */
        uiCount++;
        if(uiCount == 200)
        {
            uiCount = 0;
            deltaIdleTime = _tx_execution_idle_time_total - IdleTime;
            deltaTolTime = _tx_execution_thread_time_total + _tx_execution_isr_time_total + 
_tx_execution_idle_time_total - TolTime;
            OSCPUUsage = (double)deltaIdleTime/deltaTolTime;
            OSCPUUsage = 100- OSCPUUsage*100;
            IdleTime = _tx_execution_idle_time_total;
            TolTime = _tx_execution_thread_time_total + _tx_execution_isr_time_total +
 _tx_execution_idle_time_total;
        }
        
        tx_thread_sleep(1);
    }
}

任務資訊統一通過函式DispTaskInfo進行列印:

/*
*********************************************************************************************************
*    函 數 名: DispTaskInfo
*    功能說明: 將ThreadX任務資訊通過串列埠打印出來
*    形    參:無
*    返 回 值: 無
*********************************************************************************************************
*/
static void DispTaskInfo(void)
{
    TX_THREAD      *p_tcb;            /* 定義一個任務控制塊指標 */

    p_tcb = &AppTaskStartTCB;
    
    /* 列印標題 */
    App_Printf("===============================================================\r\n");
    App_Printf("CPU利用率 = %5.2f%%\r\n", OSCPUUsage);
    App_Printf("任務執行時間 = %.9fs\r\n", (double)_tx_execution_thread_time_total/SystemCoreClock);
    App_Printf("空閒執行時間 = %.9fs\r\n", (double)_tx_execution_idle_time_total/SystemCoreClock);
    App_Printf("中斷執行時間 = %.9fs\r\n", (double)_tx_execution_isr_time_total/SystemCoreClock);
    App_Printf("系統總執行時間 = %.9fs\r\n", (double)(_tx_execution_thread_time_total + \
                                                       _tx_execution_idle_time_total +  \
                                                       _tx_execution_isr_time_total)/SystemCoreClock);    
    App_Printf("===============================================================\r\n");
    App_Printf(" 任務優先順序 任務棧大小 當前使用棧  最大棧使用   任務名\r\n");
    App_Printf("   Prio     StackSize   CurStack    MaxStack   Taskname\r\n");

    /* 遍歷任務控制列表TCB list),列印所有的任務的優先順序和名稱 */
    while (p_tcb != (TX_THREAD *)0) 
    {
        
        App_Printf("   %2d        %5d      %5d       %5d      %s\r\n", 
                    p_tcb->tx_thread_priority,
                    p_tcb->tx_thread_stack_size,
                    (int)p_tcb->tx_thread_stack_end - (int)p_tcb->tx_thread_stack_ptr,
                    (int)p_tcb->tx_thread_stack_end - (int)p_tcb->tx_thread_stack_highest_ptr,
                    p_tcb->tx_thread_name);


        p_tcb = p_tcb->tx_thread_created_next;

        if(p_tcb == &AppTaskStartTCB) break;
    }
}

效果:

16.3 IAR的ThreadX外掛實現

IAR和MDK的實現一樣,移植了V6.1.7或者以上版本後,新增統計分析檔案即可,剩下就是使能IAR的ThreadX外掛:

  • 第1步,使能ThreadX外掛:

  • 第2步,進入除錯狀態,新增ThreadX元件,大家可以更新需要選擇展現那些資訊:

  • 第3步,先全速執行,然後點選暫停才可以檢視資訊,效果如下:

16.4 實驗例程

配套例子:

V6-3011_ThreadX Task Statistics

實驗目的:

  1. ThreadX原裝任務統計分析功能

實驗內容:

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

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

CPU利用率 = 0.89%

任務執行時間 = 0.586484645s

空閒執行時間 = 85.504470575s

中斷執行時間 = 0.173225395s

系統總執行時間 = 86.264180615s

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

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

Prio StackSize CurStack MaxStack Taskname

2 4092 303 459 App Task Start

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閃爍。

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不支援中文,所以中文部分顯示亂碼,不用管。

程式執行框圖:


16.5 總結

本章節主要為大家講解了ThreadX原裝的任務統計分析功能的實現,比較實用。