ucosiii學習(2)——系統初始化時所建立的任務
1.空閒任務OS_IdleTaskInit(p_err); os_core.c中
系統在初始化過程中,會先建立一個空閒任務,在建立空閒任務時先初始化任務控制塊和連結串列,然後進行優先順序和就緒連結串列插入操作(OS_PrioInsert和OS_RdyListInsertTail),同時將任務計數加一(OSTaskQty++; ),最後呼叫OSSched()函式。
這個任務幾乎不做什麼事情,只是把OSIdleTaskCtr
和OSStatTaskCtr
進行自加操作,這兩個變數都是用來除錯和統計任務統計的,以保證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函式中操作: