国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費(fèi)電子書(shū)等14項(xiàng)超值服

開(kāi)通VIP
我的ucos學(xué)習(xí)分析

                              2009.9.10
1.在uC/OS-II的幫助手冊(cè)內(nèi),作者特地強(qiáng)調(diào)絕對(duì)不能在OSInit()或者OSStart()內(nèi)
調(diào)用Timer初始化程序,那會(huì)破壞系統(tǒng)的可移植性同時(shí)帶來(lái)性能上的損失。

所以,一個(gè)折中的辦法就是:
在優(yōu)先級(jí)最高的程序內(nèi)調(diào)用,這樣可以保證當(dāng)OSStart()調(diào)用系統(tǒng)內(nèi)部函數(shù)
OSStartHighRdy()開(kāi)始多任務(wù)后,首先執(zhí)行的就是Timer初始化程序?;蛘?br>專門(mén)開(kāi)一個(gè)優(yōu)先級(jí)最高的任務(wù),只做一件事情,那就是執(zhí)行 Timer初始化,
之后通過(guò)調(diào)用OSTaskSuspend()將自己掛起來(lái),永遠(yuǎn)不再執(zhí)行。不過(guò)這樣會(huì)
浪費(fèi)一個(gè)TCB空間。對(duì)于那些RAM吃緊的系統(tǒng)來(lái)說(shuō),還是不用為好。
2.(三) 一些重要的uC/OS-II API介紹

任何一個(gè)操作系統(tǒng)都會(huì)提供大量的API供程序員使用,uC/OS-II也不例外。由于uC/OS-II面向
的是嵌入式開(kāi)發(fā),并不要求大而全,所以內(nèi)核提供的API也就大多和多任務(wù)息息相關(guān)。
主要的有以下幾類:

1)任務(wù)類

2)消息類

3)同步類

4)時(shí)間類

5)臨界區(qū)與事件類

我個(gè)人認(rèn)為對(duì)于初級(jí)程序員而言,任務(wù)類和時(shí)間類是必須要首先掌握的兩種類型的API。
下面我就來(lái)介紹比較重要的:

1) OSTaskCreate函數(shù)

這個(gè)函數(shù)應(yīng)該至少再main函數(shù)內(nèi)調(diào)用一次,在OSInit函數(shù)調(diào)用之后調(diào)用。作用就是創(chuàng)建
一個(gè)任務(wù)。目前有四個(gè)參數(shù),分別是任務(wù)的入口地址,任務(wù)的參數(shù), 任務(wù)堆棧的首地址和
任務(wù)的優(yōu)先級(jí)。調(diào)用本函數(shù)后,系統(tǒng)會(huì)首先從TCB空閑列表內(nèi)申請(qǐng)一個(gè)空的TCB指針,然后
將會(huì)根據(jù)用戶給出參數(shù)初始化任務(wù)堆棧,并在內(nèi)部的任務(wù)就緒表內(nèi)標(biāo)記該任務(wù)為就緒狀態(tài)。
最后返回,這樣一個(gè)任務(wù)就創(chuàng)建成功了。

2) OSTaskSuspend函數(shù)

這個(gè)函數(shù)很簡(jiǎn)單,一看名字就該明白它的作用,它可以將指定的任務(wù)掛起。如果掛起的是
當(dāng)前任務(wù)的話,那么還會(huì)引發(fā)系統(tǒng)執(zhí)行任務(wù)切換先導(dǎo)函數(shù)OSShed來(lái)進(jìn)行一次任務(wù)切換。
這個(gè)函數(shù)只有一個(gè)參數(shù),那就是指定任務(wù)的優(yōu)先級(jí)。那為什么是優(yōu)先級(jí)呢?事實(shí)上在系統(tǒng)
內(nèi)部,優(yōu)先級(jí)除了表示一個(gè)任務(wù)執(zhí)行的先后次序外,還起著分別每一個(gè)任務(wù)的作用,換句話
說(shuō),優(yōu)先級(jí)也就是任務(wù)的ID。所以u(píng)C/OS-II不允許出現(xiàn)相同優(yōu)先級(jí)的任務(wù)。

3) OSTaskResume函數(shù)

這個(gè)函數(shù)和上面的函數(shù)正好相反,它用于將指定的已經(jīng)掛起的函數(shù)恢復(fù)成就緒狀態(tài)。如果
恢復(fù)任務(wù)的優(yōu)先級(jí)高于當(dāng)前任務(wù),那么還為引發(fā)一次任務(wù)切換。其參數(shù)類似 OSTaskSuspend
函數(shù),為指定任務(wù)的優(yōu)先級(jí)。需要特別說(shuō)明是,本函數(shù)并不要求和OSTaskSuspend函數(shù)成對(duì)使
用。

4) OS_ENTER_CRITICAL宏

很多人都以為它是個(gè)函數(shù),其實(shí)不然,仔細(xì)分析一下OS_CPU.H文件,它和下面馬上要談到的
OS_EXIT_CRITICAL都是宏。他們都是涉及特定 CPU的實(shí)現(xiàn)。一般都被替換為一條或者幾條
嵌入式匯編代碼。由于系統(tǒng)希望向上層程序員隱藏內(nèi)部實(shí)現(xiàn),故而一般都宣稱執(zhí)行此條指
令后系統(tǒng)進(jìn)入臨界區(qū)。其實(shí), 它就是關(guān)個(gè)中斷而已。這樣,只要任務(wù)不主動(dòng)放棄CPU使用權(quán),
別的任務(wù)就沒(méi)有占用CPU的機(jī)會(huì)了,相對(duì)這個(gè)任務(wù)而言,它就是獨(dú)占了。所以說(shuō)進(jìn)入臨界區(qū)了。
這個(gè)宏能少用還是少用,因?yàn)樗鼤?huì)破壞系統(tǒng)的一些服務(wù),尤其是時(shí)間服務(wù)。并使系統(tǒng)對(duì)外界響
應(yīng)性能降低。

