1. 程式人生 > >ucosiii學習(2)——系統初始化時所建立的任務

ucosiii學習(2)——系統初始化時所建立的任務

1.空閒任務OS_IdleTaskInit(p_err);      os_core.c中

系統在初始化過程中,會先建立一個空閒任務,在建立空閒任務時先初始化任務控制塊和連結串列,然後進行優先順序和就緒連結串列插入操作(OS_PrioInsert和OS_RdyListInsertTail),同時將任務計數加一(OSTaskQty++;  ),最後呼叫OSSched()函式。

這個任務幾乎不做什麼事情,只是把OSIdleTaskCtrOSStatTaskCtr進行自加操作,這兩個變數都是用來除錯和統計任務統計的,以保證CPU始終處於執行狀態。

建立任務的標準流程:初始化任務控制塊——插入優先順序連結串列——插入就緒連結串列——任務計數加1——呼叫OSSched()。

2.時鐘節拍任務OS_TickTaskInit(p_err);     os_tick.c中,優先順序為2u

流程同上。

節拍任務的具體函式如下:

可以看到,函式處於for的死迴圈中,並且呼叫 

(void)OSTaskSemPend(0u,
                            OS_OPT_PEND_BLOCKING,
                            DEF_NULL,
                            &err);  函式,其作用為:

 Description: This function is called to block the current task until a signal is sent by another task or ISR.

迴圈最初,要等待任務自身的計數訊號量,而且其選項是OS_OPT_PEND_BLOCKING,等不到訊號量時會阻塞住並釋放CPU發生一次排程,排程到其他任務。而這個任務的技術訊號量的Post操作是發生在SysTick的中斷處理函式中的。在SysTick中斷處理函式void SysTick_Handler(void)中有呼叫OSTimeTick:

void  OS_CPU_SysTickHandler  (void)
{
    CPU_SR_ALLOC();
    CPU_CRITICAL_ENTER();
    OSIntEnter();               /* Tell uC/OS-III that we are starting an ISR   */
    CPU_CRITICAL_EXIT();
    OSTimeTick();               /* Call uC/OS-III's OSTimeTick()   */
    OSIntExit();                /* Tell uC/OS-III that we are leaving the ISR   */
}

在OSTimeTick()中有

  (void)OSTaskSemPost(&OSTickTaskTCB,                          /* Signal tick task                                     */
                        OS_OPT_POST_NONE,
                       &err);

因此,OSTimeTick函式會往OSTickTaskTCB任務中做一次Post操作,OS_TickTask在其for迴圈中迴圈一次。

(void)OS_TickListUpdateDly(tick_step):更新時基任務列表OSTickListTimeDly。OS_TickListUpdateDly函式會先把OSTickListTimeDly中的每一個任務的TickRemain進行檢查,如果發現這些任務延時已經到期,那麼就把這些任務從OSTickListTimeDly移除,並呼叫OS_RdyListInsert放入到就緒佇列裡。

(* Description: This function updates the delta list which contains tasks that have been delayed.)

(void)OS_TickListUpdateTimeout(tick_step):更新時基任務列表OSTickListTimeout。OS_TickListUpdateTimeout函式也會先把OSTickListTimeout中的每一個任務的TickRemain進行檢查,如果發現這些任務的Time Out已經到期,那麼就先把這些任務從OSTickListTimeout移除,又因為這些任務都是通過Pend和設定timeout值被放入OSTickListTimeout佇列的,所以這些任務一定也存在於一個Pend List中。同樣的,OS_TickListUpdateTimeout也會呼叫OS_PendListRemove把這些任務從其相應的Pend List中移除,並呼叫OS_RdyListInsert放入到就緒佇列裡。

(* Description: This function updates the delta list which contains tasks that are pending with a timeout.)

這兩個任務是系統初始化時必須建立的。

 

3.統計任務 OS_StatTaskInit(p_err);

Description: This task is internal to uC/OS-III and is used to compute some statistics about the multitasking environment.  Specifically, OS_StatTask() computes the CPU usage.  CPU usage is determined by:

a.統計總的CPU使用率(0 到 100%),每個任務的CPU使用率(0 到 100%)。μC/OS III 允許使用者在呼叫 OSStart()之前建立任意個任務。然而 ,當用到統計任務統計 CPU 的使用率時,呼叫 OSStart()之前只能建立一個任務,優先順序比空閒任務高。
b. 每個任務的堆疊使用量。並將計算結果存於每個任務OS_TCB的StkFree和StkUsed中。


如果想使用統計任務,最好在 main()中只建立一個任務,通常叫做AppTaskStat(),當使能了統計任務時,就必須在AppTaskStat任務中首先呼叫OSStatTaskCPUUsageInit()。在呼叫OSStart()之前 ,使用者的啟動程式碼只能建立一個任務,由這個任務建立其它任務。 呼叫OSStatTaskCPUUsageInit()。當沒有其它應用任務執行時,經過1/OS_CFG_STAT_TASK_RATE秒後 OSStatTaskCtr 的計數值就是OSStatTaskCtr的最大值,它意味著CPU的空閒時的工作速率 。例如,如果系統中不包含應用任務,OSStatTaskCtr 從 0 開始計數到10,000,000 用了1/OS_CFG_STAT_TASK_RATE 秒。添加了應用任務後,OSStatTaskCtr 每 1/OS_CFG_STAT_TASK_RATE秒檢測一次。得到的值不會達到 10,000,000。

4.定時器任務OS_TmrInit(p_err);

Description: This function is called by OSInit() to initialize the timer manager module.

優先順序為最大優先順序-3,高於空閒任務, 主要用於阻塞(OSTaskSemPend)或者延時(OSTimeDly),取決於巨集開關OS_CFG_DYN_TICK_EN。以OSTaskSemPend為例,定時器任務會一直等到其他任務或者中斷對OSTmrTaskTCB進行的Post操作。而這個操作和時基任務的Post操作一樣,在OS_CPU_SysTickHandler的OSTimeTick函式中操作: