0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

ucos-II移植到51單片機(jī)的解決辦法

ss ? 作者:工程師譚軍 ? 2018-09-11 09:30 ? 次閱讀

本文主要是關(guān)于ucos-II的相關(guān)介紹,并著重對ucos-II移植到51單片機(jī)進(jìn)行了詳盡的闡述。

ucos-II

μC/OS-II由Micrium公司提供,是一個(gè)可移植、可固化的、可裁剪的、占先式多任務(wù)實(shí)時(shí)內(nèi)核,它適用于多種微處理器微控制器和數(shù)字處理芯片(已經(jīng)移植到超過100種以上的微處理器應(yīng)用中)。同時(shí),該系統(tǒng)源代碼開放、整潔、一致,注釋詳盡,適合系統(tǒng)開發(fā)。 μC/OS-II已經(jīng)通過聯(lián)邦航空局(FAA)商用航行器認(rèn)證,符合航空無線電技術(shù)委員會(huì)(RTCA)DO-178B標(biāo)準(zhǔn)。

μC/OS-II被廣泛應(yīng)用于微處理器、微控制器和數(shù)字信號(hào)處理器。

μC/OS-II 的前身是μC/OS,最早出自于1992 年美國嵌入式系統(tǒng)專家Jean J.Labrosse 在《嵌入式系統(tǒng)編程》雜志的5 月和6 月刊上刊登的文章連載,并把μC/OS 的源碼發(fā)布在該雜志的B B S 上。

μC/OS 和μC/OS-II 是專門為計(jì)算機(jī)的嵌入式應(yīng)用設(shè)計(jì)的, 絕大部分代碼是用C語言編寫的。CPU 硬件相關(guān)部分是用匯編語言編寫的、總量約200行的匯編語言部分被壓縮到最低限度,為的是便于移植到任何一種其它的CPU 上。用戶只要有標(biāo)準(zhǔn)的ANSI 的C交叉編譯器,有匯編器、連接器等軟件工具,就可以將μC/OS-II嵌入到開發(fā)的產(chǎn)品中。μC/OS-II 具有執(zhí)行效率高、占用空間小、實(shí)時(shí)性能優(yōu)良和可擴(kuò)展性強(qiáng)等特點(diǎn), 最小內(nèi)核可編譯至 2KB 。μC/OS-II 已經(jīng)移植到了幾乎所有知名的CPU 上。

嚴(yán)格地說uC/OS-II只是一個(gè)實(shí)時(shí)操作系統(tǒng)內(nèi)核,它僅僅包含了任務(wù)調(diào)度,任務(wù)管理,時(shí)間管理,內(nèi)存管理和任務(wù)間的通信和同步等基本功能。沒有提供輸入輸出管理,文件系統(tǒng),網(wǎng)絡(luò)等額外的服務(wù)。但由于uC/OS-II良好的可擴(kuò)展性和源碼開放,這些非必須的功能完全可以由用戶自己根據(jù)需要分別實(shí)現(xiàn)。

uC/OS-II目標(biāo)是實(shí)現(xiàn)一個(gè)基于優(yōu)先級(jí)調(diào)度的搶占式的實(shí)時(shí)內(nèi)核,并在這個(gè)內(nèi)核之上提供最基本的系統(tǒng)服務(wù),如信號(hào)量,郵箱,消息隊(duì)列,內(nèi)存管理,中斷管理等。

uC/OS-II以源代碼的形式發(fā)布,是開源軟件, 但并不意味著它是免費(fèi)軟件。你可以將其用于教學(xué)和私下研究(peaceful research);但是如果你將其用于商業(yè)用途,那么你必須通過Micrium獲得商用許可。

uCOSII移植的一點(diǎn)心得

uCOS-II是一種十分優(yōu)秀實(shí)時(shí)操作系統(tǒng),其在NASA的認(rèn)證通過直接說明了其優(yōu)秀及穩(wěn)健的性能,同時(shí)由于其完全open,所以受到廣大開源愛好者的喜愛。uCOS-II簡單明了,同時(shí)絕大部分代碼都采用ANSI C編寫(除了與CPU相關(guān)代碼外),所以學(xué)習(xí)起來十分容易,是嵌入式學(xué)習(xí)乃至操作系統(tǒng)學(xué)習(xí)最好的入門OS之一。

