從零開始學習UCOSII操作系統3--UCOSII啓動過程
1、初始化UCOSII
(1)在調用UCOSII在任何的其他的服務之前,UCOSII要求首先調用初始化函數OSInit();這個函數的目的就是在整個系統啓動之前,初始化所有的變量和數據結構。
(2)其中,在OSInit()函數中建立空閒任務OS_TaskIdle();
這個任務總是處於就緒態的,空閒任務的優先級是設置爲最低的。
(3)調用OSInit以後,任務控制塊緩衝池中有OS_MAX_TASKS個任務控制塊,事件控制緩衝區中有OS_MAX_EVENTS個事件控制塊,消息隊列緩衝池OS_Q中有OS_MAX_QS個消息隊列控制塊等等。
2、UCOSII的啓動過程
int main(void)
{
OSInit(); /* 系統初始化*/
/* 創建主任務*/
OSTaskCreate(MainTask, (void *)0, &MainTask_Stk[MainTask_StkSize-1], MainTask_Prio);
OSStart(); /* 開始任務調度*/
return 0;
}
(1)這是我們使用的一個移植到VS2013成功的UCOSII的代碼工程。
裏面有我們需要了解的啓動UCOSII的全部的過程。
(2)剛剛說明的是OSInit()系統的初始化程序,就是爲了初始化UCOSII啓動過程的全部變量和一些內存池。
(3)通過調用OSTaskCreate()創建至少一個任務。
因爲我們到時候,程序的指針SP,會跳出main.c的函數,那麼如果不創建一個任務的話,那麼程序的指針就會跑飛。
(4)OSStart()函數就是爲了進行任務調度的,因爲我們很快就會跳出main.c的函數,不會再跳進來,所以我們需要進行內部的指針跳出。
void OSStart (void)
{
if (OSRunning == OS_FALSE) {
OS_SchedNew(); /* Find highest priority's task priority number */
OSPrioCur = OSPrioHighRdy;
OSTCBHighRdy = OSTCBPrioTbl[OSPrioHighRdy]; /* Point to highest priority task ready to run */
OSTCBCur = OSTCBHighRdy;
OSStartHighRdy(); /* Execute target specific code to start task */
}
}
(1)這是UCOSII啓動的一個關鍵的函數,此函數記錄了我們操作系統是怎麼進入多任務的狀態的。
(2)解析:當OS的狀態等於錯誤的狀態的時候,把當前的最高優先級的任務賦值給OS的當前的優先級。
(3)最高優先級是通過位圖來進行查找的,按上一講已經完全說清楚獲取最高優先級的算法。
(4)OSStartHighRdy()此函數是這個開始函數的關鍵,也就是這個地方進行任務的切換的,就是我們上一節課說明的進入中斷,然後把CPU寄存器的值進行切換,從而跳轉到最高優先級的任務當中。
void OSStartHighRdy()
{
DWORD dwID;
OSInitTrace(100000);
OS_ENTER_CRITICAL();
OSTaskSwHook();
++OSRunning;
OSCtxSwW32Event = CreateEvent(NULL,FALSE,FALSE,NULL);
OSCtxSwW32Handle = CreateThread( NULL, 0, OSCtxSwW32, 0, 0, &dwID );
SetPriorityClass(OSCtxSwW32Handle,THREAD_PRIORITY_HIGHEST);
#ifdef SET_AFFINITY_MASK
if( SetThreadAffinityMask( OSCtxSwW32Handle, 1 ) == 0 ) {
#ifdef OS_CPU_TRACE
OS_Printf("Error: SetThreadAffinityMask\n");
#endif
}
#endif
SetThreadPriority(OSCtxSwW32Handle,THREAD_PRIORITY_TIME_CRITICAL);
OSTick32Handle = CreateThread( NULL, 0, OSTickW32, 0, 0, &dwID );
SetPriorityClass(OSTick32Handle,THREAD_PRIORITY_HIGHEST);
#ifdef SET_AFFINITY_MASK
if( SetThreadAffinityMask( OSTick32Handle, 1 ) == 0 )
{
#ifdef OS_CPU_TRACE
OS_Printf("Error: SetThreadAffinityMask\n");
#endif
}
#endif
SetThreadPriority(OSTick32Handle,THREAD_PRIORITY_HIGHEST);
#ifdef WIN_MM_TICK
timeGetDevCaps(&OSTimeCap, sizeof(OSTimeCap));
if( OSTimeCap.wPeriodMin < WIN_MM_MIN_RES )
OSTimeCap.wPeriodMin = WIN_MM_MIN_RES;
timeBeginPeriod(OSTimeCap.wPeriodMin);
OSTickEventHandle = CreateEvent(NULL, FALSE, FALSE, NULL);
OSTickTimer = timeSetEvent((1000/OS_TICKS_PER_SEC),OSTimeCap.wPeriodMin,(LPTIMECALLBACK)OSTickEventHandle, dwID,TIME_PERIODIC|TIME_CALLBACK_EVENT_SET);
#endif
SS_SP = (OS_EMU_STK*) OSTCBHighRdy->OSTCBStkPtr; /* OSTCBCur = OSTCBHighRdy; */
/* OSPrioCur = OSPrioHighRdy; */
ResumeThread(SS_SP->Handle);
OS_EXIT_CRITICAL();
WaitForSingleObject(OSCtxSwW32Handle,INFINITE);
#ifdef WIN_MM_TICK
timeKillEvent(OSTickTimer);
timeEndPeriod(OSTimeCap.wPeriodMin);
CloseHandle(OSTickEventHandle);
#endif
CloseHandle(OSTick32Handle);
CloseHandle(OSCtxSwW32Event);
}
此函數就是最終的函數,與硬件所在的平臺是不一樣的。
參考代碼:移植UCOSII到VS2013程序