




版權(quán)說(shuō)明:本文檔由用戶(hù)提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、的 AVR 的 RTOS建立一個(gè)屬于序自從 03 年以來(lái),對(duì)單片機(jī)的 RTOS 的學(xué)習(xí)和應(yīng)用的熱潮可謂一浪高過(guò)一浪.03 年,在離開(kāi)校園前的,的之。,在華師的后門(mén)那里買(mǎi)了本邵的UCOSII,通讀了幾次,沒(méi)有實(shí)驗(yàn)器材,也不了了在 21IC 上,大家都可以看到寫(xiě)的關(guān)于 UCOSII 在 51 上的移植,于是掀起了 51 上的 RTOS 的熱潮。再后來(lái),推出的 small rots,展示了一個(gè)用在 51 上的微內(nèi)核,足以在 52 上進(jìn)行任務(wù)調(diào)度。前段時(shí)間,在 ouravr 上面開(kāi)有專(zhuān)門(mén)關(guān)于 AVR 的 Rtos 的專(zhuān)欄,并且不少的兄弟把的拿出來(lái),著實(shí)開(kāi)了不少眼界。這時(shí),我重新回顧了使用單片機(jī)的經(jīng)歷,
2、覺(jué)得很有必要,從根本上對(duì)單片機(jī)的 RTOS的知識(shí)進(jìn)行整理,于是,我開(kāi)始了編寫(xiě)一個(gè)用在 AVR 單片機(jī)的 RTOS。當(dāng)時(shí),我所有的知識(shí)和有:1、Proteus6.7可以用來(lái)模擬avr 系列的單片機(jī)2、WinAVR v8 基于GCC AVR 的編譯環(huán)境,好處在于可以在 C 語(yǔ)言中asm 的語(yǔ)句3、mega8 1K 的ram 有 8K 的rom,是開(kāi)發(fā) 8 位的RTOS 的一個(gè)理想的器件,并且我對(duì)它也比較熟悉。寫(xiě)UCOS 的Jean J.Labrosse 在他的書(shū)上有這樣一句話(huà),“漸漸地,我自然會(huì)想到,寫(xiě)個(gè)實(shí)時(shí)內(nèi)核直有那么難嗎?不就是不斷地保存,恢復(fù) CPU 的那些寄存器嘛?!焙昧?,當(dāng)
3、這一切準(zhǔn)備好后,我們就可以開(kāi)始我們的 Rtos for mega8 的實(shí)驗(yàn)之旅了。本文列出的例子,全部完整可用。只需要一個(gè)文件就可以編譯了。我相信,只要適當(dāng)可用,最簡(jiǎn)單的就是最好的,這樣可以排除一些不必要的干擾,讓大家專(zhuān)注到每一個(gè)過(guò)程的學(xué)習(xí)。第一篇:函數(shù)的運(yùn)行在一般的單片機(jī)系統(tǒng)中,是以前例子如下:的方式(大循環(huán)+中斷)來(lái)處理數(shù)據(jù)和作出反應(yīng)的。makefile 的設(shè)定:運(yùn)行 WinAvr 中的Mfile,設(shè)定如下MCU Type: mega8Optimization level: s Debug format :AVR-COFFC/C+ source file: 選譯要編譯的 C 文件#incl
4、ude void fun1(void)unsigned char i=0; while(1)PORTB=i+; PORTC=0x01(i%8);int main(void)1fun1();首先,提出一個(gè)問(wèn)題:如果要調(diào)用一個(gè)函數(shù),真是只能以上面的方式進(jìn)行嗎?相信學(xué)習(xí)過(guò) C 語(yǔ)言的各位會(huì)回答,No!我們還有式,就是“用函數(shù)指針變量調(diào)用函數(shù)”,如果大家先生的C 程序設(shè)計(jì)的話(huà),請(qǐng)找回書(shū)的第 10.5 節(jié)。都和我一樣,當(dāng)初的教科書(shū)是例子:用函數(shù)指針變量調(diào)用函數(shù)#include void fun1(void)unsigned char i=0; while(1)PORTB=i+; PORTC=0x01(i
5、%8);void (*pfun)(); /指向函數(shù)的指針int main(void)pfun=fun1; /(*pfun)(); /運(yùn)行指針?biāo)赶虻暮瘮?shù)第二種,是“把指向函數(shù)的指針變量作函數(shù)參數(shù)”#include void fun1(void)unsigned char i=0; while(1)PORTB=i+; PORTC=0x01(i%8);void RunFun(void (*pfun)() /獲得了要傳遞的函數(shù)的地址(*pfun)();/在 RunFun 中,運(yùn)行指針?biāo)赶虻暮瘮?shù)int main(void)RunFun(fun1);/將函數(shù)的指針作為變量傳遞看到上面的兩種方式,很多人
6、可能會(huì)說(shuō),“這的確不錯(cuò)”,但是這樣與我們想要的 RTOS,有什么關(guān)系呢? 各位請(qǐng)細(xì)心向下看。以下是GCC 對(duì)上面的代碼的編譯的情況:2對(duì)main()中的RunFun(fun1); 的編譯如下ldi r24,lo8(pm(fun1)ldi r25,hi8(pm(fun1) rcall RunFun對(duì) void RunFun(void (*pfun)()的編譯如下/*void RunFun(void (*pfun)()*/*(*pfun)();*/.LM6:movw r30,r24 icallret在調(diào)用 void RunFun(void (*pfun)()的時(shí)候,的確可以把 fun1 的地址通過(guò)
7、 r24 和r25 傳遞給 RunFun()。但是,RTOS 如何才能有效地利用函數(shù)的地址呢?第二篇: 人工堆棧在單片機(jī)的指令集中,一類(lèi)指令是專(zhuān)門(mén)與堆棧和 PC 指針打道的,它們是rcall 相對(duì)調(diào)用子程序指令icall retreti間接調(diào)用子程序指令子程序返回指令中斷返回指令對(duì)于 ret 和 reti,它們都可以將堆棧棧頂?shù)膬蓚€(gè)字節(jié)被彈出來(lái)送入程序計(jì)數(shù)器 PC 中,一般用來(lái)從子程序或中斷中。其中reti 還可以在中斷時(shí),重開(kāi)全局中斷使能。有了這個(gè)基礎(chǔ),就可以建立我們的人工堆棧了。例:#include void fun1(void)unsigned char i=0; while(1)POR
8、TB=i+; PORTC=0x018; /將函數(shù)的地址壓入堆棧,SP=pStack;/將堆棧指針指向人工堆棧的棧頂 asmvolatile (RET t); /返回并開(kāi)中斷,開(kāi)始運(yùn)行 fun1()3int main(void)RunFunInNewStack(fun1,&Stack99);RunFunInNewStack(),將指向函數(shù)的指針的值保存到一個(gè) unsigned char 的數(shù)組Stack 中,作為人工堆棧。并且將棧頂?shù)臄?shù)值傳遞組堆棧指針 SP,因此當(dāng)用ret返回時(shí),從SP 中恢復(fù)到PC 中的值,就變?yōu)榱酥赶?fun1() 的地址,開(kāi)始運(yùn)行 fun1().上面例子中在 RunFun
9、InNewStack()的最后一句嵌入了匯編代碼 ret,實(shí)際上是可以去除的。因?yàn)樵赗unFunInNewStack()返回時(shí),編譯器已經(jīng)會(huì)加上ret。我特意寫(xiě)出來(lái),是為了讓大家看到用ret作為返回后運(yùn)行fun1()的過(guò)程。第三篇:GCC 中對(duì)寄存器的分配與使用在很多用于 AVR 的RTOS 中,都會(huì)有任務(wù)調(diào)度時(shí),入棧:以下的語(yǔ)句: asmvolatile (PUSH R0 asmvolatile (PUSH R1. asmvolatile (PUSH R31出棧 asmvolatile (POP R31. asmvolatile (POP R1 asmvolatile (POP R0t);t
10、);t);t);t);t);通常大家都會(huì)認(rèn)為,在任務(wù)調(diào)度開(kāi)始時(shí),當(dāng)然要將所有的通用寄存器都保存,并且還應(yīng)該保存態(tài)寄存器 SREG。然后再根據(jù)相反的次序,將新任務(wù)的寄存器的內(nèi)容恢復(fù)。但是,事實(shí)真的是這樣嗎?如果大家看過(guò)器不過(guò)是 4 組通用寄存器中的 1 組。寫(xiě)的 small rots51,就會(huì)發(fā)現(xiàn),它所保存的通用寄存在Win AVR 中的幫助文件 avr-libc Manual 中的Related Pages 中的Frequently Asked Questions,其實(shí)有一個(gè)問(wèn)題是What registers are used by the C compiler? 回答了編譯器所需要占用的寄存
11、器。一般情況下,編譯器會(huì)先用到以下寄存器1 Call-used registers (r18-r27, r30-r31): 調(diào)用函數(shù)時(shí)作為參數(shù)傳遞,也就是用得最多的寄存器。2 Call-saved registers (r2-r17, r28-r29): 調(diào)用函數(shù)時(shí)作為結(jié)果傳遞,當(dāng)中的 r28 和 r29 可能會(huì)被作為指向堆棧上的變量的指針。3 Fixed registers (r0, r1): 固定作用。r0 用于存放臨時(shí)數(shù)據(jù),r1 用于存放 0。還有另一個(gè)問(wèn)題是How to permanently bind a variable to a register?,是將變量綁定到通用寄存器的方法
12、。而且我發(fā)現(xiàn),如果將某個(gè)寄存器定義為變量,編譯器就會(huì)不將該寄存器分配作是很重要的。這對(duì) RTOS在Inline Asm中的C Names Used in Assembler Code明確表示,如果將太多的通用寄存器定義為變量, 剛在編譯的過(guò)程中,被定義的變量依然可能被編譯器占用。大家可以比較以下兩個(gè)例子,看看編譯器產(chǎn)生的代碼:(在*.lst 文件中) 第一個(gè)例子:沒(méi)有定義通用寄存器為變量#include 4unsigned char add(unsigned char b,unsigned char c,unsigned char d)return b+c*d;int main(void)un
13、signed char a=0; while(1)a+;PORTB=add(a,a,a);在本例中,add(a,a,a);被編譯如下:mov r20,r28 mov r22,r28 mov r24,r28 rcall add第二個(gè)例子:定義通用寄存器為變量#include unsigned char add(unsigned char b,unsigned char c,unsigned char d)return b+c*d;register unsigned char a asm(r20); /將 r20 定義為 變量 a int main(void)while(1)a+;PORTB=ad
14、d(a,a,a);在本例中,add(a,a,a);被編譯如下:mov r22,r20 mov r24,r20 rcall add當(dāng)然,在上面兩個(gè)例子中,有部份代碼被編譯器優(yōu)化了。通過(guò)反復(fù)測(cè)試,發(fā)現(xiàn)編譯器一般使用如下寄存器:第 1 類(lèi)寄存器,第 2 類(lèi)寄存器的 r28,r29,第 3 類(lèi)寄存器如在中斷函數(shù)中有調(diào)用基它函數(shù),中斷又將它們出棧。在進(jìn)入中斷后,固定地將第 1 類(lèi)寄存器和第 3 類(lèi)寄存器入棧,在第四篇:只有延時(shí)服務(wù)的協(xié)作式的內(nèi)核5Cooperative Multitasking前系統(tǒng),協(xié)作式內(nèi)核系統(tǒng),與占先式內(nèi)核系統(tǒng),有什么不同呢?記得在 21IC 上看過(guò)這樣的比喻,“你(小工)在用廁所
15、,經(jīng)理在外面排第一,在外面排第二。如果是前,不管是誰(shuí),都必須按排隊(duì)的次序使用廁所;如果是協(xié)作式,那么可以等你用完廁所,就要比經(jīng)理先進(jìn)入;如果是占先式,只要有更高級(jí)的人在外面等,那么廁所里無(wú)論是誰(shuí),都要第一時(shí)間讓出來(lái),讓別的人先用?!?#include #include #include unsigned char Stack200;register unsigned char OSRdyTblasm(r2); /任務(wù)運(yùn)行就緒表register unsigned char OSTaskRunningPrio asm(r3); /正在運(yùn)行的任務(wù)#define OS_TASKS 3 struct T
16、askCtrBlock/設(shè)定運(yùn)行任務(wù)的數(shù)量/任務(wù)塊unsigned int OSTaskStackTop; /保存任務(wù)的堆棧頂unsigned int OSWaitTick; TCBOS_TASKS+1;/防止被編譯器占用/任務(wù)延時(shí)時(shí)鐘register unsigned char tempR4 asm(r4); register unsigned char tempR5 asm(r5); register unsigned char tempR6 asm(r6); register unsigned char tempR7 asm(r7); register unsigned char tem
17、pR8 asm(r8); register unsigned char tempR9 asm(r9); register unsigned char tempR10 asm(r10); register unsigned char tempR11 asm(r11); register unsigned char tempR12 asm(r12); register unsigned char tempR13 asm(r13); register unsigned char tempR14 asm(r14); register unsigned char tempR15 asm(r15); re
18、gister unsigned char tempR16 asm(r16); register unsigned char tempR16 asm(r17);/建立任務(wù)void OSTaskCreate(void (*Task)(void),unsigned char *Stack,unsigned char TaskID)unsigned char i;*Stack-=(unsigned int)Task8; /將任務(wù)的地址壓入堆棧,*Stack-=(unsigned int)Task;/將任務(wù)的地址低位壓入堆棧,*Stack-=0x00;*Stack-=0x00;*Stack-=0x80;
19、/R1 zero_reg /R0 tmp_reg /SREG 在任務(wù)中,開(kāi)啟全局中斷6for(i=0;i14;i+)*Stack-=i;/在 avr-libc 中的 FAQ 中的 What registers are used by the C compiler?/描述了寄存器的作用TCBTaskID.OSTaskStackTop=(unsigned int)Stack; /將人工堆棧的棧頂,保存到堆棧的數(shù)組中OSRdyTbl|=0x01TaskID;/任務(wù)就緒表已經(jīng)準(zhǔn)備好/開(kāi)始任務(wù)調(diào)度,從最低優(yōu)先級(jí)的任務(wù)的開(kāi)始void OSStartTask()OSTaskRunningPrio=OS_TA
20、SKS; SP=TCBOS_TASKS.OSTaskStackTop+17; asmvolatile ( reti t );/進(jìn)行任務(wù)調(diào)度void OSSched(void)/ 根據(jù)中斷時(shí)保存寄存器的次序入棧,模擬一次中斷棧的情況 asmvolatile (PUSH zero_reg asmvolatile (PUSH tmp_reg t); /R1t); /R0 asmvolatile (IN tmp_reg , SREG t); /保存狀態(tài)寄存器 SREG asmvolatile (PUSH tmp_reg asmvolatile (CLR zero_reg asmvolatile (PU
21、SH R18 asmvolatile (PUSH R19 asmvolatile (PUSH R20 asmvolatile (PUSH R21 asmvolatile (PUSH R22 asmvolatile (PUSH R23 asmvolatile (PUSH R24 asmvolatile (PUSH R25 asmvolatile (PUSH R26 asmvolatile (PUSH R27 asmvolatile (PUSH R30 asmvolatile (PUSH R31 asmvolatile (PUSH R28 asmvolatile (PUSH R29t);t); /
22、R0 重新清零t);t);t);t);t);t);t);t);t);t);t);t);t);t);/R28 與R29 用于建立在堆棧上的指針/入棧完成TCBOSTaskRunningPrio.OSTaskStackTop=SP; unsigned char OSNextTaskID;for (OSNextTaskID = 0;/將正在運(yùn)行的任務(wù)的堆棧底保存/在現(xiàn)有堆棧上開(kāi)設(shè)新的空間/進(jìn)行任務(wù)調(diào)度OSNextTaskID OS_TASKS & !(OSRdyTbl & (0x01OSNextTaskID); OSNextTaskID+);OSTaskRunningPrio = OSNextTas
23、kID ; cli(); /保護(hù)堆棧轉(zhuǎn)換SP=TCBOSTaskRunningPrio.OSTaskStackTop;sei();7/根據(jù)中斷時(shí)的出棧次序 asmvolatile (POP R29t);t);t);t);t);t);t);t);t);t);t);t);t);t); asmvolatile (POP asmvolatile (POP asmvolatile (POP asmvolatile (POP asmvolatile (POP asmvolatile (POP asmvolatile (POP asmvolatile (POP asmvolatile (POP asmvol
24、atile (POP asmvolatile (POP asmvolatile (POP asmvolatile (POP asmvolatile (POP asmvolatile (OUT asmvolatile (POP asmvolatile (POP/中斷時(shí)出棧完成R28 R31 R30 R27 R26 R25 R24 R23 R22 R21 R20 R19R18 tmp_reg t);/SERG 出棧并恢復(fù) SREG , tmp_reg t);/ tmp_reg t); zero_reg t);/R0 出棧/R1 出棧void OSTimeDly(unsigned int ticks
25、)if(ticks)/當(dāng)延時(shí)有效OSRdyTbl &= (0x01OSTaskRunningPrio);TCBOSTaskRunningPrio.OSWaitTick=ticks;OSSched();/從新調(diào)度void TCN0Init(void) /TCCR0 = 0;器 0TCCR0 |= (1CS02); / 256 預(yù)分頻TIMSK |= (1TOIE0); / T0 溢出中斷TCNT0 = 100;/ 置計(jì)數(shù)起始值 SIGNAL(SIG_OVERFLOW0)unsigned char i; for(i=0;iOS_TASKS;i+)if(TCBi.OSWaitTick)/任務(wù)時(shí)鐘8T
26、CBi.OSWaitTick-; if(TCBi.OSWaitTick=0)OSRdyTbl |= (0x01i);/當(dāng)任務(wù)時(shí)鐘到時(shí),必須是由定時(shí)器減時(shí)的/使任務(wù)在就緒表中置位TCNT0=100;void Task0()unsigned int j=0; while(1)PORTB=j+;OSTimeDly(2);void Task1()unsigned int j=0; while(1)PORTC=j+;OSTimeDly(4);void Task2()unsigned int j=0; while(1)PORTD=j+;OSTimeDly(8);void TaskScheduler()wh
27、ile(1)9OSSched();/反復(fù)進(jìn)行調(diào)度int main(void)TCN0Init();OSRdyTbl=0; OSTaskRunningPrio=0; OSTaskCreate(Task0,&Stack49,0); OSTaskCreate(Task1,&Stack99,1); OSTaskCreate(Task2,&Stack149,2);OSTaskCreate(TaskScheduler,&Stack199,OS_TASKS); OSStartTask();在上面的例子中,一切變得很簡(jiǎn)單,三個(gè)正在運(yùn)行的權(quán)。務(wù),都通過(guò)延時(shí)服務(wù),主動(dòng)放棄對(duì) CPU 的在時(shí)間中斷中,對(duì)各個(gè)任務(wù)的的
28、延時(shí)進(jìn)行,如果某個(gè)任務(wù)的延時(shí)結(jié)束,將任務(wù)重新在就緒表中置位最低級(jí)的系統(tǒng)任務(wù) TaskScheduler(),在三個(gè)果某個(gè)任務(wù)在就緒表中置位,通過(guò)調(diào)度,進(jìn)入務(wù)在放棄對(duì) CPU 的別的任務(wù)中繼續(xù)運(yùn)行。權(quán)后開(kāi)始不斷地進(jìn)行調(diào)度。如第五篇: 完善的協(xié)作式的內(nèi)核現(xiàn)在為上面的協(xié)作式內(nèi)核添加一些 OS 中所必須的服務(wù):123掛起和重新運(yùn)行任務(wù)信號(hào)量(在必要時(shí)候,可以擴(kuò)展成郵箱和信息隊(duì)列) 延時(shí)#include #include #include unsigned char Stack400;register unsigned char OSRdyTblasm(r2); /任務(wù)運(yùn)行就緒表register uns
29、igned char OSTaskRunningPrio asm(r3); /正在運(yùn)行的任務(wù)#define OS_TASKS 3 struct TaskCtrBlock/設(shè)定運(yùn)行任務(wù)的數(shù)量unsigned int OSTaskStackTop; /保存任務(wù)的堆棧頂unsigned int OSWaitTick;/任務(wù)延時(shí)時(shí)鐘10 TCBOS_TASKS+1;/防止被編譯器占用register unsigned char tempR4 asm(r4); register unsigned char tempR5 asm(r5); register unsigned char tempR6 asm
30、(r6); register unsigned char tempR7 asm(r7); register unsigned char tempR8 asm(r8); register unsigned char tempR9 asm(r9); register unsigned char tempR10 asm(r10); register unsigned char tempR11 asm(r11); register unsigned char tempR12 asm(r12); register unsigned char tempR13 asm(r13); register unsi
31、gned char tempR14 asm(r14); register unsigned char tempR15 asm(r15); register unsigned char tempR16 asm(r16); register unsigned char tempR16 asm(r17);/建立任務(wù)void OSTaskCreate(void (*Task)(void),unsigned char *Stack,unsigned char TaskID)unsigned char i;*Stack-=(unsigned int)Task8; /將任務(wù)的地址壓入堆棧,*Stack-=(
32、unsigned int)Task;/將任務(wù)的地址低位壓入堆棧,*Stack-=0x00;*Stack-=0x00;*Stack-=0x80;/R1 zero_reg /R0 tmp_reg /SREG 在任務(wù)中,開(kāi)啟全局中斷for(i=0;i14;i+)*Stack-=i;/在 avr-libc 中的 FAQ 中的 What registers are used by the C compiler?/描述了寄存器的作用TCBTaskID.OSTaskStackTop=(unsigned int)Stack; /將人工堆棧的棧頂,保存到堆棧的數(shù)組中OSRdyTbl|=0x01TaskID;/任
33、務(wù)就緒表已經(jīng)準(zhǔn)備好/開(kāi)始任務(wù)調(diào)度,從最低優(yōu)先級(jí)的任務(wù)的開(kāi)始void OSStartTask()OSTaskRunningPrio=OS_TASKS; SP=TCBOS_TASKS.OSTaskStackTop+17; asmvolatile ( reti t );/進(jìn)行任務(wù)調(diào)度void OSSched(void)11/ 根據(jù)中斷時(shí)保存寄存器的次序入棧,模擬一次中斷棧的情況 asmvolatile (PUSH zero_reg asmvolatile (PUSH tmp_reg t); /R1t); /R0 asmvolatile (IN tmp_reg , SREG t); /保存狀態(tài)寄存器
34、SREG asmvolatile (PUSH tmp_reg asmvolatile (CLR zero_reg asmvolatile (PUSH R18 asmvolatile (PUSH R19 asmvolatile (PUSH R20 asmvolatile (PUSH R21 asmvolatile (PUSH R22 asmvolatile (PUSH R23 asmvolatile (PUSH R24 asmvolatile (PUSH R25 asmvolatile (PUSH R26 asmvolatile (PUSH R27 asmvolatile (PUSH R30 a
35、smvolatile (PUSH R31 asmvolatile (PUSH R28 asmvolatile (PUSH R29t);t); /R0 重新清零t);t);t);t);t);t);t);t);t);t);t);t);t);t);/R28 與R29 用于建立在堆棧上的指針/入棧完成TCBOSTaskRunningPrio.OSTaskStackTop=SP; unsigned char OSNextTaskID;for (OSNextTaskID = 0;/將正在運(yùn)行的任務(wù)的堆棧底保存/在現(xiàn)有堆棧上開(kāi)設(shè)新的空間/進(jìn)行任務(wù)調(diào)度OSNextTaskID OS_TASKS & !(OSR
36、dyTbl & (0x01OSNextTaskID); OSNextTaskID+);OSTaskRunningPrio = OSNextTaskID ; cli(); /保護(hù)堆棧轉(zhuǎn)換SP=TCBOSTaskRunningPrio.OSTaskStackTop; sei();/根據(jù)中斷時(shí)的出棧次序 asmvolatile (POP asmvolatile (POP asmvolatile (POP asmvolatile (POP asmvolatile (POP asmvolatile (POP asmvolatile (POP asmvolatile (POP asmvolatile (P
37、OP asmvolatile (POP asmvolatile (POP asmvolatile (POP asmvolatile (POPR29 R28 R31 R30 R27 R26 R25 R24 R23 R22 R21 R20R19t);t);t);t);t);t);t);t);t);t);t);t);t);12 asmvolatile (POP R18t); asmvolatile (POP tmp_regt);/SERG 出棧并恢復(fù) asmvolatile (OUT SREG , tmp_reg t);/ asmvolatile (POP tmp_reg asmvolatile (
38、POP zero_reg /中斷時(shí)出棧完成t);/R0 出棧t);/R1 出棧/任務(wù)處理/掛起任務(wù)void OSTaskSuspend(unsigned char prio)TCBprio.OSWaitTick=0;OSRdyTbl &= (0x01prio); /從任務(wù)就緒表上去除標(biāo)志位if(OSTaskRunningPrio=prio) /當(dāng)要掛起的任務(wù)為當(dāng)前任務(wù)OSSched();/從新調(diào)度/恢復(fù)任務(wù) 可以讓被 OSTaskSuspend 或 OSTimeDly 暫停的任務(wù)恢復(fù)void OSTaskResume(unsigned char prio)OSRdyTbl |= 0x01pri
39、o) /當(dāng)要當(dāng)前任務(wù)的優(yōu)先級(jí)低于重置位的任務(wù)的優(yōu)先級(jí)OSSched();/從新調(diào)度/ 任務(wù)延時(shí)void OSTimeDly(unsigned int ticks)if(ticks)/當(dāng)延時(shí)有效OSRdyTbl &= (0x01OSTaskRunningPrio);TCBOSTaskRunningPrio.OSWaitTick=ticks;OSSched();/從新調(diào)度/信號(hào)量struct SemBlkunsigned char OSEventType;/型號(hào) 0,信號(hào)量unsigned char OSEventState; /狀態(tài) 0,不可用;1,可用;1 信號(hào)量共享型unsigned cha
40、r OSTaskPendTbl; /等待信號(hào)量的任務(wù)列表 Sem10;/初始化信號(hào)量void OSSemCreat(unsigned char Index,unsigned char Type)13SemIndex.OSEventType=Type; /型號(hào) 0,信號(hào)量SemIndex.OSTaskPendTbl=0; SemIndex.OSEventState=0;;1 信號(hào)量共享型/任務(wù)等待信號(hào)量,掛起unsigned char OSTaskSemPend(unsigned char Index,unsigned int Timeout)/unsigned char i=0;if(SemI
41、ndex.OSEventState)if(SemIndex.OSEventType=0) SemIndex.OSEventState = 0x00;else/信號(hào)量有效/如果為/信號(hào)量被獨(dú)占,不可用/加入信號(hào)的任務(wù)等待表SemIndex.OSTaskPendTbl |= 0x01OSTaskRunningPrio;OSRdyTbl &= (0x01OSTaskRunningPrio); /從任務(wù)就緒表中去除TCBOSTaskRunningPrio.OSWaitTick=Timeout; /如延時(shí)為 0,剛無(wú)限等待OSSched(); /從新調(diào)度if(TCBOSTaskRunningPrio.O
42、SWaitTick=0) return 0;return 1;/一個(gè)信號(hào)量,可以從任務(wù)或中斷void OSSemPost(unsigned char Index)if(SemIndex.OSEventType)SemIndex.OSEventState=0x01;/當(dāng)要求的信號(hào)量是共享型/使信號(hào)量有效OSRdyTbl |=Sem Index.OSTaskPendTbl; /使在等待該信號(hào)的所有任務(wù)就緒SemIndex.OSTaskPendTbl=0;/清空所有等待該信號(hào)的等待任務(wù)elseunsigned char i;/當(dāng)要求的信號(hào)量為for (i = 0; i OS_TASKS & !(Se
43、mIndex.OSTaskPendTbl & (0x01i); i+);if(i OS_TASKS)/如果有任務(wù)需要SemIndex.OSTaskPendTbl &= (0x01i); /從等待表中去除OSRdyTbl |= 0x01i;/任務(wù)就緒else14SemIndex.OSEventState =1;/使信號(hào)量有效/從任務(wù)一個(gè)信號(hào)量,并進(jìn)行調(diào)度void OSTaskSemPost(unsigned char Index)OSSemPost(Index); OSSched();/清除一個(gè)信號(hào)量,只對(duì)共享型的有用。/對(duì)于的信號(hào)量,在任務(wù)占用后,就交得不可以用了。void OSSemClea
44、n(unsigned char Index)SemIndex.OSEventState =0;/要求的信號(hào)量無(wú)效void TCN0Init(void) /TCCR0 = 0;器 0TCCR0 |= (1CS02); / 256 預(yù)分頻TIMSK |= (1TOIE0); / T0 溢出中斷TCNT0 = 100;/ 置計(jì)數(shù)起始值 SIGNAL(SIG_OVERFLOW0)unsigned char i; for(i=0;iOS_TASKS;i+)/任務(wù)時(shí)鐘if(TCBi.OSWaitTick)TCBi.OSWaitTick-;if(TCBi.OSWaitTick=0)OSRdyTbl |= (
45、0x01i);/當(dāng)任務(wù)時(shí)鐘到時(shí),必須是由定時(shí)器減時(shí)的/使任務(wù)在就緒表中置位 TCNT0=100;void Task0()unsigned int j=0; while(1)15PORTB=j+;OSTaskSuspend(1); OSTaskSemPost(0); OSTimeDly(50); OSTaskResume(1); OSSemClean(0); OSTimeDly(50);/掛起任務(wù) 1/恢復(fù)任務(wù) 1void Task1()unsigned int j=0; while(1)PORTC=j+;OSTimeDly(5);void Task2()unsigned int j=0; wh
46、ile(1)OSTaskSemPend(0,10); PORTD=j+;OSTimeDly(5);void TaskScheduler()while(1)OSSched();/反復(fù)進(jìn)行調(diào)度int main(void)TCN0Init();OSRdyTbl=0;OSSemCreat(0,1); /將信號(hào)量設(shè)為共享型OSTaskCreate(Task0,&Stack99,0); OSTaskCreate(Task1,&Stack199,1); OSTaskCreate(Task2,&Stack299,2); OSTaskCreate(TaskScheduler,&Stack399,OS_TASKS);16OSStartTask();第六篇:時(shí)間片輪番調(diào)度法的內(nèi)核Round-Robin Sheduling時(shí)間片輪調(diào)法是非常有趣的。本篇中的例子,建立了 3 個(gè)任務(wù),任務(wù)沒(méi)有優(yōu)先級(jí),在時(shí)間中斷的調(diào)度下,每個(gè)任務(wù)都輪流運(yùn)行相同的時(shí)間。如果在內(nèi)核中沒(méi)有加入其它服務(wù),感覺(jué)上就好像是有三個(gè)大循環(huán)在同時(shí)運(yùn)行。本例只是提供了一個(gè)用時(shí)間中斷進(jìn)行調(diào)度的內(nèi)核,大家可以根據(jù)要注意到:的需要,添加相應(yīng)的服務(wù)。1,由于在時(shí)間中斷內(nèi)調(diào)用了任務(wù)切換函數(shù),因?yàn)樵?/p>
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶(hù)所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶(hù)上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶(hù)上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶(hù)因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 世紀(jì)廣場(chǎng)幼兒園活動(dòng)方案
- 業(yè)主到訪(fǎng)活動(dòng)方案
- 業(yè)主物業(yè)拜年活動(dòng)方案
- 天府書(shū)展活動(dòng)方案
- 培訓(xùn)銷(xiāo)售茶葉活動(dòng)方案
- 大型營(yíng)銷(xiāo)活動(dòng)策劃方案
- 城市樂(lè)章活動(dòng)策劃方案
- 大型兒童人氣活動(dòng)方案
- 大班科普故事活動(dòng)方案
- 夏日喝酒活動(dòng)方案
- 智能機(jī)器人介紹課件
- 胎心監(jiān)護(hù)醫(yī)學(xué)宣教
- 2024屆四川省成都市溫江區(qū)八年級(jí)語(yǔ)文第二學(xué)期期末達(dá)標(biāo)測(cè)試試題含解析
- 電商平臺(tái)的運(yùn)營(yíng)和增長(zhǎng)策略
- 家庭安全隱患排查和應(yīng)對(duì)策略及方案
- 《塞翁失馬》課件
- 慣性導(dǎo)航與組合導(dǎo)航
- 急性腎盂腎炎疾病查房
- 第九屆全國(guó)大學(xué)生化學(xué)實(shí)驗(yàn)邀請(qǐng)賽無(wú)機(jī)分析題
- 單位就業(yè)人員登記表
- 《應(yīng)用寫(xiě)作》(第三版)復(fù)習(xí)思考、案例訓(xùn)練參考答案
評(píng)論
0/150
提交評(píng)論