我主要想講一下自己最近移植uCOS-II的心得,因?yàn)樽罱苍趯W(xué)習(xí)操作系統(tǒng),所以這段日子對于uCOS-II的學(xué)習(xí)的確也讓我對于操作系統(tǒng)有了一個(gè)實(shí)際深刻的認(rèn)識(shí)。

uCOS-II移植其實(shí)十分簡單。對于一個(gè)處理器,需要做的工作只有:修改三個(gè)文件――os_cpu_c.c、os_cpu.h、os_cpu_a.asm(ASM文件根據(jù)編譯器不同而又有一些不同)。

用另一種方式說,需要做的工作就是修改五個(gè)函數(shù):

1、os_cpu_c.c:OSTaskStkInit;

2、os_cpu_a.asm:OSStartHighRdy、OSCtxSw、OSIntCtxSw、OSTickISR;

OSTaskStkInit函數(shù)是針對CPU壓棧的函數(shù),需要模仿出CPU初始化后的寄存器狀況。也使需要修改的唯一一個(gè)C語言函數(shù)。其他的都是匯編函數(shù)。

如果我們可以從uCOS-II官方網(wǎng)站上找到相同CPU或是相似的同一家族的CPU移植代碼,那么我們的移植工作將會(huì)簡單得多。因?yàn)橹辽傥覀兛梢灾挥昧私膺@個(gè)處理器的內(nèi)部結(jié)構(gòu),而不用細(xì)致的了解其匯編指令等很多繁瑣而沒有意義的事情(有的處理器你可能一輩子不再用它,了解得太細(xì)致只是在浪費(fèi)時(shí)間)。

譬如,此次我要做的是將uCOS-II移植到瑞薩M16C/62A上,而官方網(wǎng)站上只有其62P的移植代碼,于是乎我就將二者的datasheet在CPU的寄存器、中斷部分仔細(xì)比對,發(fā)現(xiàn)二者區(qū)別很小。最大的區(qū)別恐怕就在CPU內(nèi)部寄存器中的INTBL和PC寄存器二者順序相反吧,這只要在相關(guān)部分注意就可以了,所以很容易就搞定了CPU相關(guān)代碼部分。

總結(jié)一下移植中浪費(fèi)我時(shí)間的幾個(gè)小錯(cuò)誤吧,這完全是個(gè)人粗心導(dǎo)致的失誤:

1、在os_cpu.h文件中需要用宏定義將OS_TASK_SW指向OSCtxSw函數(shù),而我開始像以前一樣直接將OSCtxSw函數(shù)與0號(hào)軟終端鏈接起來,結(jié)果發(fā)現(xiàn)函數(shù)調(diào)用不成功。后來直接用宏定義將OS_TASK_SW define為OSCtxSw函數(shù),初步調(diào)試通過,即驗(yàn)證OSCtxSw函數(shù)正確,但是到后來調(diào)用任務(wù)的時(shí)候卻發(fā)現(xiàn)任務(wù)切換不正常,不得不重新將函數(shù)與中斷結(jié)合起來,當(dāng)然就不能還是0號(hào)中斷了,而是改為一個(gè)比較保險(xiǎn)的軟終端,這個(gè)問題糾結(jié)了很長時(shí)間。

2、在看書的時(shí)候不仔細(xì)直接導(dǎo)致我犯了一個(gè)大錯(cuò)誤。起初以為task只要是能夠達(dá)到功能的死循環(huán)即可。所以每個(gè)task函數(shù)都是while(1)或者for(;;;),但是我沒有注意到一點(diǎn)就是每個(gè)task里面都應(yīng)該有OSTimeDly()函數(shù),否則將導(dǎo)致任務(wù)之間不能跳轉(zhuǎn)。所以最初的實(shí)驗(yàn)現(xiàn)象是永遠(yuǎn)只有一個(gè)任務(wù)在運(yùn)行,但是任務(wù)不能切換……

