<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

          移植μC/OS-Ⅱ

          作者: 時間:2016-10-08 來源:網(wǎng)絡(luò) 收藏

          8.03.03OS_STK_GROWTH

          絕大多數(shù)的微處理器和微控制器的堆棧是從上往下長的。 但是某些處理器是用另外一種方式工作的。μC/OS-Ⅱ被設(shè)計成兩種情況都可以處理,只要在結(jié)構(gòu)常量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-Ⅱ從低優(yōu)先級任務(wù)切換到最高優(yōu)先級任務(wù)時被調(diào)用的。OS_TASK_SW()總是在任務(wù)級代碼中被調(diào)用的。另一個函數(shù)OSIntExit()被用來在ISR使得更高優(yōu)先級任務(wù)處于就緒狀態(tài)時,執(zhí)行任務(wù)切換功能。任務(wù)切換只是簡單的將處理器寄存器保存到將被掛起的任務(wù)的堆棧中, 并且將更高優(yōu)先級的任務(wù)從堆棧中恢復(fù)出來。

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

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

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

          8.04OS_CPU_A.ASM

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

          OSStartHighRdy()

          OSCtxSw()

          OSIntCtxSw()

          OSTickISR()

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

          8.04.01OSStartHighRdy()

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

          voidOSStartHighRdy(void)

          {

          CalluserdefinableOSTaskSwHook();

          Getthestackpointerofthetasktoresume:

          Stackpointer=OSTCBHighRdy->OSTCBStkPtr;

          OSRunning=TRUE;

          Restoreallprocessorregistersfromthenewtask'sstack;

          Executeareturnfrominterruptinstruction;

          }

          注意,OSStartHighRdy()必須調(diào)用OSTaskSwHook(),因?yàn)橛脩粽谶M(jìn)行任務(wù)切換的部分工作——用戶在恢復(fù)最高優(yōu)先級任務(wù)的寄存器。而OSTaskSwHook()可以通過檢查OSRunning來知道是OSStartHighRdy()在調(diào)用它(OSRunning為FALSE)還是正常的任務(wù)切換在調(diào)用它(OSRunning為TRUE).

          OSStartHighRdy()還必須在最高優(yōu)先級任務(wù)恢復(fù)之前和調(diào)用OSTaskSwHook()之后設(shè)置OSRunning為TRUE。

          8.04.02OSCtxSw()

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

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

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

          voidOSCtxSw(void)

          {

          保存處理器寄存器;

          將當(dāng)前任務(wù)的堆棧指針保存到當(dāng)前任務(wù)的OS_TCB中:

          OSTCBCur->OSTCBStkPtr=Stackpointer;

          調(diào)用用戶定義的OSTaskSwHook();

          OSTCBCur=OSTCBHighRdy;

          OSPrioCur=OSPrioHighRdy;

          得到需要恢復(fù)的任務(wù)的堆棧指針:

          Stackpointer=OSTCBHighRdy->OSTCBStkPtr;

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

          執(zhí)行中斷返回指令;

          }

          8.04.03OSIntCtxSw()

          OSIntExit()通過調(diào)用OSIntCtxSw()來從ISR中執(zhí)行切換功能。 因?yàn)镺SIntCtxSw()是在ISR中被調(diào)用的,所以可以斷定所有的處理器寄存器都被正確地保存到了被中斷的任務(wù)的堆棧之中。實(shí)際上除了我們需要的東西外,堆棧結(jié)構(gòu)中還有其它的一些東西。OSIntCtxSw()必須要清理堆棧,這樣被中斷的任務(wù)的堆棧結(jié)構(gòu)內(nèi)容才能滿足我們的需要。

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



          關(guān)鍵詞:

          評論


          相關(guān)推薦

          技術(shù)專區(qū)

          關(guān)閉
          看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();