5) OS_EXIT_CRITICAL宏

這個(gè)是和上面介紹的宏配套使用另一個(gè)宏,它在系統(tǒng)手冊(cè)里的說(shuō)明是退出臨界區(qū)。其實(shí)它就
是重新開(kāi)中斷。需要注意的是,它必須和上面的宏成對(duì)出現(xiàn),否則會(huì)帶來(lái)意想不到的后果。
最壞的情況下,系統(tǒng)會(huì)崩潰。我們推薦程序員們盡量少使用這兩個(gè)宏調(diào)用,因?yàn)樗麄兊拇_會(huì)
破壞系統(tǒng)的多任務(wù)性能。

6) OSTimeDly函數(shù)

這應(yīng)該程序員們調(diào)用最多的一個(gè)函數(shù)了,這個(gè)函數(shù)完成功能很簡(jiǎn)單,就是先掛起當(dāng)起當(dāng)前任務(wù),
然后進(jìn)行任務(wù)切換,在指定的時(shí)間到來(lái)之后,將當(dāng)前任務(wù)恢復(fù)為就緒狀態(tài),但是并不一定運(yùn)行,
如果恢復(fù)后是優(yōu)先級(jí)最高就緒任務(wù)的話,那么運(yùn)行之。簡(jiǎn)單點(diǎn)說(shuō),就是可以任務(wù)延時(shí)一定時(shí)間
后再次執(zhí)行它,或者說(shuō),暫時(shí)放棄CPU的使用權(quán)。一個(gè)任務(wù)可以不顯式的調(diào)用這些可以導(dǎo)致放棄CPU使用權(quán)的API,但那樣多任務(wù)性能會(huì)大大降低,因?yàn)榇藭r(shí)僅僅依靠時(shí)鐘機(jī)制在進(jìn)行任務(wù)切換。一個(gè)好的任務(wù)應(yīng)該在完成一些操作主動(dòng)放棄使用權(quán),好東西要大家分享嘛!


3.我們推薦程序員們盡量少使用OS_ENTER_CRITICAL宏和 OS_EXIT_CRITICAL宏兩個(gè)宏調(diào)用,
因?yàn)樗麄兊拇_會(huì)破壞系統(tǒng)的多任務(wù)性能。why??


4.在以u(píng)C/OS為操作系統(tǒng)的項(xiàng)目中,系統(tǒng)可能要處理各種不同的中斷請(qǐng)求,如果某個(gè)中斷處理
程序需要調(diào)用uC/OS的各種Post函數(shù)向任務(wù)發(fā)出消息,那么uC/OS建議中斷服務(wù)程序的寫(xiě)法是:

1、保存全部CPU寄存器
2、調(diào)用OSIntEnter或OSIntNesting直接加1
3、執(zhí)行用戶代碼做中斷服務(wù)
4、調(diào)用OSIntExit
5、恢復(fù)所有CPU寄存器
6、執(zhí)行中斷返回指令
暫且稱為“標(biāo)準(zhǔn)中斷”方式,這種方式實(shí)際上是將這個(gè)中斷處理加入了任務(wù)調(diào)度系統(tǒng),也就是
說(shuō)這個(gè)中斷可以引起任務(wù)的切換。

如果在中斷處理中沒(méi)有調(diào)用各種Post函數(shù)的話,則可以用一般的、象原來(lái)沒(méi)有操作系統(tǒng)時(shí)的
寫(xiě)法:
1、保存中斷處理程序需要用到的CPU寄存器
2、執(zhí)行中斷處理
3、恢復(fù)保存了的CPU寄存器
4、執(zhí)行中斷返回指令
暫且稱為“快中斷”方式,按照這種方法定義的中斷永遠(yuǎn)不會(huì)引起任務(wù)切換。

在uC/OS系統(tǒng)中,每個(gè)任務(wù)都要定義獨(dú)立的??臻g,一個(gè)??臻g的使用包括5個(gè)部分:
1、任務(wù)包括的各個(gè)函數(shù)的調(diào)用返回地址
2、任務(wù)包括的各個(gè)函數(shù)中可能在棧上分配的局部變量
3、發(fā)生了“標(biāo)準(zhǔn)中斷”方式定義的中斷或任務(wù)被掛起時(shí),所要保存的任務(wù)上下文
4、發(fā)生了“快中斷”方式定義的中斷時(shí),中斷處理程序所需要的??臻g
5、中斷嵌套時(shí),所要保存的中斷嵌套上下文

在這些使用的部分中,1,2,3,4的內(nèi)存占用量是比較容易估算的,最精確和保險(xiǎn)的確定
方法是:查看由C生成的asm文件,并計(jì)算各個(gè)函數(shù)的棧使用量。但是第5部分的棧空間使用
量是隨中斷嵌套的深度而不斷增加的,是不確定的,一般的方法只能定義一個(gè)充分大的棧
空間,使之不會(huì)溢出。

為每個(gè)任務(wù)都定義一個(gè)充分大的??臻g,這在某些內(nèi)存稀缺的小項(xiàng)目中是非常痛苦的,
有時(shí)不得不增擴(kuò)內(nèi)存,這就會(huì)使成本增加。

我深入研究了uC/OS后,認(rèn)為,可以將所有任務(wù)??臻g使用的第5部分合并,這樣將會(huì)大大的
降低整個(gè)系統(tǒng)對(duì)內(nèi)存的需求。

uC/OS的任務(wù)調(diào)度是靠OS_Sched和 OSIntExit來(lái)完成的,這兩個(gè)函數(shù)中都要先判斷一個(gè)叫
OSIntNesting的系統(tǒng)變量,如果OSIntNesting不為0,則不進(jìn)行任務(wù)切換。也就是說(shuō):
在OSIntNesting為1(當(dāng)前只有一個(gè)中斷在處理中,并且沒(méi)有嵌套的中斷)時(shí)起,
如果發(fā)生了嵌套的中斷(不管嵌套的層數(shù)有深),那么在所有嵌套的中斷一層一層地都返回
直到 OSIntNesting再次為1時(shí)止,任務(wù)棧是不會(huì)切換的(棧指針都在一個(gè)任務(wù)的??臻g中變
化)。