3、未注意到版本之間的區(qū)別。我們知道在新版本的uCOS-II中,添加了一個(gè)文件os_tmr.c,主要是在timer上面做了很大的調(diào)整,但是我沒有注意到這一點(diǎn),仍舊按照老版本的方法調(diào)試,導(dǎo)致函數(shù)調(diào)用讓我完全不知所措。最后注意到os的源代碼的不同,仔細(xì)閱讀源代碼之后知道了其用法,其實(shí)如果不需要timer太強(qiáng)大的功能,只要在os_cfg.h文件中將OS_TMR_EN設(shè)置為0即可。這在習(xí)慣老版本調(diào)試方法的同學(xué)而言是很好的方法。

ucos-II移植到51單片機(jī)的解決辦法

先來了解和51移植相關(guān)的三個(gè)概念:

第一,移植UCOS必須要了解編譯器,我們一般使用的51編譯器都是KEIL。值得一提的是KEIL對可重入函數(shù)的處理。由于51單片機(jī)的堆棧指針是8位的,所以硬件堆棧只能設(shè)置在內(nèi)部RAM的DATA區(qū)和IDATA區(qū)(DATA、IDATA、PDATA、XDATA、CODE這些概念相關(guān)資料很多,我不想在此處滋述),所以51的堆棧是很緊張的。于是,KEIL將函數(shù)內(nèi)的動(dòng)態(tài)變量和函數(shù)傳遞的參數(shù)(當(dāng)然有一部分參數(shù)是用寄存器直接傳送的),放在分配的固定數(shù)據(jù)段中,函數(shù)執(zhí)行時(shí)在固定的數(shù)據(jù)段中去取得相關(guān)的數(shù)據(jù),而不是像傳統(tǒng)的CPU都用堆棧來處理,這就導(dǎo)致了函數(shù)不可重入,因?yàn)楫?dāng)一個(gè)函數(shù)沒執(zhí)行完成時(shí)再次執(zhí)行會(huì)把數(shù)據(jù)段里的內(nèi)容覆蓋掉。為了使函數(shù)可重入KEIL引入了仿真堆棧的概念(重入函數(shù)需在函數(shù)定義后面加上reentrant關(guān)鍵字),用仿真堆棧來傳遞參數(shù)及分配動(dòng)態(tài)變量,就好像傳統(tǒng)堆棧的入棧、出棧操作一般,如此函數(shù)第二次進(jìn)入執(zhí)行時(shí),就不會(huì)覆蓋掉上一次的變量和參數(shù),仿真堆棧實(shí)現(xiàn)原理詳見http://hi.baidu.com/lyb1900/blog/item/99b6313defc2b40abaa167fe.html 。但是,KEIL的這一機(jī)制會(huì)給我們移植造成了麻煩,任務(wù)切換時(shí)不僅要保存好硬件堆棧內(nèi)容,還要保存好仿真堆棧的內(nèi)容。(建議先理解仿真堆棧的概念)

第二,其他類型的CPU可以在任務(wù)切換時(shí)先將SP指針保存到被中斷任務(wù)的OSTCBCur-》OSTCBStkPtr中,再將高優(yōu)先級(jí)任務(wù)的OSTCBCur-》OSTCBStkPtr恢復(fù)到SP中就可以了,各個(gè)任務(wù)使用各自的堆棧空間,互不干擾,切換也很方便。而51的堆棧指針是8位的,SP只能指向內(nèi)部RAM空間,但是內(nèi)部RAM很小,根本不可能將所有任務(wù)堆棧都設(shè)置在內(nèi)部RAM中(DATA和IDATA區(qū))。所以,51只能設(shè)置一個(gè)固定的硬件堆棧,每個(gè)任務(wù)可以在外部RAM中設(shè)置各自的任務(wù)堆棧,任務(wù)切換時(shí),將本任務(wù)所使用到的硬件堆棧的長度和內(nèi)容保存到任務(wù)堆棧中,然后將高優(yōu)先級(jí)任務(wù)的用戶堆棧里的內(nèi)容恢復(fù)到硬件堆棧中。所以51切換任務(wù)會(huì)比較慢。

第三,在KEIL的工程配置Target選項(xiàng)中會(huì)有一個(gè)Memory Model選項(xiàng)。用鼠標(biāo)點(diǎn)擊Memory Model的下拉箭頭,會(huì)有3個(gè)選項(xiàng)。

Small:變量存儲(chǔ)在內(nèi)部ram里。

