新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > 移植μC/OS-Ⅱ

        移植μC/OS-Ⅱ

        作者: 時間:2016-10-08 來源:網絡 收藏

        8.03.03OS_STK_GROWTH

        絕大多數的微處理器和微控制器的堆棧是從上往下長的。 但是某些處理器是用另外一種方式工作的。μC/OS-Ⅱ被設計成兩種情況都可以處理,只要在結構常量OS_STK_GROWTH[L8.1(4)]中指定堆棧的生長方式(如下所示)就可以了。

        置OS_STK_GROWTH為0表示堆棧從下往上長。

        置OS_STK_GROWTH為1表示堆棧從上往下長。

        8.03.04OS_TASK_SW()

        OS_TASK_SW()[L8.1(5)]是一個宏,它是在μC/OS-Ⅱ從低優先級任務切換到最高優先級任務時被調用的。OS_TASK_SW()總是在任務級代碼中被調用的。另一個函數OSIntExit()被用來在ISR使得更高優先級任務處于就緒狀態時,執行任務切換功能。任務切換只是簡單的將處理器寄存器保存到將被掛起的任務的堆棧中, 并且將更高優先級的任務從堆棧中恢復出來。

        在μC/OS-Ⅱ中,處于就緒狀態的任務的堆棧結構看起來就像剛發生過中斷并將所有的寄存器保存到堆棧中的情形一樣。換句話說,μC/OS-Ⅱ要運行處于就緒狀態的任務必須要做的事就是將所有處理器寄存器從任務堆棧中恢復出來,并且執行中斷的返回。為了切換任務可以通過執行OS_TASK_SW()來產生中斷。大部分的處理器會提供軟中斷或是陷阱(TRAP)指令來完成這個功能。ISR或是陷阱處理函數(也叫做異常處理函數)的向量地址必須指向匯編語言函數OSCtxSw()(參看8.04.02)。

        例如,在Intel或者AMD80x86處理器上可以使用INT指令。但是中斷處理向量需要指向OSCtxSw()。Motorola68HC11處理器使用的是SWI指令,同樣,SWI的向量地址仍是OSCtxSw()。還有,Motorola680x0/CPU32可能會使用16個陷阱指令中的一個。當然,選中的陷阱向量地址還是OSCtxSw()。

        一些處理器如ZilogZ80并不提供軟中斷機制。在這種情況下,用戶需要盡自己的所能將堆棧結構設置成與中斷堆棧結構一樣。OS_TASK_SW()只會簡單的調用OSCtxSw()而不是將某個向量指向OSCtxSw()。μC/OS已經被移植到了Z80處理器上,μC/OS-Ⅱ也同樣可以。

        8.04OS_CPU_A.ASM

        μC/OS-Ⅱ的移植實例要求用戶編寫四個簡單的匯編語言函數:

        OSStartHighRdy()

        OSCtxSw()

        OSIntCtxSw()

        OSTickISR()

        如果用戶的編譯器支持插入匯編語言代碼的話, 用戶就可以將所有與處理器相關的代碼放到OS_CPU_C.C文件中,而不必再擁有一些分散的匯編語言文件。

        8.04.01OSStartHighRdy()

        使就緒狀態的任務開始運行的函數叫做OSStart(),如下所示。在用戶調用OSStart()之前,用戶必須至少已經建立了自己的一個任務(參看OSTaskCreate()和OSTaskCteateExt())。OSStartHighRdy()假設OSTCBHighRdy指向的是優先級最高的任務的任務控制塊。前面曾提到過,在μC/OS-Ⅱ中處于就緒狀態的任務的堆棧結構看起來就像剛發生過中斷并將所有的寄存器保存到堆棧中的情形一樣。要想運行最高優先級任務,用戶所要做的是將所有處理器寄存器按順序從任務堆棧中恢復出來,并且執行中斷的返回。為了簡單一點,堆棧指針總是儲存在任務控制塊(即它的OS_TCB)的開頭。換句話說,也就是要想恢復的任務堆棧指針總是儲存在OS_TCB的0偏址內存單元中。

        voidOSStartHighRdy(void)

        {

        CalluserdefinableOSTaskSwHook();

        Getthestackpointerofthetasktoresume:

        Stackpointer=OSTCBHighRdy->OSTCBStkPtr;

        OSRunning=TRUE;

        Restoreallprocessorregistersfromthenewtask'sstack;

        Executeareturnfrominterruptinstruction;

        }

        注意,OSStartHighRdy()必須調用OSTaskSwHook(),因為用戶正在進行任務切換的部分工作——用戶在恢復最高優先級任務的寄存器。而OSTaskSwHook()可以通過檢查OSRunning來知道是OSStartHighRdy()在調用它(OSRunning為FALSE)還是正常的任務切換在調用它(OSRunning為TRUE).

        OSStartHighRdy()還必須在最高優先級任務恢復之前和調用OSTaskSwHook()之后設置OSRunning為TRUE。

        8.04.02OSCtxSw()

        如前面所述, 任務級的切換問題是通過發軟中斷命令或依靠處理器執行陷阱指令來完成的。中斷服務例程,陷阱或異常處理例程的向量地址必須指向OSCtxSw()。

        如果當前任務調用μC/OS-Ⅱ提供的系統服務,并使得更高優先級任務處于就緒狀態,μC/OS-Ⅱ就會借助上面提到的向量地址找到OSCtxSw()。在系統服務調用的最后,μC/OS-Ⅱ會調用OSSched(),并由此來推斷當前任務不再是要運行的最重要的任務了。OSSched()先將最高優先級任務的地址裝載到OSTCBHighRdy中,再通過調用OS_TASK_SW()來執行軟中斷或陷阱指令。注意,變量OSTCBCur早就包含了指向當前任務的任務控制塊(OS_TCB)的指針。 軟中斷(或陷阱)指令會強制一些處理器寄存器(比如返回地址和處理器狀態字)到當前任務的堆棧中,并使處理器執行OSCtxSw()。OSCtxSw()的原型如程序清單L8.2所示。這些代碼必須寫在匯編語言中,因為用戶不能直接從C中訪問CPU寄存器。注意在OSCtxSw()和用戶定義的函數OSTaskSwHook()的執行過程中,中斷是禁止的。

        程序清單 L8.2 OSCtxSw()的原型

        voidOSCtxSw(void)

        {

        保存處理器寄存器;

        將當前任務的堆棧指針保存到當前任務的OS_TCB中:

        OSTCBCur->OSTCBStkPtr=Stackpointer;

        調用用戶定義的OSTaskSwHook();

        OSTCBCur=OSTCBHighRdy;

        OSPrioCur=OSPrioHighRdy;

        得到需要恢復的任務的堆棧指針:

        Stackpointer=OSTCBHighRdy->OSTCBStkPtr;

        將所有處理器寄存器從新任務的堆棧中恢復出來;

        執行中斷返回指令;

        }

        8.04.03OSIntCtxSw()

        OSIntExit()通過調用OSIntCtxSw()來從ISR中執行切換功能。 因為OSIntCtxSw()是在ISR中被調用的,所以可以斷定所有的處理器寄存器都被正確地保存到了被中斷的任務的堆棧之中。實際上除了我們需要的東西外,堆棧結構中還有其它的一些東西。OSIntCtxSw()必須要清理堆棧,這樣被中斷的任務的堆棧結構內容才能滿足我們的需要。

        要想了解OSIntCtxSw(),用戶可以看看μC/OS-Ⅱ調用該函數的過程。用戶可以參看圖8.2來幫助理解下面的描述。假定中斷不能嵌套(即ISR不會被中斷),中斷是允許的,并且處理器正在執行任務級的代碼。當中斷來臨的時候,處理器會結束當前的指令,識別中斷并且初始化中斷處理過程, 包括將處理器的狀態寄存器和返回被中斷的任務的地址保存到堆棧中[F8.2(1)]。至于究竟哪些寄存器保存到了堆棧上,以及保存的順序是怎樣的,并不重要。



        關鍵詞:

        評論


        相關推薦

        技術專區

        關閉
        主站蜘蛛池模板: 北安市| 灵山县| 虞城县| 闵行区| 钟祥市| 尼勒克县| 运城市| 巴南区| 清远市| 哈密市| 志丹县| 罗定市| 南雄市| 南部县| 双桥区| 丘北县| 洪江市| 桂林市| 江安县| 汉寿县| 灌云县| 民乐县| 玉林市| 黄骅市| 保康县| 博客| 南澳县| 阳城县| 长沙县| 平塘县| 洪泽县| 宾阳县| 南华县| 阿坝| 辽中县| 芜湖县| 湘乡市| 昌邑市| 太康县| 合作市| 荥经县|