據(jù)此,我們可以這樣改動(dòng):設(shè)置一個(gè)緩沖區(qū)OSInterruptStk,作為嵌套中斷的棧空間,
由所有任務(wù)共享,中斷服務(wù)程序改為:
1、保存全部CPU寄存器
2、調(diào)用OSIntEnter或OSIntNesting直接加1
增加:2.1、判斷OSIntNesting是否等于1,如果不是則轉(zhuǎn)到3
增加:2.2、將棧指針SP保存到OSTCBCur->OSTCBStkPtr
增加:2.3、將SP指向OSInterruptStk的棧頂(注意棧增長(zhǎng)的方向)。
3、執(zhí)行用戶代碼做中斷服務(wù)
4、調(diào)用OSIntExit
增加:4.1、判斷OSIntNesting是否等于0,如果不是則轉(zhuǎn)到5
增加:4.2、從OSTCBCur->OSTCBStkPtr中恢復(fù)棧指針SP
5、恢復(fù)所有CPU寄存器
6、執(zhí)行中斷返回指令

并且要修改OSIntCtxSw函數(shù),原始的OSIntCtxSw函數(shù)的寫(xiě)法是:
1、調(diào)整棧指針來(lái)去掉在調(diào)用:OSIntExit,OSIntCtxSw過(guò)程中入棧的多余內(nèi)容
2、將當(dāng)前任務(wù)棧指針保存到OSTCBCur中(OSTCBCur->OSTCBStkPtr = __SP__)
3、如果需要?jiǎng)t調(diào)用OSTaskSwHook
4、OSTCBCur = OSTCBHighRdy
5、OSPrio = OSPrioHighRdy
6、從OSTCBCur中恢復(fù)棧指針(__SP__ = OSTCBCur->OSTCBStkPtr)
7、恢復(fù)保存了的CPU寄存器
8、執(zhí)行中斷返回指令

新的寫(xiě)法只需將原寫(xiě)法中的1,2去掉即可,因?yàn)?,2步只是保存舊任務(wù)的棧指針,而新的寫(xiě)
法中,這些步被移到了“中斷服務(wù)程序”中的2.2。

5.注意ARM Image for uCOSII for lpc213x 模板中的TargetInit()


對(duì)于很多使用ZLG ARM Image for uCOSII for lpc213x 模板的初學(xué)者,常常會(huì)置疑使用該模板
后自動(dòng)生成的target.c文件,和在程序中調(diào)用的TargetInit()函數(shù),我和 Zgpswh都是如此,這
個(gè)問(wèn)題當(dāng)初困擾了很久:當(dāng)用戶程序中不調(diào)用TargetInit()時(shí),發(fā)現(xiàn)內(nèi)核能運(yùn)行,但是等待機(jī)制
失靈,調(diào)用 TargetInit(),很多硬件中斷打不開(kāi),后來(lái),在很多熱心人的指點(diǎn)下解決了,現(xiàn)重新
總結(jié)如下:

請(qǐng)仔細(xì)察看ZLG模板里的target.c文件,這里的TargetInit()如下:

void TargetInit(void)
{
    OS_ENTER_CRITICAL();
    srand((uint32) TargetInit);
    VICInit();
    Timer0Init();
    OS_EXIT_CRITICAL();
}

其中的Timer0Init();用于硬件定時(shí)器0的初始化,事實(shí)上,ZLG的移植代碼的μC/OS-Ⅱ的時(shí)鐘節(jié)拍是
通過(guò)定時(shí)器0提供的,不在主程序里調(diào)用這個(gè)函數(shù),μC/OS-Ⅱ的時(shí)鐘源就無(wú)法打開(kāi);但是,沒(méi)有開(kāi)啟
時(shí)鐘源的μC/OS-Ⅱ是同樣能運(yùn)行的,只是內(nèi)核提供的延時(shí)和等待時(shí)限機(jī)制都不起作用,系統(tǒng)雖能將
就運(yùn)行,但因沒(méi)調(diào)用TargetInit()而使內(nèi)核功能不健全。

請(qǐng)注意,TargetInit()中的另一個(gè)函數(shù)VICInit ()是用來(lái)中斷的初始化,它其中含有對(duì)UART0中斷的
分配,在用戶程序里需要根據(jù)使用的硬件中斷修改這部分代碼,否則,這些硬件中斷無(wú)法開(kāi)啟;
再者,在不調(diào)用TargetInit()的時(shí)候,硬件的中斷初始化是在硬件初始化函數(shù)中完成,
這也就是Zgpswh提到的現(xiàn)象:不調(diào)用TargetInit()內(nèi)核運(yùn)行異常,調(diào)用了卻開(kāi)不了UART0的中斷。

解決的方法如下:
這在《ARM嵌入式系統(tǒng)基礎(chǔ)教程》的430頁(yè)7.4.3節(jié)中論述的很清楚:

……關(guān)鍵在于把程序與芯片相關(guān)中斷源掛接,使芯片在產(chǎn)生相應(yīng)的中斷后會(huì)調(diào)用相應(yīng)的處理程序。
這需要做兩方面事情:
1. 增加匯編接口的支持。……
2. 初始化向量中斷控制器。……

按照一下方法完成中斷源的的掛接:
1、增加匯編接口的支持。方法是修改IRQ.s文件,在末尾添加本句代碼:

UART0_Handler HANDLER UART0_Exception

追加定義了通用串口0 中斷句柄。
2、初始化向量中斷控制器。將target.c文件中的VICInit()修改如下:

void VICInit(void)
{ extern void IRQ_Handler(void);
   extern void Timer0_Handler(void);
   extern void UART0_Handler(void);
   VICIntEnClr = 0xffffffff;
   VICDefVectAddr = (uint32)IRQ_Handler;
   VICVectAddr0 = (uint32)Timer0_Handler;
   VICVectCntl0 = (0x20 | 0x04);
   VICIntEnable = 1 << 4;
   VICVectAddr14 = (uint32)UART0_Handler;
   VICVectCntl14 = (0x20 | 0x06);
   VICIntEnable = 1 << 6;
}

此為初始化向量中斷控制器。包括定時(shí)器0和串口0,特別要注意的是,一定不可以省略對(duì)定
時(shí)器0的初始化
中斷里,不可以調(diào)用延時(shí)

請(qǐng)注意,中斷里面是不支持等待機(jī)制的。請(qǐng)用自己編的一個(gè)軟件延時(shí),問(wèn)題就可以解決了。
中斷源掛接正確是沒(méi)問(wèn)題的。

6.問(wèn)
void TargetInit(void)
{
    OS_ENTER_CRITICAL();
    srand((uint32) TargetInit);
    VICInit();
    Timer0Init();
    OS_EXIT_CRITICAL();
}
在此單獨(dú)用srand()函數(shù)有什么作用(用了有什么好處,不用又會(huì)怎樣),一般srand()用于
給rand()設(shè)定種子(即srand給定rand運(yùn)算式子的第一個(gè)值)。查了FAQ(P22)僅僅說(shuō)明了
seed的譯文。

答 2
你說(shuō)的沒(méi)有錯(cuò),他就是用來(lái)設(shè)置隨機(jī)數(shù)的種子。
每次編譯一次,void TargetInit(void)函數(shù)在Ram或者Flash中的地址都不一樣
(即種子也不一樣)。如果你在程序中不用隨機(jī)函數(shù)rand(),那么srand()
在這里對(duì)你來(lái)說(shuō)是沒(méi)有意義的,如果你要用rand(),那么每次編譯程序后你的rand()
產(chǎn)生的隨機(jī)數(shù)就不一樣。當(dāng)然,你也可以自己種種子咯。

7.
在ARM上移植操作系統(tǒng)有一點(diǎn)需要注意:建立任務(wù)的任務(wù),最好不要做復(fù)雜的工作。
頻繁的訪問(wèn)其他硬件或者做時(shí)序要求比較嚴(yán)的工作容易造成系統(tǒng)死機(jī),希望大家多
多注意。我的做法是:將建立任務(wù)的任務(wù),閑置起來(lái),但是不能進(jìn)入死循環(huán)。方法
是:利用一個(gè)空郵箱,讓任務(wù)無(wú)限期的等待,這樣可以實(shí)現(xiàn)與其他任務(wù)的切換。


8.//定義與編譯器無(wú)關(guān)的數(shù)據(jù)類型

typedef unsigned char BOOLEAN; //布爾變量

typedef unsigned char INT8U; // 無(wú)符號(hào)8位整型變量

typedef signed char INT8S; //有符號(hào)8位整型變量

typedef unsigned short INT16U; //無(wú)符號(hào)16位整型變量

typedef signed short INT16S; //有符號(hào)16位整型變量

typedef unsigned int INT32U; //無(wú)符號(hào)32位整型變量

typedef signed int INT32S; //有符號(hào)32位整型變量

typedef float FP32; //單精度浮點(diǎn)數(shù)(32位長(zhǎng)度)

typedef double FP64; //雙精度浮點(diǎn)數(shù)(64位長(zhǎng)度)

typedef INT32U OS_STK; //堆棧是32位寬度

注:這里為什么用typedef,因?yàn)槿绻?define,那么代碼中的每一個(gè)相應(yīng)的類型都會(huì)被替代,
很有可能會(huì)出現(xiàn)問(wèn)題,畢竟他只是一個(gè)替代的關(guān)系,且編譯時(shí)間會(huì)增加,而用typedef則不會(huì),
它就相當(dāng)于我們C++里面的引用,一樣的思維,在這里面就是說(shuō)多了一個(gè)名稱。還有要注意的是
我們?cè)趺粗纔nsigned char 就是無(wú)符號(hào)8位整型變量,可以ARM公司里面下載ADS_CompilerGuide_D.PDF
文件,或者在你所裝的ADS1.2目錄里面有一個(gè)文件夾叫PDF,打開(kāi)它就可以找到,具體頁(yè)在259頁(yè)。

9>OS_CPU_a.s:

;定義系統(tǒng)模式堆棧的大小

SVC_STACK_LEGTH EQU 32


NoInt EQU 0x80


USR32Mode EQU 0x10

SVC32Mode EQU 0x13

SYS32Mode EQU 0x1f

IRQ32Mode EQU 0x12

FIQ32Mode EQU 0x11


;T_bit用于檢測(cè)進(jìn)入異常前cpu是否處于THUMB狀態(tài)

T_bit EQU 0x20


CODE32


AREA |subr|, CODE, READONLY


IMPORT OSTCBCur ;指向當(dāng)前任務(wù)TCB的指針

IMPORT OSTCBHighRdy ;指向?qū)⒁\(yùn)行的任務(wù)TCB的指針

IMPORT OSPrioCur ;當(dāng)前任務(wù)的優(yōu)先級(jí)

IMPORT OSPrioHighRdy ;將要運(yùn)行的任務(wù)的優(yōu)先級(jí)

IMPORT OSTaskSwHook ;任務(wù)切換的鉤子函數(shù)

IMPORT OSRunning ;uC/OS-II運(yùn)行標(biāo)志


IMPORT OsEnterSum ;關(guān)中斷計(jì)數(shù)器(關(guān)中斷信號(hào)量)

IMPORT SWI_Exception ;軟中斷異常處理程序

EXPORT __OSStartHighRdy

EXPORT OSIntCtxSw ;中斷退出時(shí)的入口,參見(jiàn)startup.s中的IRQ_Handler

EXPORT SoftwareInterrupt ;軟中斷入口


;軟件中斷