Compact:變量存儲(chǔ)在外部ram里,使用頁8位間接尋址

Large:變量存儲(chǔ)在外部Ram里,使用16位間接尋址。

這三個(gè)變量決定了定義的變量在不加存儲(chǔ)類型關(guān)鍵字時(shí),變量存放的位置。這一點(diǎn)很多網(wǎng)站、資料都說的很明白。但是其實(shí)還有一點(diǎn)很多資料都是沒說的。它還默認(rèn)決定了上述仿真堆棧的位置。這一點(diǎn)在51的啟動(dòng)代碼STARTUP.asm中能體現(xiàn)出來。其中有一段如下:

; Stack Space for reentrant functions in the SMALL model.

IBPSTACK EQU 1 ; set to 1 if small reentrant is used.

IBPSTACKTOP EQU 0FFH+1 ; set top of stack to highest location+1.

;

; Stack Space for reentrant functions in the LARGE model.

XBPSTACK EQU 0 ; set to 1 if large reentrant is used.

XBPSTACKTOP EQU 7FFFH+1; set top of stack to highest location+1.

;

; Stack Space for reentrant functions in the COMPACT model.

PBPSTACK EQU 0 ; set to 1 if compact reentrant is used.

PBPSTACKTOP EQU 7FFFH+1; set top of stack to highest location+1.

IF IBPSTACK 《》 0

EXTRN DATA (?C_IBP)

MOV ?C_IBP,#LOW IBPSTACKTOP

ENDIF

IF XBPSTACK 《》 0

EXTRN DATA (?C_XBP)

MOV ?C_XBP,#HIGH XBPSTACKTOP

MOV ?C_XBP+1,#LOW XBPSTACKTOP

ENDIF

IF PBPSTACK 《》 0

EXTRN DATA (?C_PBP)

MOV ?C_PBP,#LOW PBPSTACKTOP

ENDIF

注釋講的很清楚,根據(jù)所選模式,編譯器會(huì)將IBPSTACK、PBPSTACK或者XBPSTACK設(shè)置為1,就決定了仿真堆棧在IDATA區(qū)、PDAIA區(qū)還是XDATA區(qū)。對應(yīng)的,KEIL會(huì)自動(dòng)分配一個(gè)仿真堆棧指針,分別是?C_IBP、?C_PBP和(?C_XBP、?C_XBP+1),由于尋址XDATA區(qū)需要16位地址,所以需要兩個(gè)字節(jié)。這三個(gè)指針是KEIL根據(jù)選擇的Memory Model選項(xiàng)自動(dòng)分配的。

注意:不要試圖在選擇好模式后將仿真堆棧設(shè)置在另一模式的空間中。比如,我用的小模式編譯,仿真堆棧在IDATA區(qū),用的仿真堆棧指針是?C_IBP,但是我現(xiàn)在在啟動(dòng)代碼中將IBPSTACK定義為0,將XBPSTACK設(shè)置為1,看起來我們先把仿真堆棧設(shè)置在XDATA區(qū)了,但實(shí)際上其它代碼段中使用的仿真堆棧指針任然是?C_IBP。有趣的是,KEIL還為我們的啟動(dòng)代碼做了一個(gè)很友好的列表框選擇界面。但實(shí)際上選擇好編譯模式后,仿真堆棧使用空間是不能更改的,不知道KEIL為什么這么做?但是我們有時(shí)候要根據(jù)單片機(jī)的型號(hào)選擇仿真堆棧的起始地址。

講了那么多,應(yīng)該來看看關(guān)于堆棧的組織了,首先是不知道哪位前輩移植的,用的小模式編譯的堆棧結(jié)構(gòu):

ucos-II移植到51單片機(jī)的解決辦法

每個(gè)任務(wù)分都需要配一個(gè)任務(wù)堆棧,OSTCBCur-》OSTCBStkPtr指向任務(wù)堆棧的棧底,任務(wù)堆棧的首字節(jié)是仿真堆棧指針?C_IBP(由于是小模式編譯,所以使用的仿真堆棧設(shè)置在IDAIA區(qū))。用戶堆棧中緊接著存放的是該任務(wù)的仿真堆棧中的內(nèi)容。再接著是系統(tǒng)堆棧(就是SP指針?biāo)傅亩褩#┑拈L度,最后是系統(tǒng)堆棧的內(nèi)容。

