從零開始學習UCOSII操作系統3--UCOSII啓動過程

從零開始學習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程序


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