uc/os-ii統計任務

uC/OS-II定義了兩個系統任務,空閒任務與統計任務。

  • 空閒任務OSTaskIdle()是μC/OS-Ⅱ必不可少的系統函數,當沒有其它任務進入就緒態時,該任務立即轉入運行態。空閒任務的優先級永遠設爲最低,即OS_LOWEST_PRIO,永遠不被掛起,也不能被刪除。

  • 空閒任務什麼都不做,只是在不停地給一個32位計數器OSIdleCtr加1,統計任務使用這個計數器以確定當前應用程序實際消耗的CPU時間。計數器是一個全局變量,大多數8位或16位CPU對32位變量加1需要多條指令,所以在訪問前必須先關中斷,然後再開啓,以防高優先級任務或中斷打入。

void  OS_TaskIdle (void *p_arg)
{
#if OS_CRITICAL_METHOD == 3                      /* Allocate storage for CPU status register           */
    OS_CPU_SR  cpu_sr = 0;
#endif



    (void)p_arg;                                 /* Prevent compiler warning for not using 'p_arg'     */
    for (;;) {
        OS_ENTER_CRITICAL();
        OSIdleCtr++;
        OS_EXIT_CRITICAL();
        OSTaskIdleHook();                        /* Call user definable HOOK                           */
    }
}
  • 統計任務OSTaskStat()也是μC/OS-Ⅱ的系統函數之一,其功能是計算當前CPU的利用率,告訴用戶應用程序使用了多少CPU時間。一旦將文件OS_CFG.H中的配置常數OS_ TASK_STAT_EN置1,這個任務就自動建立。它每秒鐘運行一次,計算結果放在一個有符號的8位整數OSCPUsage中,表示格式是百分數,精確到1%。
void  OS_TaskStat (void *p_arg)
{
#if OS_CRITICAL_METHOD == 3                      /* Allocate storage for CPU status register           */
    OS_CPU_SR  cpu_sr = 0;
#endif



    (void)p_arg;                                 /* Prevent compiler warning for not using 'p_arg'     */
    while (OSStatRdy == OS_FALSE) {
        OSTimeDly(2 * OS_TICKS_PER_SEC / 10);    /* Wait until statistic task is ready                 */
    }
    OSIdleCtrMax /= 100L;
    if (OSIdleCtrMax == 0L) {
        OSCPUUsage = 0;
        (void)OSTaskSuspend(OS_PRIO_SELF);
    }
    for (;;) {
        OS_ENTER_CRITICAL();
        OSIdleCtrRun = OSIdleCtr;                /* Obtain the of the idle counter for the past second */
        OSIdleCtr    = 0L;                       /* Reset the idle counter for the next second         */
        OS_EXIT_CRITICAL();
        OSCPUUsage   = (INT8U)(100L - OSIdleCtrRun / OSIdleCtrMax);
        OSTaskStatHook();                        /* Invoke user definable hook                         */
#if (OS_TASK_STAT_STK_CHK_EN > 0) && (OS_TASK_CREATE_EXT_EN > 0)
        OS_TaskStatStkChk();                     /* Check the stacks for each task                     */
#endif
        OSTimeDly(OS_TICKS_PER_SEC / 10);        /* Accumulate OSIdleCtr for the next 1/10 second      */
    }
}
  • 下面重點分析一下如何計算CPU利用率。
    使用統計任務時,初始化時只能建立唯一的一個任務,其它任務的建立只能在多任務啓動後建立。值得注意的是:時鐘節拍的初始化和啓動工作也可以放在OSStart()函數中完成。一般不要在多任務啓動之前啓動時鐘節拍器,因爲這樣做可能導致任務開始前應用程序就收到時鐘節拍中斷,以至系統崩潰。
void main (void)
{  
    OSInit();      /*初始化ucosii  */     
    OSTaskCreate(TaskStart,(void *)0,
        &startup_task_stk[STARTUP_TASK_STK_SIZE-1], STARTUP_TASK_PRIO);/*創建唯一任務  */        
    OSStart();       
}
void TaskStart(void *p_arg)
{
    SysTick_init();/*安裝並啓動始終節拍   */
    OSStatInit(); /*調用系統函數,初始化統計任務  */         
    while(1)
    {
         /*TaskStart代碼      */
    }
}
  • 統計任務的使用方法是:首先用戶在初始化時建立一個也只能是一個任務,其次在這個唯一的任務中調用OSStatInit()函數。