任務(wù)在切換時(shí),首先將當(dāng)前的?C_IBP的值保存到本任務(wù)堆棧的首地址中,然后將仿真堆棧的全部內(nèi)容復(fù)制到任務(wù)堆棧中(仿真堆棧棧底固定在IDATA區(qū)的最高字節(jié)0xff,可以根據(jù)(0xff-?C_IBP+1)的值來確定所使用的仿真堆棧的長度),接著保存系統(tǒng)堆棧的長度(系統(tǒng)堆棧設(shè)置在DATA或IDATA區(qū)中,系統(tǒng)堆棧的棧底的地址我們可以在啟動(dòng)代碼中設(shè)置,長度可以用(SP-Stack+1)來計(jì)算得到)最后將所用的系統(tǒng)堆棧中的內(nèi)容復(fù)制到任務(wù)堆棧中。

然后得到高優(yōu)先級(jí)的任務(wù)堆棧,首先恢復(fù)高優(yōu)先級(jí)任務(wù)的?C_IBP,然后計(jì)算出高優(yōu)先級(jí)任務(wù)所用仿真堆棧的長度,將保存的仿真堆棧的內(nèi)容一一恢復(fù)到仿真堆棧中,然后得到系統(tǒng)棧的長度,再將保存的系統(tǒng)堆棧的內(nèi)容恢復(fù)到系統(tǒng)堆棧中,最后恢復(fù)SP指針并執(zhí)行RETI返回指令,便實(shí)現(xiàn)了任務(wù)切換。

任務(wù)被打斷時(shí)將仿真堆棧和系統(tǒng)堆棧的內(nèi)容全都備份到任務(wù)堆棧中,在恢復(fù)運(yùn)行時(shí)將相應(yīng)的內(nèi)容還原到系統(tǒng)堆棧和仿真堆棧中。

這種方法的缺點(diǎn)是,任務(wù)切換將會(huì)變的很慢,因?yàn)橐謩e拷貝和恢復(fù)仿真堆棧和系統(tǒng)堆棧的全部內(nèi)容。完全可以將仿真堆棧設(shè)置在XDATA區(qū)中,任務(wù)切換時(shí),只需保存和恢復(fù)?C_XBP指針就行了,而不必每次都拷貝和恢復(fù)仿真堆棧的全部內(nèi)容。由于SP指針只有8位,系統(tǒng)堆棧只能設(shè)置在內(nèi)部RAM中。

再來看看楊屹大俠大模式編譯下的堆棧結(jié)構(gòu):

ucos-II移植到51單片機(jī)的解決辦法

同樣,每個(gè)任務(wù)分配一個(gè)任務(wù)堆棧,OSTCBCur-》OSTCBStkPtr指向任務(wù)堆棧的棧底,任務(wù)堆棧的首字節(jié)是系統(tǒng)堆棧的長度,接著是系統(tǒng)堆棧的全部內(nèi)容。再接著是仿真堆棧指針?C_XBP的高低字節(jié)(因?yàn)槭谴竽J骄幾g,所以仿真堆棧在XDATA區(qū)),任務(wù)堆棧再高的字節(jié)是作為仿真堆棧用的,用戶堆棧的棧頂就是仿真堆棧的棧底。

任務(wù)切換時(shí),首先計(jì)算任務(wù)使用的系統(tǒng)堆棧的長度,將長度保存在任務(wù)堆棧棧底,然后將使用的系統(tǒng)堆棧的內(nèi)容全部復(fù)制到任務(wù)堆棧中,最后保存當(dāng)前的?C_XBP仿真堆棧指針的高低字節(jié)。

接著恢復(fù)高優(yōu)先級(jí)任務(wù)的信息,先得到堆棧長度,將備份的堆棧內(nèi)容恢復(fù)到系統(tǒng)堆棧中,并恢復(fù)SP指針(根據(jù)長度和系統(tǒng)堆棧的棧底可以計(jì)算出SP指針的值)。最后恢復(fù)?C_XBP的高低字節(jié)。便實(shí)現(xiàn)了任務(wù)的切換。