//當(dāng)CPU發(fā)現(xiàn)有軟中斷信號(hào)出現(xiàn)時(shí),CPU的PC馬上指到軟中斷服務(wù)地址處【見(jiàn)Startup.s】,然后通過(guò)跳轉(zhuǎn)到下面這段軟中斷處理程序,進(jìn)入后,首先要設(shè)置好管理模式下的堆棧,保存好用戶任務(wù)的幾個(gè)寄存器,其它寄存器系統(tǒng)會(huì)自動(dòng)保存,然后取出SWI號(hào)。

SoftwareInterrupt

LDR SP, StackSvc ; 重新設(shè)置堆棧指針

STMFD SP!, {R0-R3, R12, LR} //為什么只保存這幾個(gè)寄存器,見(jiàn)上面的解釋

MOV R1, SP ; R1指向參數(shù)存儲(chǔ)位置


MRS R3, SPSR //保存管理模式的狀態(tài)寄存器

TST R3, #T_bit ; 中斷前是否是Thumb狀態(tài)

LDRNEH R0, [LR,#-2] ; 是: 取得Thumb狀態(tài)SWI號(hào)

BICNE R0, R0, #0xff00

LDREQ R0, [LR,#-4] ; 否: 取得arm狀態(tài)SWI號(hào)

BICEQ R0, R0, #0xFF000000

; r0 = SWI號(hào),R1指向參數(shù)存儲(chǔ)位置

CMP R0, #1

LDRLO PC, =OSIntCtxSw

LDREQ PC, =__OSStartHighRdy ; SWI 0x01為第一次任務(wù)切換


BL SWI_Exception

LDMFD SP!, {R0-R3, R12, PC}^

StackSvc DCD (SvcStackSpace + SVC_STACK_LEGTH * 4 - 4)


OSIntCtxSw

;下面為保存任務(wù)環(huán)境

LDR R2, [SP, #20] ;獲取PC//其實(shí)他就是管理模式下的LR寄存器的值,也就是用戶任務(wù)的PC值,為什么是SP+20,因?yàn)樵摋J菨M棧遞減,保存了R0-R3, R12, LR,所以LR的值為[SP+#20]。

LDR R12, [SP, #16] ;獲取R12

MRS R0, CPSR //用通用寄存器R0保存該管理模式下的CPSR


MSR CPSR_c, #(NoInt | SYS32Mode)//切換到系統(tǒng)模式

MOV R1, LR //把用戶的LR保存在通用寄存器R1中

STMFD SP!, {R1-R2} ;保存LR,PC//把系統(tǒng)模式的LR,PC壓入用戶任務(wù)的棧中

STMFD SP!, {R4-R12} ;保存R4-R12//把系統(tǒng)模式的R4-R12壓入用戶棧中


MSR CPSR_c, R0 //重新回到管理模式

LDMFD SP!, {R4-R7} ;獲取R0-R3//實(shí)際上把用戶的R0~R3放到管理模式下的R4-R7

ADD SP, SP, #8 ;出棧R12,PC//這兩個(gè)已經(jīng)保存了,所以SP要往上8個(gè)字節(jié)

MSR CPSR_c, #(NoInt | SYS32Mode//系統(tǒng)模式

STMFD SP!, {R4-R7} ;保存R0-R3//因?yàn)楣芾砟J降腞4-R11和系統(tǒng)模式的R4-R11是一樣的,保它保存在用戶任務(wù)的棧中

//接下來(lái)的我就不分析拉,因?yàn)槟闳绻凑瘴疑厦娴姆治?,?yīng)該不成問(wèn)題的,如果還未明白,請(qǐng)多看幾遍,如果有問(wèn)題,請(qǐng)留言我們一起來(lái)探討,謝謝合作!上面的分析除了紅色部分是周立功公司的注釋外,其余都是我的理解,如果有錯(cuò)的,真心希望您能指出!謝謝!

LDR R1, =OsEnterSum ;獲取OsEnterSum

LDR R2, [R1]

STMFD SP!, {R2, R3} ;保存CPSR,OsEnterSum


;保存當(dāng)前任務(wù)堆棧指針到當(dāng)前任務(wù)的TCB

LDR R1, =OSTCBCur

LDR R1, [R1]

STR SP, [R1]


BL OSTaskSwHook ;調(diào)用鉤子函數(shù)

;OSPrioCur <= OSPrioHighRdy

LDR R4, =OSPrioCur

LDR R5, =OSPrioHighRdy

LDRB R6, [R5]

STRB R6, [R4]

;OSTCBCur <= OSTCBHighRdy

LDR R6, =OSTCBHighRdy

LDR R6, [R6]

LDR R4, =OSTCBCur

STR R6, [R4]

OSIntCtxSw_1

;獲取新任務(wù)堆棧指針

LDR R4, [R6]

ADD SP, R4, #68 ;17寄存器CPSR,OsEnterSum,R0-R12,LR,SP

LDR LR, [SP, #-8]

MSR CPSR_c, #(NoInt | SVC32Mode) ;進(jìn)入管理模式

MOV SP, R4 ;設(shè)置堆棧指針


LDMFD SP!, {R4, R5} ;CPSR,OsEnterSum

;恢復(fù)新任務(wù)的OsEnterSum

LDR R3, =OsEnterSum

STR R4, [R3]

MSR SPSR_cxsf, R5 ;恢復(fù)CPSR

LDMFD SP!, {R0-R12, LR, PC }^ ;運(yùn)行新任務(wù)

__OSStartHighRdy

MSR CPSR_c, #(NoInt | SYS32Mode)

;告訴uC/OS-II自身已經(jīng)運(yùn)行

LDR R4, =OSRunning

MOV R5, #1

STRB R5, [R4]


BL OSTaskSwHook ;調(diào)用鉤子函數(shù)


LDR R6, =OSTCBHighRdy

LDR R6, [R6]

B OSIntCtxSw_1


AREA SWIStacks, DATA, NOINIT,ALIGN=2

SvcStackSpace SPACE SVC_STACK_LEGTH * 4 ;管理模式堆??臻g


END
 

類別:uc/os-ii | 添加到搜藏 | 瀏覽(180) | 評(píng)論 (0)  上一篇:模電學(xué)習(xí)筆記匯總    下一篇:uCos-II學(xué)習(xí)匯總(一) 相關(guān)文章:? 09年部分省市高考理科狀元學(xué)習(xí)經(jīng)...          ? English詞匯學(xué)習(xí)專貼分類詞匯匯...
學(xué)習(xí)Fluent的經(jīng)驗(yàn)匯總(轉(zhuǎn)摘的,個(gè)...          ? .net學(xué)習(xí)網(wǎng)站匯總
2010年?yáng)|南大學(xué)-301學(xué)習(xí)科學(xué)研究...          ? 精彩英語(yǔ)聽(tīng)力口語(yǔ)學(xué)習(xí)網(wǎng)站-網(wǎng)址...
樹(shù)狀數(shù)組學(xué)習(xí)系列2 之 OJ題目大...          ? 學(xué)習(xí)娛樂(lè)兩不誤 OPPO S39評(píng)測(cè)大...
DIV CSS網(wǎng)頁(yè)布局學(xué)習(xí)中容易出現(xiàn)...          ? 數(shù)據(jù)挖掘?qū)W習(xí)和研究的一些指導(dǎo)性...
更多>>
 最近讀者: 登錄后,您就出現(xiàn)在這里。 

嵌入式實(shí)時(shí)操作系統(tǒng)ucos ii的分析2009年03月18日 星期三 下午 05:23摘要:近年來(lái),在單片機(jī)系統(tǒng)中嵌入操作系統(tǒng)已經(jīng)成為人們?cè)絹?lái)越關(guān)心的一個(gè)話題。本文通過(guò)對(duì)一種源碼公開(kāi)的嵌入式實(shí)時(shí)操作系統(tǒng)ucos ii的分析,以51系列單片機(jī)為例,闡述了在單片機(jī)中使用該嵌入式操作系統(tǒng)的優(yōu)缺點(diǎn),以及在應(yīng)用中應(yīng)當(dāng)注意的一些問(wèn)題。
關(guān)鍵詞:實(shí)時(shí)操作系統(tǒng);ucos ii;單片機(jī)


引言
  早在20世紀(jì)60年代,就已經(jīng)有人開(kāi)始研究和開(kāi)發(fā)嵌入式操作系統(tǒng)。但直到最近,它才在國(guó)內(nèi)被越來(lái)越多的提及,在通信、電子、自動(dòng)化等需要實(shí)時(shí)處理的領(lǐng)域所曰益顯現(xiàn)的重要性吸引了人們?cè)絹?lái)越多的注意力。但是,人們所談?wù)摰耐且恍┲纳虡I(yè)內(nèi)核,諸如VxWorks、PSOS等。這些商業(yè)內(nèi)核性能優(yōu)越,但價(jià)格昂貴,主要用于16位和32位處理器中,針對(duì)國(guó)內(nèi)大部分用戶使用的51系列8位單片機(jī),可以選擇免費(fèi)的ucos ii。