void  OSStatInit (void)
{
#if OS_CRITICAL_METHOD == 3                      /* Allocate storage for CPU status register           */
    OS_CPU_SR  cpu_sr = 0;
#endif
    OSTimeDly(2);                                /* Synchronize with clock tick                        */
    OS_ENTER_CRITICAL();
    OSIdleCtr    = 0L;                           /* Clear idle counter                                 */
    OS_EXIT_CRITICAL();
    OSTimeDly(OS_TICKS_PER_SEC / 10);            /* Determine MAX. idle counter value for 1/10 second  */
    OS_ENTER_CRITICAL();
    OSIdleCtrMax = OSIdleCtr;                    /* Store maximum idle counter count in 1/10 second    */
    OSStatRdy    = OS_TRUE;
    OS_EXIT_CRITICAL();
}
  • 進入多任務的條件準備好了以後,調用系統啓動函數OSStart()。這個函數將使TaskStart()開始執行,因爲TaskStart()是優先級最高的任務。TaskStart()負責初始化和啓動時鐘節拍。在這裏啓動時鐘節拍是必要的,因爲用戶不會希望在多任務還沒有開始時就接收到時鐘節拍中斷。接下去TaskStart()調用統計初始化函數OSStatInit()
    統計初始化函數OSStatInit()決定在沒有其它應用任務運行時,空閒計數器OSIdleCtr的計數有多快。這裏取0.1秒(OS_TICKS_PER_SEC / 10)內OSIdleCtr的計數值OSIdleCtrMax 爲計算CPU利用率的基準。

    1. 系統統計初始化任務函數OSStatInit()調用延遲函數OSTimeDly(2)將自身延時2個時鐘節拍以停止自身的運行。這是爲了使OSStatInit()與時鐘節拍同步。
    2. μC/OS-Ⅱ然後選下一個優先級最高的進入就緒態的任務運行,這恰好是統計任務OSTaskStat()OSTaskStat()所要做的第一件事就是查看統計任務就緒標誌是否爲“假”,如果是的話,要延時0.2秒(2 * OS_TICKS_PER_SEC / 10)。一定會是這樣,因爲標誌OSStatRdy已被OSInit()函數初始化爲“假”,所以實際上OSTaskStat也將自己推入休眠態0.2秒。
    3. 於是任務切換到空閒任務,OSTaskIdle()開始運行,這是唯一一個就緒態任務了。CPU處在空閒任務OSTaskIdle中,直到TaskStart()的延遲兩個時鐘節拍完成。
    4. 兩個時鐘節拍之後,TaskStart()恢復運行。 在執行OSStartInit()時,空閒計數器OSIdleCtr被清零。然後,OSStatInit()將自身延時0.1秒。
    5. 因爲沒有其它進入就緒態的任務,OSTaskIdle()又獲得了CPU的控制權。0.1秒鐘以後,TaskStart()繼續運行,還是在OSStatInit()中,空閒計數器將0.1秒鐘內計數的值存入空閒計數器最大值OSIdleCtrMax
    6. OSStarInit()將統計任務就緒標誌OSStatRdy設爲“真”,以此來允許OSTaskStat()開始計算CPU的利用率。
  • 統計任務每0.1秒執行一次,以確定所有應用程序中的任務消耗了多少CPU時間。當用戶的應用程序代碼加入以後,運行空閒任務的CPU時間就少了,OSIdleCtr就不會像原來什麼任務都不運行時有那麼多計數。要知道,OSIdleCtr的最大計數值是OSStatInit()在初始化時保存在計數器最大值OSIdleCtrMax中的。CPU利用率是保存在變量OSCPUsage中的,根據公式計算OSIdleCtr=OSIdleCtrMax 時CPU利用率最低爲0,OSIdleCtr=0 時CPU利用率最高爲100%。
     圖1-1
    ===========以上爲統計任務的分析===============

  • 關於統計任務運行頻率的補充

統計任務執行到最後時是OSTimeDly(OS_TICKS_PER_SEC/10);這樣一個函數。表示延遲一分鐘。而只有統計任務延時時空閒任務纔有可能運行,所以每當統計任務運行時OSIdleCtr的值都是在可能的1s內記的數。因爲在統計任務在賦完值之後清零了。所以說,統計任務不是1s運行一次,只不過統計任務運行時用到的變量都是在1s內的數據。

參考:http://gha20028.blog.163.com/blog/static/13481666201363021616344/

發佈了34 篇原創文章 · 獲贊 7 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章