任務(wù)切換時(shí)將系統(tǒng)堆棧的內(nèi)容和仿真堆棧指針保存起來,再將高優(yōu)先級(jí)任務(wù)的仿真堆棧指針和系統(tǒng)堆棧的內(nèi)容恢復(fù)。

和上述的小模式下的切換過程相比,仿真堆棧的內(nèi)容在任務(wù)切換時(shí)不需要保存和恢復(fù)了,任務(wù)切換速度會(huì)提高不少。但是讀過楊屹大俠代碼的朋友肯定知道,每個(gè)任務(wù)堆棧的大小都要設(shè)置成相同。這對于有些堆棧使用很少的任務(wù)來說是很浪費(fèi)的,而且51的RAM本來就那么緊張?仿真堆棧被設(shè)置在任務(wù)堆棧的最高地址處,細(xì)心的朋友會(huì)發(fā)現(xiàn),堆棧檢測函數(shù)肯定是無法運(yùn)行了。

正是意識(shí)到這些缺陷,我對楊屹大俠移植的代碼進(jìn)行了一些改動(dòng),堆棧結(jié)構(gòu)也有較大改變,使用的也是大模式編譯:

ucos-II移植到51單片機(jī)的解決辦法

先來了解和51移植相關(guān)的三個(gè)概念:

第一,移植UCOS必須要了解編譯器,我們一般使用的51編譯器都是KEIL。值得一提的是KEIL對可重入函數(shù)的處理。由于51單片機(jī)的堆棧指針是8位的,所以硬件堆棧只能設(shè)置在內(nèi)部RAM的DATA區(qū)和IDATA區(qū)(DATA、IDATA、PDATA、XDATA、CODE這些概念相關(guān)資料很多,我不想在此處滋述),所以51的堆棧是很緊張的。于是,KEIL將函數(shù)內(nèi)的動(dòng)態(tài)變量和函數(shù)傳遞的參數(shù)(當(dāng)然有一部分參數(shù)是用寄存器直接傳送的),放在分配的固定數(shù)據(jù)段中,函數(shù)執(zhí)行時(shí)在固定的數(shù)據(jù)段中去取得相關(guān)的數(shù)據(jù),而不是像傳統(tǒng)的CPU都用堆棧來處理,這就導(dǎo)致了函數(shù)不可重入,因?yàn)楫?dāng)一個(gè)函數(shù)沒執(zhí)行完成時(shí)再次執(zhí)行會(huì)把數(shù)據(jù)段里的內(nèi)容覆蓋掉。為了使函數(shù)可重入KEIL引入了仿真堆棧的概念(重入函數(shù)需在函數(shù)定義后面加上reentrant關(guān)鍵字),用仿真堆棧來傳遞參數(shù)及分配動(dòng)態(tài)變量,就好像傳統(tǒng)堆棧的入棧、出棧操作一般,如此函數(shù)第二次進(jìn)入執(zhí)行時(shí),就不會(huì)覆蓋掉上一次的變量和參數(shù),仿真堆棧實(shí)現(xiàn)原理詳見http://hi.baidu.com/lyb1900/blog/item/99b6313defc2b40abaa167fe.html 。但是,KEIL的這一機(jī)制會(huì)給我們移植造成了麻煩,任務(wù)切換時(shí)不僅要保存好硬件堆棧內(nèi)容,還要保存好仿真堆棧的內(nèi)容。(建議先理解仿真堆棧的概念)

第二,其他類型的CPU可以在任務(wù)切換時(shí)先將SP指針保存到被中斷任務(wù)的OSTCBCur-》OSTCBStkPtr中,再將高優(yōu)先級(jí)任務(wù)的OSTCBCur-》OSTCBStkPtr恢復(fù)到SP中就可以了,各個(gè)任務(wù)使用各自的堆??臻g,互不干擾,切換也很方便。而51的堆棧指針是8位的,SP只能指向內(nèi)部RAM空間,但是內(nèi)部RAM很小,根本不可能將所有任務(wù)堆棧都設(shè)置在內(nèi)部RAM中(DATA和IDATA區(qū))。所以,51只能設(shè)置一個(gè)固定的硬件堆棧,每個(gè)任務(wù)可以在外部RAM中設(shè)置各自的任務(wù)堆棧,任務(wù)切換時(shí),將本任務(wù)所使用到的硬件堆棧的長度和內(nèi)容保存到任務(wù)堆棧中,然后將高優(yōu)先級(jí)任務(wù)的用戶堆棧里的內(nèi)容恢復(fù)到硬件堆棧中。所以51切換任務(wù)會(huì)比較慢。