ucos ii的特點(diǎn)
  1.ucos ii是由Labrosse先生編寫(xiě)的一個(gè)開(kāi)放式內(nèi)核,最主要的特點(diǎn)就是源碼公開(kāi)。這一點(diǎn)對(duì)于用戶來(lái)說(shuō)可謂利弊各半,好處在于,一方面它是免費(fèi)的,另一方面用戶可以根據(jù)自己的需要對(duì)它進(jìn)行修改。缺點(diǎn)在于它缺乏必要的支持,沒(méi)有功能強(qiáng)大的軟件包,用戶通常需要自己編寫(xiě)驅(qū)動(dòng)程序,特別是如果用戶使用的是不太常用的單片機(jī),還必須自己編寫(xiě)移植程序。

  2.ucos ii是一個(gè)占先式的內(nèi)核,即已經(jīng)準(zhǔn)備就緒的高優(yōu)先級(jí)任務(wù)可以剝奪正在運(yùn)行的低優(yōu)先級(jí)任務(wù)的CPU使用權(quán)。這個(gè)特點(diǎn)使得它的實(shí)時(shí)性比非占先式的內(nèi)核要好。通常我們都是在中斷服務(wù)程序中使高優(yōu)先級(jí)任務(wù)進(jìn)入就緒態(tài)(例如發(fā)信號(hào)),這樣退出中斷服務(wù)程序后,將進(jìn)行任務(wù)切換,高優(yōu)先級(jí)任務(wù)將被執(zhí)行。拿51單片機(jī)為例,比較一下就可以發(fā)現(xiàn)這樣做的好處。假如需要用中斷方式采集一批數(shù)據(jù)并進(jìn)行處理,在傳統(tǒng)的編程方法中不能在中斷服務(wù)程序中進(jìn)行復(fù)雜的數(shù)據(jù)處理,因?yàn)檫@會(huì)使得關(guān)中斷時(shí)間過(guò)長(zhǎng)。所以經(jīng)常采用的方法是置一標(biāo)志位,然后退出中斷。由于主程序是循環(huán)執(zhí)行的,所以它總有機(jī)會(huì)檢測(cè)到這一標(biāo)志并轉(zhuǎn)到數(shù)據(jù)處理程序中去。但是因?yàn)闊o(wú)法確定發(fā)生中斷時(shí)程序到底執(zhí)行到了什么地方,也就無(wú)法判斷要經(jīng)過(guò)多長(zhǎng)時(shí)間數(shù)據(jù)處理程序才會(huì)執(zhí)行,中斷響應(yīng)時(shí)間無(wú)法確定,系統(tǒng)的實(shí)時(shí)性不強(qiáng)。如果使用μC/OS-II的話,只要把數(shù)據(jù)處理程序的優(yōu)先級(jí)設(shè)定得高一些,并在中斷服務(wù)程序中使它進(jìn)入就緒態(tài),中斷結(jié)束后數(shù)據(jù)處理程序就會(huì)被立即執(zhí)行。這樣可以把中斷響應(yīng)時(shí)間限制在一定的范圍內(nèi)。對(duì)于一些對(duì)中斷響應(yīng)時(shí)間有嚴(yán)格要求的系統(tǒng),這是必不可少的。但應(yīng)該指出的是如果數(shù)據(jù)處理程序簡(jiǎn)單,這樣做就未必合適。因?yàn)閡cos ii要求在中斷服務(wù)程序末尾使用OSINTEXIT函數(shù)以判斷是否進(jìn)行任務(wù)切換,這需要花費(fèi)一定的時(shí)間。

  3.ucos ii和大家所熟知的Linux等分時(shí)操作系統(tǒng)不同,它不支持時(shí)間片輪轉(zhuǎn)法。ucos ii是一個(gè)基于優(yōu)先級(jí)的實(shí)時(shí)操作系統(tǒng),每個(gè)任務(wù)的優(yōu)先級(jí)必須不同,分析它的源碼會(huì)發(fā)現(xiàn),ucos ii把任務(wù)的優(yōu)先級(jí)當(dāng)做任務(wù)的標(biāo)識(shí)來(lái)使用,如果優(yōu)先級(jí)相同,任務(wù)將無(wú)法區(qū)分。進(jìn)入就緒態(tài)的優(yōu)先級(jí)最高的任務(wù)首先得到CPU的使用權(quán),只有等它交出CPU的使用權(quán)后,其他任務(wù)才可以被執(zhí)行。所以它只能說(shuō)是多任務(wù),不能說(shuō)是多進(jìn)程,至少不是我們所熟悉的那種多進(jìn)程。顯而易見(jiàn),如果只考慮實(shí)時(shí)性,它當(dāng)然比分時(shí)系統(tǒng)好,它可以保證重要任務(wù)總是優(yōu)先占有CPU。但是在系統(tǒng)中,重要任務(wù)畢竟是有限的,這就使得劃分其他任務(wù)的優(yōu)先權(quán)變成了一個(gè)讓人費(fèi)神的問(wèn)題。另外,有些任務(wù)交替執(zhí)行反而對(duì)用戶更有利。例如,用單片機(jī)控制兩小塊顯示屏?xí)r,無(wú)論是編程者還是使用者肯定希望它們同時(shí)工作,而不是顯示完一塊顯示屏的信息以后再顯示另一塊顯示屏的信息。這時(shí)候,要是ucos ii即支持優(yōu)先級(jí)法又支持時(shí)間片輪轉(zhuǎn)法就更合適了。

  4.ucos ii對(duì)共享資源提供了保護(hù)機(jī)制。正如上文所提到的,ucos ii是一個(gè)支持多任務(wù)的操作系統(tǒng)。一個(gè)完整的程序可以劃分成幾個(gè)任務(wù),不同的任務(wù)執(zhí)行不同的功能。這樣,一個(gè)任務(wù)就相當(dāng)于模塊化設(shè)計(jì)中的一個(gè)子模塊。在任務(wù)中添加代碼時(shí),只要不是共享資源就不必?fù)?dān)心互相之間有影響。而對(duì)于共享資源(比如串口),ucos ii也提供了很好的解決辦法。一般情況下使用的是信號(hào)量的方法。簡(jiǎn)單地說(shuō),先創(chuàng)建一個(gè)信號(hào)量并對(duì)它進(jìn)行初始化。當(dāng)一個(gè)任務(wù)需要使用一個(gè)共享資源時(shí),它必須先申請(qǐng)得到這個(gè)信號(hào)量,而一旦得到了此信號(hào)量,那就只有等使用完了該資源,信號(hào)量才會(huì)被釋放。在這個(gè)過(guò)程中即使有優(yōu)先權(quán)更高的任務(wù)進(jìn)入了就緒態(tài),因?yàn)闊o(wú)法得到此信號(hào)量,也不能使用該資源。這個(gè)特點(diǎn)的好處顯而易見(jiàn),例如當(dāng)顯示屏正在顯示信息的時(shí)候,外部產(chǎn)生了一個(gè)中斷,而在中斷服務(wù)程序中需要顯示屏顯示其他信息。這樣,退出中斷服務(wù)程序后,原有的信息就可能被破壞了。而在μC/OS-II中采用信號(hào)量的方法時(shí),只有顯示屏把原有信息顯示完畢后才可以顯示新信息,從而可以避免這個(gè)現(xiàn)象。不過(guò),采用這種方法是以犧牲系統(tǒng)的實(shí)時(shí)性為代價(jià)的。如果顯示原有信息需要耗費(fèi)大量時(shí)間,系統(tǒng)只好等待。從結(jié)果上看,等于延長(zhǎng)了中斷響應(yīng)時(shí)間,這對(duì)于未顯示信息是報(bào)警信息的情況,無(wú)疑是致命的。發(fā)生這種情況,在μC/OS-II中稱為優(yōu)先級(jí)反轉(zhuǎn),就是高優(yōu)先級(jí)任務(wù)必須等待低優(yōu)先級(jí)任務(wù)的完成。在上述情況下,在兩個(gè)任務(wù)之間發(fā)生優(yōu)先級(jí)反轉(zhuǎn)是無(wú)法避免的。所以在使用ucos ii時(shí),必須對(duì)所開(kāi)發(fā)的系統(tǒng)了解清楚,才能決定對(duì)于某種共享資源是否使用信號(hào)量。


