ucosiii學習(2)——空閒任務和節拍任務
1.空閒任務Idle Task
OS_IdleTaskInit(p_err); os_core.c中
系統在初始化過程中,會先建立一個空閒任務,在建立空閒任務時先初始化任務控制塊和連結串列,然後進行優先順序和就緒連結串列插入操作(OS_PrioInsert和OS_RdyListInsertTail),同時將任務計數加一(OSTaskQty++; ),最後呼叫OSSched()函式。
建立任務的標準流程:初始化任務控制塊——插入優先順序連結串列——插入就緒連結串列——任務計數加1——呼叫OSSched()。
2.時鐘節拍任務Tick Task
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.)
這兩個任務是系統初始化時必須建立的。