第三,在KEIL的工程配置Target選項(xiàng)中會(huì)有一個(gè)Memory Model選項(xiàng)。用鼠標(biāo)點(diǎn)擊Memory Model的下拉箭頭,會(huì)有3個(gè)選項(xiàng)。

Small:變量存儲(chǔ)在內(nèi)部ram里。

Compact:變量存儲(chǔ)在外部ram里,使用頁8位間接尋址

Large:變量存儲(chǔ)在外部Ram里,使用16位間接尋址。

這三個(gè)變量決定了定義的變量在不加存儲(chǔ)類型關(guān)鍵字時(shí),變量存放的位置。這一點(diǎn)很多網(wǎng)站、資料都說的很明白。但是其實(shí)還有一點(diǎn)很多資料都是沒說的。它還默認(rèn)決定了上述仿真堆棧的位置。這一點(diǎn)在51的啟動(dòng)代碼STARTUP.asm中能體現(xiàn)出來。其中有一段如下:

; Stack Space for reentrant functions in the SMALL model.

IBPSTACK EQU 1 ; set to 1 if small reentrant is used.

IBPSTACKTOP EQU 0FFH+1 ; set top of stack to highest location+1.

;

; Stack Space for reentrant functions in the LARGE model.

XBPSTACK EQU 0 ; set to 1 if large reentrant is used.

XBPSTACKTOP EQU 7FFFH+1; set top of stack to highest location+1.

;

; Stack Space for reentrant functions in the COMPACT model.

PBPSTACK EQU 0 ; set to 1 if compact reentrant is used.

PBPSTACKTOP EQU 7FFFH+1; set top of stack to highest location+1.

IF IBPSTACK 《》 0

EXTRN DATA (?C_IBP)

MOV ?C_IBP,#LOW IBPSTACKTOP

ENDIF

IF XBPSTACK 《》 0

EXTRN DATA (?C_XBP)

MOV ?C_XBP,#HIGH XBPSTACKTOP

MOV ?C_XBP+1,#LOW XBPSTACKTOP

ENDIF

IF PBPSTACK 《》 0

EXTRN DATA (?C_PBP)

MOV ?C_PBP,#LOW PBPSTACKTOP

ENDIF

注釋講的很清楚,根據(jù)所選模式,編譯器會(huì)將IBPSTACK、PBPSTACK或者XBPSTACK設(shè)置為1,就決定了仿真堆棧在IDATA區(qū)、PDAIA區(qū)還是XDATA區(qū)。對應(yīng)的,KEIL會(huì)自動(dòng)分配一個(gè)仿真堆棧指針,分別是?C_IBP、?C_PBP和(?C_XBP、?C_XBP+1),由于尋址XDATA區(qū)需要16位地址,所以需要兩個(gè)字節(jié)。這三個(gè)指針是KEIL根據(jù)選擇的Memory Model選項(xiàng)自動(dòng)分配的。

注意:不要試圖在選擇好模式后將仿真堆棧設(shè)置在另一模式的空間中。比如,我用的小模式編譯,仿真堆棧在IDATA區(qū),用的仿真堆棧指針是?C_IBP,但是我現(xiàn)在在啟動(dòng)代碼中將IBPSTACK定義為0,將XBPSTACK設(shè)置為1,看起來我們先把仿真堆棧設(shè)置在XDATA區(qū)了,但實(shí)際上其它代碼段中使用的仿真堆棧指針任然是?C_IBP。有趣的是,KEIL還為我們的啟動(dòng)代碼做了一個(gè)很友好的列表框選擇界面。但實(shí)際上選擇好編譯模式后,仿真堆棧使用空間是不能更改的,不知道KEIL為什么這么做?但是我們有時(shí)候要根據(jù)單片機(jī)的型號(hào)選擇仿真堆棧的起始地址。

結(jié)語

關(guān)于ucos-II的相關(guān)介紹就到這了,如有不足之處歡迎指正。