ucos ii在單片機(jī)使用中的一些特點(diǎn)
  1.在單片機(jī)系統(tǒng)中嵌入ucos ii將增強(qiáng)系統(tǒng)的可靠性,并使得調(diào)試程序變得簡(jiǎn)單。以往傳統(tǒng)的單片機(jī)開(kāi)發(fā)工作中經(jīng)常遇到程序跑飛或是陷入死循環(huán)??梢杂每撮T(mén)狗解決程序跑飛問(wèn)題,而對(duì)于后一種情況,尤其是其中牽扯到復(fù)雜數(shù)學(xué)計(jì)算的話,只有設(shè)置斷點(diǎn),耗費(fèi)大量時(shí)間來(lái)慢慢分析。如果在系統(tǒng)中嵌入 ucos ii的話,事情就簡(jiǎn)單多了??梢园颜麄€(gè)程序分成許多任務(wù),每個(gè)任務(wù)相對(duì)獨(dú)立,然后在每個(gè)任務(wù)中設(shè)置超時(shí)函數(shù),時(shí)間用完以后,任務(wù)必須交出 CPU的使用權(quán)。即使一個(gè)任務(wù)發(fā)生問(wèn)題,也不會(huì)影響其他任務(wù)的運(yùn)行。這樣既提高了系統(tǒng)的可靠性,同時(shí)也使得調(diào)試程序變得容易。

  2.在單片機(jī)系統(tǒng)中嵌入ucos ii將增加系統(tǒng)的開(kāi)銷?,F(xiàn)在所使用的51單片機(jī),一般是指87C51或者89C51,其片內(nèi)都帶有一定的RAM和 ROM。對(duì)于一些簡(jiǎn)單的程序,如果采用傳統(tǒng)的編程方法,已經(jīng)不需要外擴(kuò)存儲(chǔ)器了。如果在其中嵌入ucos ii的話,在只需要使用任務(wù)調(diào)度、任務(wù)切換、信號(hào)量處理、延時(shí)或超時(shí)服務(wù)的情況下,也不需要外擴(kuò)ROM了,但是外擴(kuò)RAM是必須的。由于ucos ii是可裁減的操作系統(tǒng),其所需要的RAM大小就取決于操作系統(tǒng)功能的多少。舉例來(lái)說(shuō),μC/OS-II允許用戶定義最大任務(wù)數(shù)。由于每建立一個(gè)任務(wù),都要產(chǎn)生一個(gè)與之相對(duì)應(yīng)的數(shù)據(jù)結(jié)構(gòu)TCB,該數(shù)據(jù)結(jié)構(gòu)要占用很大一部分內(nèi)存空間。所以在定義最大任務(wù)數(shù)時(shí),一定要考慮實(shí)際情況的需要。如果定得過(guò)大,勢(shì)必會(huì)造成不必要的浪費(fèi)。嵌入ucos ii以后,總的RAM需求可以由如下表達(dá)式得出:

  RAM總需求=應(yīng)用程序的RAM需求+內(nèi)核數(shù)據(jù)區(qū)的RAM需求+(任務(wù)棧需求+最大中斷嵌套棧需求)·任務(wù)數(shù)
