<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>

新聞中心

EEPW首頁(yè) > 嵌入式系統 > 設計應用 > μC/OS-II在51單片機上的移植

μC/OS-II在51單片機上的移植

作者: 時(shí)間:2012-04-27 來(lái)源:網(wǎng)絡(luò ) 收藏

4.1 任務(wù)堆棧初始化函數OSTaskStkInit()
此函數是在任務(wù)創(chuàng )建函數OSTaskCreat()或OSTaskCreatExt()中調用的。因為系統為每個(gè)任務(wù)申請了一個(gè)數組作為棧,當一個(gè)任務(wù)運行時(shí),就把堆棧指針指向本任務(wù)的棧,任務(wù)堆棧初始化函數就是在任務(wù)創(chuàng )建時(shí)將要創(chuàng )建任務(wù)的堆棧進(jìn)行初始化。但C51的堆棧指針SP是8位的,只能在片內RAM的256個(gè)字節內尋址。因其尋址空間有限且SP唯一,不能像DSP或ARM那樣為每一段程序或每一種模式定義堆棧,需小心管理堆??臻g。為了適應上述情況,需要換一種思路,不是讓SP去指向各任務(wù)堆??臻g,而是把各任務(wù)堆??臻g的內容復制到系統棧中。至于堆棧數組空間要有多大以及堆棧數組空間里放些什么內容,可以借鑒keil中中斷函數的壓棧情況,當中斷函數不指定寄存器組時(shí),編譯器一般將PC、ACC、B、DPTR、PSW、R0~R7寄存器入棧,其中PC和DPTR是雙字節的,其它都是單字節的,一共15個(gè)字節,所以把堆棧數組設計成至少15個(gè)字節的,以保證任務(wù)所用的寄存器都在堆棧數組中包含著(zhù)。因為每個(gè)數組里放的是寄存器的值,在此就把這每個(gè)任務(wù)的堆棧數組叫做寄存器數組,暫且把寄存器數組設計成15個(gè)字節,依次存放PC、ACC、B、DPTR、PSW、R0~R7。
函數OSTaskStkInit()傳遞4個(gè)參數,第1個(gè)參數task是所創(chuàng )建任務(wù)的起始地址,這個(gè)參數須保存到PC在寄存器數組的對應位置,第2個(gè)參數ppdata是所創(chuàng )建任務(wù)的參數,C51規則中用R1~R3來(lái)傳遞參數指針,這個(gè)參數須存放到R1~R3在寄存器數組中的對應位置。第3個(gè)參數ptos是棧底指針,從當前地址開(kāi)始初始化堆棧指針,第4個(gè)參數opt是附加參數,一般不用。
4.2 運行等待任務(wù)中優(yōu)先級最高任務(wù)函數OSStartHighRdy()
此函數在啟動(dòng)操作系統函數OSStart()的最后一行調用,且此函數不返回,經(jīng)過(guò)此函數后μC/OS接管系統。OSStartHighRdy()不是去調用用戶(hù)任務(wù)函數,而是讓PC指針指向任務(wù)函數首地址。且任務(wù)函數的傳遞參數只有一個(gè),若此參數正確,則可保證任務(wù)函數運行正確。在調用OSStartHighRdy()之前OSStart()已經(jīng)把最高優(yōu)先級任務(wù)的任務(wù)表準備好了,只要把最高優(yōu)先級任務(wù)表的數據恢復到堆棧中,再執行返回指令即可,以上最關(guān)鍵的是如何讓其返回到最高優(yōu)先級任務(wù)中而不是返回到被調函數中。
當函數OSStart()調用函數OSStartHighRdy()時(shí),斷點(diǎn)地址入棧;當OSStartHighRdy()執行完之后,返回斷點(diǎn)。在OSStartHighRdy()中把SP及SP-1的值改為最高優(yōu)先級任務(wù)的地址,這樣OSStartHighRdy()就會(huì )返回到最高優(yōu)先級任務(wù)中去運行。
4.3 任務(wù)級的任務(wù)切換函數OSCtxSw()
此函數是保存當前任務(wù)的狀態(tài),然后運行處于就緒態(tài)中的最高優(yōu)先級任務(wù)。前面介紹過(guò)不是更改SP去指向寄存器數組,而是把寄存器數組的數復制到堆棧中。先看下一般的情況,在用戶(hù)任務(wù)MyTask(void*ppdtat)中調用TimeDly(),TimeDly()中調用OSSched(),在OSSched()中有一個(gè)宏OS_TASK_SW(),這個(gè)宏的目的是讓程序進(jìn)人函數OSCtxSw()。參看圖1,就如Fun4為OSCtxSw(),Fun3為OSSched(),Fun2為T(mén)imeDly(),Fun1為MyTask()。ADD_D存的是OSSched()的斷點(diǎn),ADD_C為T(mén)imeDly()的斷點(diǎn),ADD_B為MyTask()的斷點(diǎn)。如果進(jìn)行任務(wù)切換,應該把高優(yōu)先級任務(wù)的地址值賦給ADD_B(即SP-4與SP-5)。
以上考慮的是最簡(jiǎn)單的情況,當任務(wù)比較復雜時(shí),可能更改了ACC、PSW、DPTR或R0~R7的值,在進(jìn)入高優(yōu)先任務(wù)時(shí),寄存器并不是此任務(wù)的寄存器值,運行的結果可能不正確。
在上述情況下如何保證CPU寄存器的值正確,要分兩個(gè)階段。第一個(gè)階段是把CPU寄存器值保存到要掛起任務(wù)的寄存器數組中,當剛進(jìn)入OSCtxSw()時(shí),CPU寄存器的值是要掛起任務(wù)的寄存器值,所以一開(kāi)始就要鎖定CPU寄存器的值。如果OS_TASK_SW()定義為中斷的話(huà),在進(jìn)入OSCtxSw()時(shí),CPU寄存器的值被自動(dòng)壓棧;如果把OS_TASK_SW()定義為函數時(shí),在進(jìn)入函數時(shí)使用內嵌匯編的方法把CPU寄存器入棧。這時(shí)堆棧中又壓入了13個(gè)字節,就如在圖1的ADD_D上又壓入了13個(gè)字節的數據,然后從堆棧中把值取出來(lái)放到相應任務(wù)的寄存器數組中。第二個(gè)階段是把將要執行任務(wù)的寄存器數組的值復制到堆棧中。此時(shí)PC指針在堆棧中對應的位置是SP-17與SP-18,SP到SP-12的13個(gè)字節對應ACC、B、DPTR、PSW、R0~R7。
4.4 中斷級的任務(wù)切換函數OSIntCtxSw()
此函數和上一個(gè)函數基本思想一致,都要保存當前任務(wù)的狀態(tài),運行處于就緒態(tài)中的優(yōu)先級最高的任務(wù)。二者的不同在于,上個(gè)函數的堆棧中SP-17與SP-18是PC值的位置,SP到SP-12是13個(gè)寄存器的位置。當中斷來(lái)時(shí),在中斷中調用函數OSIntExit(),函數OSIntExit()調用函數OSIntCtxSw(),在OSIntCtxSw()中實(shí)現任務(wù)切換。在進(jìn)入函數OSIntExit()之前寄存器的值已經(jīng)入棧,所以運行到本函數時(shí)堆棧中SP-17與SP-18是PC值的位置。SP-4到SP-16是13個(gè)寄存器的位置。在圖1上,上個(gè)函數的13個(gè)寄存器的值被壓入ADD_D上面的13個(gè)字節中,而本函數是在A(yíng)DD_B于A(yíng)DD_C之間壓入的這13個(gè)寄存器。
4.5 周期節拍中斷函數OSTickISR()
這個(gè)函數是給系統提供一個(gè)節拍,一般每秒10~100次。如果節拍頻率太高,μC/OS系統會(huì )占用大量硬件資源;如果太低,任務(wù)間的切換又會(huì )很慢。
此函數首先要保證產(chǎn)生一個(gè)周期性的中斷,可以使用硬件定時(shí)器,也可以從交流電中獲得50/60Hz的時(shí)鐘頻率。這個(gè)函數至少要做3件事:1)進(jìn)入中斷時(shí),把中斷嵌套層數計數器加1,說(shuō)明又進(jìn)入一次中斷,也可以直接調用OSIntEnter()函數;2)調用時(shí)鐘節拍函數OSTimeTick(),告知系統又經(jīng)過(guò)了一個(gè)節拍;3)調用OSIntExit()函數,說(shuō)明要退出中斷了,此函數會(huì )自動(dòng)處理。

5 結束語(yǔ)
文中闡述了在堆??臻g有限的51運行μC/系統的過(guò)程,利用系統棧SP作為數據交換的樞紐。在實(shí)際應用中,如果用系統棧來(lái),只需根據文中的基本思想進(jìn)行適當的改寫(xiě),即可運行于其他處理器上。如果處理器的堆棧指針尋址空間足夠大,也可以為每個(gè)任務(wù)開(kāi)辟一個(gè)棧,通過(guò)改變堆棧指針指向不同任務(wù)的??臻g,來(lái)實(shí)現任務(wù)調度。
通過(guò)在51的運行,可以看出μC/也能在堆??臻g比較少的CPU上運行。

本文引用地址:http://dyxdggzs.com/article/171557.htm

上一頁(yè) 1 2 3 下一頁(yè)

關(guān)鍵詞: 移植 機上 單片 OS-II

評論


相關(guān)推薦

技術(shù)專(zhuān)區

關(guān)閉
国产精品自在自线亚洲|国产精品无圣光一区二区|国产日产欧洲无码视频|久久久一本精品99久久K精品66|欧美人与动牲交片免费播放
<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>