相關(guān)閱讀推薦:UCOS-II操作系統(tǒng)在ZEVIO1020上移植過程的主要步驟詳解

相關(guān)閱讀推薦:uCOSii的移植過程詳解

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報(bào)投訴
  • 處理器
    +關(guān)注

    關(guān)注

    68

    文章

    19286

    瀏覽量

    229852
  • 單片機(jī)
    +關(guān)注

    關(guān)注

    6037

    文章

    44558

    瀏覽量

    635349
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    快速實(shí)現(xiàn)STM32移植ucos-ii

    快速實(shí)現(xiàn)STM32移植ucos-ii,歡迎大家一起學(xué)習(xí)[groupid=618]單片機(jī)項(xiàng)目開發(fā)設(shè)計(jì)群[/groupid]
    發(fā)表于 08-08 16:28

    ucos_II51單片機(jī)上的移植源代碼

    求各位大神幫忙發(fā)一個(gè)51單片機(jī)ucos-II移植好的源代碼
    發(fā)表于 04-26 23:33

    51系列單片機(jī)移植uCOS-II

    本文詳細(xì)系統(tǒng)地介紹了uC/OS-II51單片機(jī)上的移植、重入實(shí)現(xiàn)方法、硬件仿真、固化、人機(jī)界面等關(guān)鍵內(nèi)容。關(guān)鍵詞:嵌入式實(shí)時(shí)多任務(wù)操作系統(tǒng)、uC/OS-
    發(fā)表于 06-16 11:22 ?4658次閱讀
    在<b class='flag-5'>51</b>系列<b class='flag-5'>單片機(jī)</b>上<b class='flag-5'>移植</b><b class='flag-5'>uCOS-II</b>

    ucOS-II入門經(jīng)典教程

    ucOS-II入門經(jīng)典教程,ucOS-II入門經(jīng)典教程
    發(fā)表于 11-06 10:07 ?0次下載

    盤古STM32F103開發(fā)板移植uCOS-II詳細(xì)說明

    盤古STM32F103開發(fā)板移植uCOS-II詳細(xì)說明
    發(fā)表于 03-02 17:29 ?13次下載

    STM32平臺(tái)移植uCOS-II詳細(xì)說明-2012.11.13

    STM32平臺(tái)移植uCOS-II詳細(xì)說明-2012.11.13
    發(fā)表于 03-04 15:31 ?12次下載

    uCOS-ii中文書

    學(xué)習(xí)uCOS-ii的最好中文教材,uCOS-ii中文書(邵貝貝)
    發(fā)表于 08-24 18:31 ?0次下載

    uCOS-II原理1

    原理uCOS-II
    發(fā)表于 12-20 22:58 ?5次下載

    uCOS-II原理2

    uCOS-II原理2
    發(fā)表于 12-20 22:53 ?0次下載

    uCOS-II原理3

    uCOS-II原理3
    發(fā)表于 12-20 22:52 ?0次下載

    在W78E58處理器上移植uCOS-II

    在W78E58處理器上移植uCOS-II
    發(fā)表于 01-08 14:27 ?12次下載

    uCOS-II在MSP430移植

    uCOS-II在MSP430移植
    發(fā)表于 10-12 17:24 ?9次下載
    <b class='flag-5'>uCOS-II</b>在MSP430<b class='flag-5'>移植</b>

    手把手盤古STM32開發(fā)板移植uCOS-II教程

    手把手盤古STM32開發(fā)板移植uCOS-II教程
    發(fā)表于 10-16 09:38 ?22次下載

    如何在系列51單片機(jī)移植uCOS-II

    本文詳細(xì)系統(tǒng)地介紹了uC/OS-II51單片機(jī)上的移植、重入實(shí)現(xiàn)方法、硬件仿真、固化、人機(jī)界面等關(guān)鍵內(nèi)容。
    發(fā)表于 08-02 17:34 ?2次下載
    如何在系列<b class='flag-5'>51</b><b class='flag-5'>單片機(jī)</b>上<b class='flag-5'>移植</b><b class='flag-5'>uCOS-II</b>

    基于51單片機(jī)uCOS_ii仿真源碼下載

    基于51單片機(jī)uCOS_ii仿真源碼下載
    發(fā)表于 04-09 14:30 ?20次下載