所幸的是,μC/OS-II可以對(duì)每個(gè)任務(wù)分別定義堆??臻g的大小,開(kāi)發(fā)人員可根據(jù)任務(wù)的實(shí)際需求來(lái)進(jìn)行??臻g的分配。但在RAM容量有限的情況下,還是應(yīng)該注意一下對(duì)大型數(shù)組、數(shù)據(jù)結(jié)構(gòu)和函數(shù)的使用,別忘了,函數(shù)的形參也是要推入堆棧的。

  3.ucos ii的移植也是一件需要值得注意的工作。如果沒(méi)有現(xiàn)成的移植實(shí)例的話,就必須自己來(lái)編寫(xiě)移植代碼。雖然只需要改動(dòng)兩個(gè)文件,但仍需要對(duì)相應(yīng)的微處理器比較熟悉才行,最好參照已有的移植實(shí)例。另外,即使有移植實(shí)例,在編程前最好也要閱讀一下,因?yàn)槔锩鏍砍兜蕉褩2僮?。在編?xiě)中斷服務(wù)程序時(shí),把寄存器推入堆棧的順序必須與移植代碼中的順序相對(duì)應(yīng)。

  4.和其他一些著名的嵌入式操作系統(tǒng)不同,ucos ii在單片機(jī)系統(tǒng)中的啟動(dòng)過(guò)程比較簡(jiǎn)單,不像有些操作系統(tǒng)那樣,需要把內(nèi)核編譯成一個(gè)映像文件寫(xiě)入ROM中,上電復(fù)位后,再?gòu)腞OM中把文件加載到RAM中去,然后再運(yùn)行應(yīng)用程序。ucos ii的內(nèi)核是和應(yīng)用程序放在一起編譯成一個(gè)文件的,使用者只需要把這個(gè)文件轉(zhuǎn)換成HEX格式,寫(xiě)入ROM中就可以了,上電后,會(huì)像普通的單片機(jī)程序一樣運(yùn)行。

結(jié)語(yǔ)
  由以上介紹可以看出,ucos ii具有免費(fèi)、使用簡(jiǎn)單、可靠性高、實(shí)時(shí)性好等優(yōu)點(diǎn),但也有移植困難、缺乏必要的技術(shù)支持等缺點(diǎn),尤其不像商用嵌入式系統(tǒng)那樣得到廣泛使用和持續(xù)的研究更新。但開(kāi)放性又使得開(kāi)發(fā)人員可以自行裁減和添加所需的功能,在許多應(yīng)用領(lǐng)域發(fā)揮著獨(dú)特的作用。當(dāng)然,是否在單片機(jī)系統(tǒng)中嵌入ucos ii應(yīng)視所開(kāi)發(fā)的項(xiàng)目而定,對(duì)于一些簡(jiǎn)單的、低成本的項(xiàng)目來(lái)說(shuō),就沒(méi)必要使用嵌入式操作系統(tǒng)了。
 

本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)。
打開(kāi)APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
uCOS II的移植步驟
uCOS II內(nèi)核調(diào)度分析
μCOSII在Cortex-M3核ARM處理器上的移植
ucos II任務(wù)管理之一:掛起任務(wù)
ucos-II延時(shí)函數(shù)
一步一步教你使用uCOS
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服