????自從03年以來,對(duì)單片機(jī)的RTOS的學(xué)習(xí)和應(yīng)用的熱潮可謂一浪高過一浪.03年,在離開校園前的,非典的那幾個(gè)月,在華師的后門那里買了本邵貝貝的《UCOSII》,通讀了幾次,沒有實(shí)驗(yàn)器材,也不了了之。
????在21IC上,大家都可以看到楊屹寫的關(guān)于UCOSII在51上的移植,于是掀起了51上的RTOS的熱潮。
????再后來,陳明計(jì)先生推出的small?rots,展示了一個(gè)用在51上的微內(nèi)核,足以在52上進(jìn)行任務(wù)調(diào)度。
????前段時(shí)間,在ouravr上面開有專門關(guān)于AVR的Rtos的專欄,并且不少的兄弟把自己的作品拿出來,著實(shí)開了不少眼界。這時(shí),我重新回顧了使用單片機(jī)的經(jīng)歷,覺得很有必要,從根本上對(duì)單片機(jī)的RTOS的知識(shí)進(jìn)行整理,于是,我開始了編寫一個(gè)用在AVR單片機(jī)的RTOS。
???
????當(dāng)時(shí),我所有的知識(shí)和資源有:?
????Proteus6.7????????可以用來模擬仿真avr系列的單片機(jī)
????WinAVR?v2.0.5.48??基于GCC?AVR的編譯環(huán)境,好處在于可以在C語言中插入asm的語句
????mega8??1K的ram有8K的rom,是開發(fā)8位的RTOS的一個(gè)理想的器件,并且我對(duì)它也比較熟悉。
????
????寫UCOS的Jean?J.Labrosse在他的書上有這樣一句話,“漸漸地,我自然會(huì)想到,寫個(gè)實(shí)時(shí)內(nèi)核直有那么難嗎?不就是不斷地保存,恢復(fù)CPU的那些寄存器嘛。”?
????好了,當(dāng)這一切準(zhǔn)備好后,我們就可以開始我們的Rtos?for?mega8的實(shí)驗(yàn)之旅了。
???
????本文列出的例子,全部完整可用。只需要一個(gè)文件就可以編譯了。我相信,只要適當(dāng)可用,最簡(jiǎn)單的就是最好的,這樣可以排除一些不必要的干擾,讓大家專注到每一個(gè)過程的學(xué)習(xí)。
第一篇:函數(shù)的運(yùn)行
????在一般的單片機(jī)系統(tǒng)中,是以前后臺(tái)的方式(大循環(huán)+中斷)來處理數(shù)據(jù)和作出反應(yīng)的。
????例子如下:
???
????makefile的設(shè)定:運(yùn)行WinAvr中的Mfile,設(shè)定如下
????MCU?Type:?mega8
????Optimization?level:?s
????Debug?format?:AVR-COFF
????C/C++?source?file:?選譯要編譯的C文件
#include?
void?fun1(void)
{
??unsigned?char?i=0;
??while(1)
??{
????PORTB=i++;
????PORTC=0x01<<(i%8);
??}
}
int?main(void)
{
??fun1();
}
????首先,提出一個(gè)問題:如果要調(diào)用一個(gè)函數(shù),真是只能以上面的方式進(jìn)行嗎?
????相信學(xué)習(xí)過C語言的各位會(huì)回答,No!我們還有一種方式,就是“用函數(shù)指針變量調(diào)用函數(shù)”,如果大家都和我一樣,當(dāng)初的教科書是譚浩強(qiáng)先生的《C程序設(shè)計(jì)》的話,請(qǐng)找回書的第9.5節(jié)。
????
????例子:用函數(shù)指針變量調(diào)用函數(shù)
#include?
void?fun1(void)
{
??unsigned?char?i=0;
??while(1)
??{
????PORTB=i++;
????PORTC=0x01<<(i%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ù)的指針作為變量傳遞
????
}
????看到上面的兩種方式,很多人可能會(huì)說,“這的確不錯(cuò)”,但是這樣與我們想要的RTOS,有什么關(guān)系呢?各位請(qǐng)細(xì)心向下看。
????以下是GCC對(duì)上面的代碼的編譯的情況:
????
????對(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
??icall
??ret
????在調(diào)用void?RunFun(void?(*pfun)())的時(shí)候,的確可以把fun1的地址通過r24和r25傳遞給RunFun()。但是,RTOS如何才能有效地利用函數(shù)的地址呢?
第二篇:?人工堆棧
在單片機(jī)的指令集中,一類指令是專門與堆棧和PC指針打道的,它們是
????rcall???相對(duì)調(diào)用子程序指令
????icall???間接調(diào)用子程序指令
????ret?????子程序返回指令
????reti????中斷返回指令???
????對(duì)于ret和reti,它們都可以將堆棧棧頂?shù)膬蓚€(gè)字節(jié)被彈出來送入程序計(jì)數(shù)器PC中,一般用來從子程序或中斷中退出。其中reti還可以在退出中斷時(shí),重開全局中斷使能。
????有了這個(gè)基礎(chǔ),就可以建立我們的人工堆棧了。
????例:
#include?
void?fun1(void)
{
??unsigned?char?i=0;
??while(1)
??{
????PORTB=i++;
????PORTC=0x01<<(i%8);
??}
}
unsigned?char?Stack[100];?//建立一個(gè)100字節(jié)的人工堆棧
void?RunFunInNewStack(void?(*pfun)(),unsigned?char?*pStack)
{
??*pStack--=(unsigned?int)pfun>>8;????//將函數(shù)的地址高位壓入堆棧,
??*pStack--=(unsigned?int)pfun;????????//將函數(shù)的地址低位壓入堆棧,
??SP=pStack;????????????????????????????//將堆棧指針指向人工堆棧的棧頂
??__asm__?__volatile__("RET?nt");????//返回并開中斷,開始運(yùn)行fun1()
}
int?main(void)
{
???RunFunInNewStack(fun1,&Stack[99]);
}
?????RunFunInNewStack(),將指向函數(shù)的指針的值保存到一個(gè)unsigned??char的數(shù)組Stack中,作為人工堆棧。并且將棧頂?shù)臄?shù)值傳遞組堆棧指針SP,因此當(dāng)用"ret"返回時(shí),從SP中恢復(fù)到PC中的值,就變?yōu)榱酥赶騠un1()的地址,開始運(yùn)行fun1().
????上面例子中在RunFunInNewStack()的最后一句嵌入了匯編代碼?"ret",實(shí)際上是可以去除的。因?yàn)樵赗unFunInNewStack()返回時(shí),編譯器已經(jīng)會(huì)加上"ret"。我特意寫出來,是為了讓大家看到用"ret"作為返回后運(yùn)行fun1()的過程。
第三篇:GCC中對(duì)寄存器的分配與使用
在很多用于AVR的RTOS中,都會(huì)有任務(wù)調(diào)度時(shí),插入以下的語句:
????
????入棧:
????__asm__?__volatile__("PUSH?R0??nt");
????__asm__?__volatile__("PUSH?R1??nt");
????......
????__asm__?__volatile__("PUSH?R31?nt");
????出棧
????__asm__?__volatile__("POP??R31?nt");
????......
????__asm__?__volatile__("POP??R1??nt");
????__asm__?__volatile__("POP??R0??nt");
????通常大家都會(huì)認(rèn)為,在任務(wù)調(diào)度開始時(shí),當(dāng)然要將所有的通用寄存器都保存,并且還應(yīng)該保存程序狀態(tài)寄存器SREG。然后再根據(jù)相反的次序,將新任務(wù)的寄存器的內(nèi)容恢復(fù)。
????
????但是,事實(shí)真的是這樣嗎?如果大家看過陳明計(jì)先生寫的small?rots51,就會(huì)發(fā)現(xiàn),它所保存的通用寄存器不過是4組通用寄存器中的1組。
????
????在Win?AVR中的幫助文件?avr-libc?Manual中的Related?Pages中的Frequently?Asked?Questions,其實(shí)有一個(gè)問題是"What?registers?are?used?by?the?C?compiler?"??回答了編譯器所需要占用的寄存器。一般情況下,編譯器會(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è)問題是"How?to?permanently?bind?a?variable?to?a?register?",是將變量綁定到通用寄存器的方法。而且我發(fā)現(xiàn),如果將某個(gè)寄存器定義為變量,編譯器就會(huì)不將該寄存器分配作其它用途。這對(duì)RTOS是很重要的。
????在"Inline?Asm"中的"C?Names?Used?in?Assembler?Code"明確表示,如果將太多的通用寄存器定義為變量,剛在編譯的過程中,被定義的變量依然可能被編譯器占用。
????大家可以比較以下兩個(gè)例子,看看編譯器產(chǎn)生的代碼:(在*.lst文件中)
第一個(gè)例子:沒有定義通用寄存器為變量
#include?
unsigned?char?add(unsigned?char?b,unsigned?char?c,unsigned?char?d)
{
???return?b+c*d;
}
int?main(void)
{
??unsigned?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=add(a,a,a);
????}
}
????在本例中,"add(a,a,a);"被編譯如下:??
????mov?r22,r20
????mov?r24,r20
????rcall?add
????當(dāng)然,在上面兩個(gè)例子中,有部份代碼被編譯器優(yōu)化了。?
????
????通過反復(fù)測(cè)試,發(fā)現(xiàn)編譯器一般使用如下寄存器:
????第1類寄存器,第2類寄存器的r28,r29,第3類寄存器
????如在中斷函數(shù)中有調(diào)用基它函數(shù),剛會(huì)在進(jìn)入中斷后,固定地將第1類寄存器和第3類寄存器入棧,在退出中斷又將它們出棧。
?
第四篇:只有延時(shí)服務(wù)的協(xié)作式的內(nèi)核
???Cooperative?Multitasking
???前后臺(tái)系統(tǒng),協(xié)作式內(nèi)核系統(tǒng),與占先式內(nèi)核系統(tǒng),有什么不同呢?
???記得在21IC上看過這樣的比喻,“你(小工)在用廁所,經(jīng)理在外面排第一,老板在外面排第二。如果是前后臺(tái),不管是誰,都必須按排隊(duì)的次序使用廁所;如果是協(xié)作式,那么可以等你用完廁所,老板就要比經(jīng)理先進(jìn)入;如果是占先式,只要有更高級(jí)的人在外面等,那么廁所里無論是誰,都要第一時(shí)間讓出來,讓最高級(jí)別的人先用。”
#include?
#include?
#include?
unsigned?char?Stack[200];
register?unsigned?char?OSRdyTbl??????????asm("r2");????//任務(wù)運(yùn)行就緒表
register?unsigned?char?OSTaskRunningPrio?asm("r3");????//正在運(yùn)行的任務(wù)
#define?OS_TASKS?3????????????????????//設(shè)定運(yùn)行任務(wù)的數(shù)量
struct?TaskCtrBlock???????????//任務(wù)控制塊
{
??unsigned?int?OSTaskStackTop;??//保存任務(wù)的堆棧頂
??unsigned?int?OSWaitTick;??????//任務(wù)延時(shí)時(shí)鐘
}?TCB[OS_TASKS+1];
//防止被編譯器占用
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?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?unsigned?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)Task>>8;????//將任務(wù)的地址高位壓入堆棧,
??*Stack--=(unsigned?int)Task;?????????//將任務(wù)的地址低位壓入堆棧,
????
??*Stack--=0x00;?????????????????????//R1?__zero_reg__????????????
??*Stack--=0x00;?????????????????????//R0?__tmp_reg__
??*Stack--=0x80;????????????????????????????????????????//SREG?在任務(wù)中,開啟全局中斷????????
??for(i=0;i<14;i++)????//在?avr-libc?中的?FAQ中的?What?registers?are?used?by?the?C?compiler?
????*Stack--=i;????????????????????//描述了寄存器的作用????
????TCB[TaskID].OSTaskStackTop=(unsigned?int)Stack;????//將人工堆棧的棧頂,保存到堆棧的數(shù)組中
????OSRdyTbl|=0x01<
//開始任務(wù)調(diào)度,從最低優(yōu)先級(jí)的任務(wù)的開始
void?OSStartTask()????????
{
??OSTaskRunningPrio=OS_TASKS;
??SP=TCB[OS_TASKS].OSTaskStackTop+17;
??__asm__?__volatile__(????"reti"???????"nt"??);?
}
//進(jìn)行任務(wù)調(diào)度
void?OSSched(void)
{?
???//??根據(jù)中斷時(shí)保存寄存器的次序入棧,模擬一次中斷后,入棧的情況??
??__asm__?__volatile__("PUSH?__zero_reg__?????????nt");??//R1
??__asm__?__volatile__("PUSH?__tmp_reg__??????????nt");??//R0?
??__asm__?__volatile__("IN???__tmp_reg__,__SREG__?nt");??//保存狀態(tài)寄存器SREG
??__asm__?__volatile__("PUSH?__tmp_reg__??????????nt");
??__asm__?__volatile__("CLR??__zero_reg__?????????nt");??//R0重新清零
??__asm__?__volatile__("PUSH?R18??????????????????nt");
??__asm__?__volatile__("PUSH?R19??????????????????nt");
??__asm__?__volatile__("PUSH?R20??????????????????nt");
??__asm__?__volatile__("PUSH?R21??????????????????nt");
??__asm__?__volatile__("PUSH?R22??????????????????nt");
??__asm__?__volatile__("PUSH?R23??????????????????nt");
??__asm__?__volatile__("PUSH?R24??????????????????nt");
??__asm__?__volatile__("PUSH?R25??????????????????nt");
??__asm__?__volatile__("PUSH?R26??????????????????nt");
??__asm__?__volatile__("PUSH?R27??????????????????nt");
??__asm__?__volatile__("PUSH?R30??????????????????nt");????
??__asm__?__volatile__("PUSH?R31??????????????????nt");
??__asm__?__volatile__("PUSH?R28??????????????????nt");??//R28與R29用于建立在堆棧上的指針
??__asm__?__volatile__("PUSH?R29??????????????????nt");??//入棧完成
????
??TCB[OSTaskRunningPrio].OSTaskStackTop=SP;???????????//將正在運(yùn)行的任務(wù)的堆棧底保存
????
??
??unsigned?char?OSNextTaskID;?????????????????????????????//在現(xiàn)有堆棧上開設(shè)新的空間?
??for?(OSNextTaskID?=?0;??????????????????????????????????//進(jìn)行任務(wù)調(diào)度
????OSNextTaskID?????OSNextTaskID++);
????OSTaskRunningPrio?=?OSNextTaskID?;
??cli();??//保護(hù)堆棧轉(zhuǎn)換
??SP=TCB[OSTaskRunningPrio].OSTaskStackTop;
??sei();
????
????//根據(jù)中斷時(shí)的出棧次序????
??__asm__?__volatile__("POP??R29??????????????????nt");????
??__asm__?__volatile__("POP??R28??????????????????nt");????????
??__asm__?__volatile__("POP??R31??????????????????nt");????
??__asm__?__volatile__("POP??R30??????????????????nt");????
??__asm__?__volatile__("POP??R27??????????????????nt");????
??__asm__?__volatile__("POP??R26??????????????????nt");????
??__asm__?__volatile__("POP??R25??????????????????nt");????
??__asm__?__volatile__("POP??R24??????????????????nt");????
??__asm__?__volatile__("POP??R23??????????????????nt");????
??__asm__?__volatile__("POP??R22??????????????????nt");????
??__asm__?__volatile__("POP??R21??????????????????nt");????
??__asm__?__volatile__("POP??R20??????????????????nt");????
??__asm__?__volatile__("POP??R19??????????????????nt");
??__asm__?__volatile__("POP??R18??????????????????nt");
??__asm__?__volatile__("POP??__tmp_reg__??????????nt");??????//SERG?出棧并恢復(fù)
??__asm__?__volatile__("OUT??__SREG__,__tmp_reg__?nt");??????//
??__asm__?__volatile__("POP??__tmp_reg__??????????nt");??????//R0?出棧
??__asm__?__volatile__("POP??__zero_reg__?????????nt");??????//R1?出棧
??//中斷時(shí)出棧完成
}
void?OSTimeDly(unsigned?int?ticks)
{
??if(ticks)?????????????????????????????//當(dāng)延時(shí)有效
??{
????OSRdyTbl?&=?~(0x01<
????OSSched();??????????????????????????//從新調(diào)度
??}
}
void?TCN0Init(void)????//?計(jì)時(shí)器0
{
??TCCR0?=?0;
??TCCR0?|=?(1<
????
}
SIGNAL(SIG_OVERFLOW0)
{
??unsigned?char?i;
??for(i=0;i
????if(TCB[i].OSWaitTick)?
????{
??????TCB[i].OSWaitTick--;
??????if(TCB[i].OSWaitTick==0)?????//當(dāng)任務(wù)時(shí)鐘到時(shí),必須是由定時(shí)器減時(shí)的才行
??????{??
????????OSRdyTbl?|=?(0x01<??????}
????}
??}
??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()
{?
??while(1)
??{????????
?????OSSched();??????//反復(fù)進(jìn)行調(diào)度
??}
}
int?main(void)
{????
??TCN0Init();
??OSRdyTbl=0;
??OSTaskRunningPrio=0;
??OSTaskCreate(Task0,&Stack[49],0);
??OSTaskCreate(Task1,&Stack[99],1);
??OSTaskCreate(Task2,&Stack[149],2);
??OSTaskCreate(TaskScheduler,&Stack[199],OS_TASKS);
??OSStartTask();
}
???在上面的例子中,一切變得很簡(jiǎn)單,三個(gè)正在運(yùn)行的主任務(wù),都通過延時(shí)服務(wù),主動(dòng)放棄對(duì)CPU的控制權(quán)。
???在時(shí)間中斷中,對(duì)各個(gè)任務(wù)的的延時(shí)進(jìn)行計(jì)時(shí),如果某個(gè)任務(wù)的延時(shí)結(jié)束,將任務(wù)重新在就緒表中置位。
???最低級(jí)的系統(tǒng)任務(wù)TaskScheduler(),在三個(gè)主任務(wù)在放棄對(duì)CPU的控制權(quán)后開始不斷地進(jìn)行調(diào)度。如果某個(gè)任務(wù)在就緒表中置位,通過調(diào)度,進(jìn)入最高級(jí)別的任務(wù)中繼續(xù)運(yùn)行。
第五篇:?完善的協(xié)作式的內(nèi)核??
??現(xiàn)在為上面的協(xié)作式內(nèi)核添加一些OS中所必須的服務(wù):
???1??掛起和重新運(yùn)行任務(wù)
???2??信號(hào)量(在必要時(shí)候,可以擴(kuò)展成郵箱和信息隊(duì)列)
???3??延時(shí)
???
#include?
#include?
#include?
unsigned?char?Stack[400];
register?unsigned?char?OSRdyTbl??????????asm("r2");????//任務(wù)運(yùn)行就緒表
register?unsigned?char?OSTaskRunningPrio?asm("r3");????//正在運(yùn)行的任務(wù)
#define?OS_TASKS?3????????????????????//設(shè)定運(yùn)行任務(wù)的數(shù)量
struct?TaskCtrBlock
{
??unsigned?int?OSTaskStackTop;??//保存任務(wù)的堆棧頂
??unsigned?int?OSWaitTick;??????//任務(wù)延時(shí)時(shí)鐘
}?TCB[OS_TASKS+1];
//防止被編譯器占用
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?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?unsigned?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)Task>>8;????//將任務(wù)的地址高位壓入堆棧,
??*Stack--=(unsigned?int)Task;?????????//將任務(wù)的地址低位壓入堆棧,
????
??*Stack--=0x00;?????????????????????//R1?__zero_reg__????????????
??*Stack--=0x00;?????????????????????//R0?__tmp_reg__
??*Stack--=0x80;????????????????????????????????????????
//SREG?在任務(wù)中,開啟全局中斷????????
??for(i=0;i<14;i++)????//在?avr-libc?中的?FAQ中的?What?registers?are?used?by?the?C?compiler?
????*Stack--=i;????????????????????//描述了寄存器的作用????
??TCB[TaskID].OSTaskStackTop=(unsigned?int)Stack;????//將人工堆棧的棧頂,保存到堆棧的數(shù)組中
??OSRdyTbl|=0x01<
//開始任務(wù)調(diào)度,從最低優(yōu)先級(jí)的任務(wù)的開始
void?OSStartTask()????????
{
??OSTaskRunningPrio=OS_TASKS;
??SP=TCB[OS_TASKS].OSTaskStackTop+17;
??__asm__?__volatile__(????"reti"???????"nt"??);?
}
//進(jìn)行任務(wù)調(diào)度
void?OSSched(void)
{?
???//??根據(jù)中斷時(shí)保存寄存器的次序入棧,模擬一次中斷后,入棧的情況??
??__asm__?__volatile__("PUSH?__zero_reg__?????????nt");??//R1
??__asm__?__volatile__("PUSH?__tmp_reg__??????????nt");??//R0?
??__asm__?__volatile__("IN???__tmp_reg__,__SREG__?nt");??//保存狀態(tài)寄存器SREG
??__asm__?__volatile__("PUSH?__tmp_reg__??????????nt");
??__asm__?__volatile__("CLR??__zero_reg__?????????nt");??//R0重新清零
??__asm__?__volatile__("PUSH?R18??????????????????nt");
??__asm__?__volatile__("PUSH?R19??????????????????nt");
??__asm__?__volatile__("PUSH?R20??????????????????nt");
??__asm__?__volatile__("PUSH?R21??????????????????nt");
??__asm__?__volatile__("PUSH?R22??????????????????nt");
??__asm__?__volatile__("PUSH?R23??????????????????nt");
??__asm__?__volatile__("PUSH?R24??????????????????nt");
??__asm__?__volatile__("PUSH?R25??????????????????nt");
??__asm__?__volatile__("PUSH?R26??????????????????nt");
??__asm__?__volatile__("PUSH?R27??????????????????nt");
??__asm__?__volatile__("PUSH?R30??????????????????nt");????
??__asm__?__volatile__("PUSH?R31??????????????????nt");
??__asm__?__volatile__("PUSH?R28??????????????????nt");??//R28與R29用于建立在堆棧上的指針
??__asm__?__volatile__("PUSH?R29??????????????????nt");??//入棧完成
????
??TCB[OSTaskRunningPrio].OSTaskStackTop=SP;???????????//將正在運(yùn)行的任務(wù)的堆棧底保存
??unsigned?char?OSNextTaskID;?????????????????????????????//在現(xiàn)有堆棧上開設(shè)新的空間?
??for?(OSNextTaskID?=?0;??????????????????????????????????//進(jìn)行任務(wù)調(diào)度
????OSNextTaskID?????OSNextTaskID++);
????OSTaskRunningPrio?=?OSNextTaskID?;
??cli();??//保護(hù)堆棧轉(zhuǎn)換
??SP=TCB[OSTaskRunningPrio].OSTaskStackTop;
??sei();
????
????//根據(jù)中斷時(shí)的出棧次序????
??__asm__?__volatile__("POP??R29??????????????????nt");????
??__asm__?__volatile__("POP??R28??????????????????nt");????????
??__asm__?__volatile__("POP??R31??????????????????nt");????
??__asm__?__volatile__("POP??R30??????????????????nt");????
??__asm__?__volatile__("POP??R27??????????????????nt");????
??__asm__?__volatile__("POP??R26??????????????????nt");????
??__asm__?__volatile__("POP??R25??????????????????nt");????
??__asm__?__volatile__("POP??R24??????????????????nt");????
??__asm__?__volatile__("POP??R23??????????????????nt");????
??__asm__?__volatile__("POP??R22??????????????????nt");????
??__asm__?__volatile__("POP??R21??????????????????nt");????
??__asm__?__volatile__("POP??R20??????????????????nt");????
??__asm__?__volatile__("POP??R19??????????????????nt");
??__asm__?__volatile__("POP??R18??????????????????nt");
??__asm__?__volatile__("POP??__tmp_reg__??????????nt");??????//SERG?出棧并恢復(fù)
??__asm__?__volatile__("OUT??__SREG__,__tmp_reg__?nt");??????//
??__asm__?__volatile__("POP??__tmp_reg__??????????nt");??????//R0?出棧
??__asm__?__volatile__("POP??__zero_reg__?????????nt");??????//R1?出棧
??//中斷時(shí)出棧完成
}
////////////////////////////////////////////任務(wù)處理
//掛起任務(wù)
void?OSTaskSuspend(unsigned?char?prio)?
{
??TCB[prio].OSWaitTick=0;
??OSRdyTbl?&=?~(0x01<
????OSSched();???????????????//從新調(diào)度
}
//恢復(fù)任務(wù)?可以讓被OSTaskSuspend或?OSTimeDly暫停的任務(wù)恢復(fù)
void?OSTaskResume(unsigned?char?prio)
{
??OSRdyTbl?|=?0x01<
??if(OSTaskRunningPrio>prio)???//當(dāng)要當(dāng)前任務(wù)的優(yōu)先級(jí)低于重置位的任務(wù)的優(yōu)先級(jí)
????OSSched();???????????????//從新調(diào)度??????????????//從新調(diào)度
}
//?任務(wù)延時(shí)
void?OSTimeDly(unsigned?int?ticks)
{
??if(ticks)?????????????????????????????//當(dāng)延時(shí)有效
??{
????OSRdyTbl?&=?~(0x01<
????OSSched();??????????????????????????//從新調(diào)度
??}
}
//信號(hào)量
struct?SemBlk
{
??unsigned?char?OSEventType;?????//型號(hào)?0,信號(hào)量獨(dú)占型;1信號(hào)量共享型?
??unsigned?char?OSEventState;????//狀態(tài)?0,不可用;1,可用
??unsigned?char?OSTaskPendTbl;???//等待信號(hào)量的任務(wù)列表
}?Sem[10];
//初始化信號(hào)量
void?OSSemCreat(unsigned?char?Index,unsigned?char?Type)
{
??Sem[Index].OSEventType=Type;??//型號(hào)?0,信號(hào)量獨(dú)占型;1信號(hào)量共享型?
??Sem[Index].OSTaskPendTbl=0;
??Sem[Index].OSEventState=0;
}
//任務(wù)等待信號(hào)量,掛起
unsigned?char?OSTaskSemPend(unsigned?char?Index,unsigned?int?Timeout)
{
??//unsigned?char?i=0;
??if(Sem[Index].OSEventState)???????????????//信號(hào)量有效
??{?
????if(Sem[Index].OSEventType==0)??????????//如果為獨(dú)占型
????Sem[Index].OSEventState?=?0x00;???????//信號(hào)量被獨(dú)占,不可用
??}
??else
??{?????????????????????????????????????????//加入信號(hào)的任務(wù)等待表
????Sem[Index].OSTaskPendTbl?|=?0x01<
????OSSched();???//從新調(diào)度
????if(TCB[OSTaskRunningPrio].OSWaitTick==0)?return?0;????
??}
??return?1;
}
//發(fā)送一個(gè)信號(hào)量,可以從任務(wù)或中斷發(fā)送
void?OSSemPost(unsigned?char?Index)
{
if(Sem[Index].OSEventType)????????????????//當(dāng)要求的信號(hào)量是共享型
??{
????Sem[Index].OSEventState=0x01;???????????//使信號(hào)量有效
????OSRdyTbl?|=Sem?[Index].OSTaskPendTbl;???//使在等待該信號(hào)的所有任務(wù)就緒
????Sem[Index].OSTaskPendTbl=0;?????????????//清空所有等待該信號(hào)的等待任務(wù)
??}??
??else???????????????????????????????????????//當(dāng)要求的信號(hào)量為獨(dú)占型
??{??????
????unsigned?char?i;
????for?(i?=?0;?i?????if(i?????{
??????Sem[Index].OSTaskPendTbl?&=?~(0x01<??????OSRdyTbl?|=?0x01<????}
????else
????{
??????Sem[Index].OSEventState?=1;????????//使信號(hào)量有效
????}
??}
}
//從任務(wù)發(fā)送一個(gè)信號(hào)量,并進(jìn)行調(diào)度
void?OSTaskSemPost(unsigned?char?Index)?
{
??OSSemPost(Index);
??OSSched();???
}
//清除一個(gè)信號(hào)量,只對(duì)共享型的有用。
//對(duì)于獨(dú)占型的信號(hào)量,在任務(wù)占用后,就交得不可以用了。?
void?OSSemClean(unsigned?char?Index)
{
??Sem[Index].OSEventState?=0;??????????//要求的信號(hào)量無效
}
void?TCN0Init(void)????//?計(jì)時(shí)器0
{
??TCCR0?=?0;
??TCCR0?|=?(1<
????
}
SIGNAL(SIG_OVERFLOW0)
{
??unsigned?char?i;
??for(i=0;i
????if(TCB[i].OSWaitTick)?
????{
??????TCB[i].OSWaitTick--;
??????if(TCB[i].OSWaitTick==0)?????//當(dāng)任務(wù)時(shí)鐘到時(shí),必須是由定時(shí)器減時(shí)的才行
??????{??
????????OSRdyTbl?|=?(0x01<??????}
????}
??}
??TCNT0=100;
}
void?Task0()
{
??unsigned?int?j=0;
??while(1)
??{????????????
????PORTB=j++;
????OSTaskSuspend(1);????//掛起任務(wù)1?
????OSTaskSemPost(0);
????OSTimeDly(50);
????OSTaskResume(1);?????//恢復(fù)任務(wù)1
????OSSemClean(0);
????OSTimeDly(50);
??}
}
void?Task1()
{
??unsigned?int?j=0;
??while(1)
??{
????PORTC=j++;
????OSTimeDly(5);
??}
}
void?Task2()
{
??unsigned?int?j=0;
??while(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,&Stack[99],0);
??OSTaskCreate(Task1,&Stack[199],1);
??OSTaskCreate(Task2,&Stack[299],2);
??OSTaskCreate(TaskScheduler,&Stack[399],OS_TASKS);
??OSStartTask();
}
第六篇:時(shí)間片輪番調(diào)度法的內(nèi)核
???Round-Robin?Sheduling
????時(shí)間片輪調(diào)法是非常有趣的。本篇中的例子,建立了3個(gè)任務(wù),任務(wù)沒有優(yōu)先級(jí),在時(shí)間中斷的調(diào)度下,每個(gè)任務(wù)都輪流運(yùn)行相同的時(shí)間。如果在內(nèi)核中沒有加入其它服務(wù),感覺上就好像是有三個(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)樵谶M(jìn)入中斷時(shí),已經(jīng)將一系列的寄存器入棧。
????2,在中斷內(nèi)進(jìn)行調(diào)度,是直接通過"RJMP?Int_OSSched"進(jìn)入任務(wù)切換和調(diào)度的,這是GCC?AVR的一個(gè)特點(diǎn),為用C編寫內(nèi)核提供了極大的方便。
????3,在閱讀代碼的同時(shí),請(qǐng)對(duì)照閱讀編譯器產(chǎn)生的?*.lst文件,會(huì)對(duì)你理解例子有很大的幫助。
???
#include?
#include?
#include?
unsigned?char?Stack[400];
register?unsigned?char?OSRdyTbl??????????asm("r2");????//任務(wù)運(yùn)行就緒表
register?unsigned?char?OSTaskRunningPrio?asm("r3");????//正在運(yùn)行的任務(wù)
#define?OS_TASKS?3????????????????????//設(shè)定運(yùn)行任務(wù)的數(shù)量
struct?TaskCtrBlock
{
??unsigned?int?OSTaskStackTop;??//保存任務(wù)的堆棧頂
??unsigned?int?OSWaitTick;??????//任務(wù)延時(shí)時(shí)鐘
}?TCB[OS_TASKS+1];
//防止被編譯器占用
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?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?unsigned?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)Task>>8;????//將任務(wù)的地址高位壓入堆棧,
??*Stack--=(unsigned?int)Task;?????????//將任務(wù)的地址低位壓入堆棧,
????
??*Stack--=0x00;?????????????????????//R1?__zero_reg__????????????
??*Stack--=0x00;?????????????????????//R0?__tmp_reg__
??*Stack--=0x80;????????????????????????????????????????
//SREG?在任務(wù)中,開啟全局中斷????????
??for(i=0;i<14;i++)????//在?avr-libc?中的?FAQ中的?What?registers?are?used?by?the?C?compiler?
????*Stack--=i;????????????????????//描述了寄存器的作用????
??TCB[TaskID].OSTaskStackTop=(unsigned?int)Stack;????//將人工堆棧的棧頂,保存到堆棧的數(shù)組中
??OSRdyTbl|=0x01<
//開始任務(wù)調(diào)度,從最低優(yōu)先級(jí)的任務(wù)的開始
void?OSStartTask()????????
{
??OSTaskRunningPrio=OS_TASKS;
??SP=TCB[OS_TASKS].OSTaskStackTop+17;
??__asm__?__volatile__(????"reti"???????"nt"??);?
}
//進(jìn)行任務(wù)調(diào)度
void?OSSched(void)
{?
???//??根據(jù)中斷時(shí)保存寄存器的次序入棧,模擬一次中斷后,入棧的情況??
??__asm__?__volatile__("PUSH?__zero_reg__?????????nt");??//R1
??__asm__?__volatile__("PUSH?__tmp_reg__??????????nt");??//R0?
??__asm__?__volatile__("IN???__tmp_reg__,__SREG__?nt");??//保存狀態(tài)寄存器SREG
??__asm__?__volatile__("PUSH?__tmp_reg__??????????nt");
??__asm__?__volatile__("CLR??__zero_reg__?????????nt");??//R0重新清零
??__asm__?__volatile__("PUSH?R18??????????????????nt");
??__asm__?__volatile__("PUSH?R19??????????????????nt");
??__asm__?__volatile__("PUSH?R20??????????????????nt");
??__asm__?__volatile__("PUSH?R21??????????????????nt");
??__asm__?__volatile__("PUSH?R22??????????????????nt");
??__asm__?__volatile__("PUSH?R23??????????????????nt");
??__asm__?__volatile__("PUSH?R24??????????????????nt");
??__asm__?__volatile__("PUSH?R25??????????????????nt");
??__asm__?__volatile__("PUSH?R26??????????????????nt");
??__asm__?__volatile__("PUSH?R27??????????????????nt");
??__asm__?__volatile__("PUSH?R30??????????????????nt");????
??__asm__?__volatile__("PUSH?R31??????????????????nt");
????
??__asm__?__volatile__("Int_OSSched:??????????????nt");??//當(dāng)中斷要求調(diào)度,直接進(jìn)入這里
??__asm__?__volatile__("PUSH?R28??????????????????nt");??//R28與R29用于建立在堆棧上的指針
??__asm__?__volatile__("PUSH?R29??????????????????nt");??//入棧完成
????
??TCB[OSTaskRunningPrio].OSTaskStackTop=SP;???????????//將正在運(yùn)行的任務(wù)的堆棧底保存
??if(++OSTaskRunningPrio>=OS_TASKS)?//輪流運(yùn)行各個(gè)任務(wù),沒有優(yōu)先級(jí)
??????OSTaskRunningPrio=0;
??//cli();??//保護(hù)堆棧轉(zhuǎn)換
??SP=TCB[OSTaskRunningPrio].OSTaskStackTop;
??//sei();
????
????//根據(jù)中斷時(shí)的出棧次序????
??__asm__?__volatile__("POP??R29??????????????????nt");????
??__asm__?__volatile__("POP??R28??????????????????nt");????????
??__asm__?__volatile__("POP??R31??????????????????nt");????
??__asm__?__volatile__("POP??R30??????????????????nt");????
??__asm__?__volatile__("POP??R27??????????????????nt");????
??__asm__?__volatile__("POP??R26??????????????????nt");????
??__asm__?__volatile__("POP??R25??????????????????nt");????
??__asm__?__volatile__("POP??R24??????????????????nt");????
??__asm__?__volatile__("POP??R23??????????????????nt");????
??__asm__?__volatile__("POP??R22??????????????????nt");????
??__asm__?__volatile__("POP??R21??????????????????nt");????
??__asm__?__volatile__("POP??R20??????????????????nt");????
??__asm__?__volatile__("POP??R19??????????????????nt");
??__asm__?__volatile__("POP??R18??????????????????nt");
??__asm__?__volatile__("POP??__tmp_reg__??????????nt");??????//SERG?出棧并恢復(fù)
??__asm__?__volatile__("OUT??__SREG__,__tmp_reg__?nt");??????//
??__asm__?__volatile__("POP??__tmp_reg__??????????nt");??????//R0?出棧
??__asm__?__volatile__("POP??__zero_reg__?????????nt");??????//R1?出棧
??__asm__?__volatile__("RETI??????????????????????nt");?????//返回并開中斷
??//中斷時(shí)出棧完成
}
void?IntSwitch(void)
{????
??__asm__?__volatile__("POP??R31??????????????????nt");??//去除因調(diào)用子程序而入棧的PC
??__asm__?__volatile__("POP??R31??????????????????nt");
??__asm__?__volatile__("RJMP?Int_OSSched??????????nt");??//重新調(diào)度
}
void?TCN0Init(void)????//?計(jì)時(shí)器0
{
??TCCR0?=?0;
??TCCR0?|=?(1<
}
SIGNAL(SIG_OVERFLOW0)
{
??TCNT0=100;
??IntSwitch();????????//任務(wù)調(diào)度
}
void?Task0()
{
??unsigned?int?j=0;
??while(1)
??{????????????
????PORTB=j++;
????//OSTimeDly(50);
??}
}
void?Task1()
{
??unsigned?int?j=0;
??while(1)
??{
????PORTC=j++;
????//OSTimeDly(5);
??}
}
void?Task2()
{
??unsigned?int?j=0;
??while(1)
??{
????PORTD=j++;?
????//OSTimeDly(5);??
??}
}
void?TaskScheduler()
{?
??while(1)
??{????????
?????OSSched();??????//反復(fù)進(jìn)行調(diào)度
??}
}
int?main(void)
{????
??TCN0Init();
??OSRdyTbl=0;
??OSTaskCreate(Task0,&Stack[99],0);
??OSTaskCreate(Task1,&Stack[199],1);
??OSTaskCreate(Task2,&Stack[299],2);
??OSTaskCreate(TaskScheduler,&Stack[399],OS_TASKS);
??OSStartTask();
}
?第七篇:占先式內(nèi)核(只帶延時(shí)服務(wù))
Preemptive?Multitasking
????當(dāng)大家理解時(shí)間片輪番調(diào)度法的任務(wù)調(diào)度方式后,占先式的內(nèi)核的原理,已經(jīng)伸手可及了。
????先想想,占先式內(nèi)核是在什么地方實(shí)現(xiàn)任務(wù)調(diào)度的呢?對(duì)了,它在可以在任務(wù)中進(jìn)行調(diào)度,這個(gè)在協(xié)作式的內(nèi)核中已經(jīng)做到了;同時(shí),它也可以在中斷結(jié)束后進(jìn)行調(diào)度,這個(gè)問題,已經(jīng)在時(shí)間片輪番調(diào)度法中已經(jīng)做到了。
????
????由于中斷是可以嵌套的,只有當(dāng)各層嵌套中要求調(diào)度,并且中斷嵌套返回到最初進(jìn)入的中斷的那一層時(shí),才能進(jìn)行任務(wù)調(diào)度。
??
#include?
#include?
#include?
unsigned?char?Stack[400];
register?unsigned?char?OSRdyTbl??????????asm("r2");????//任務(wù)運(yùn)行就緒表
register?unsigned?char?OSTaskRunningPrio?asm("r3");????//正在運(yùn)行的任務(wù)
register?unsigned?char?IntNum????????????asm("r4");??//中斷嵌套計(jì)數(shù)器
//只有當(dāng)中斷嵌套數(shù)為0,并且有中斷要求時(shí),才能在退出中斷時(shí),進(jìn)行任務(wù)調(diào)度
register?unsigned?char?OSCoreState???????asm("r16");?//?系統(tǒng)核心標(biāo)志位?,R16?編譯器沒有使用
//只有大于R15的寄存器才能直接賦值?例LDI?R16,0x01
//0x01?正在任務(wù)?切換??0x02?有中斷要求切換
#define?OS_TASKS?3????????????????????//設(shè)定運(yùn)行任務(wù)的數(shù)量
struct?TaskCtrBlock
{
??unsigned?int?OSTaskStackTop;??//保存任務(wù)的堆棧頂
??unsigned?int?OSWaitTick;??????//任務(wù)延時(shí)時(shí)鐘
}?TCB[OS_TASKS+1];
//防止被編譯器占用
//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?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?unsigned?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)Task>>8;????//將任務(wù)的地址高位壓入堆棧,
??*Stack--=(unsigned?int)Task;?????????//將任務(wù)的地址低位壓入堆棧,
????
??*Stack--=0x00;?????????????????????//R1?__zero_reg__????????????
??*Stack--=0x00;?????????????????????//R0?__tmp_reg__
??*Stack--=0x80;????????????????????????????????????????
//SREG?在任務(wù)中,開啟全局中斷????????
??for(i=0;i<14;i++)????//在?avr-libc?中的?FAQ中的?What?registers?are?used?by?the?C?compiler?
????*Stack--=i;????????????????????//描述了寄存器的作用????
??TCB[TaskID].OSTaskStackTop=(unsigned?int)Stack;????//將人工堆棧的棧頂,保存到堆棧的數(shù)組中
??OSRdyTbl|=0x01<
//開始任務(wù)調(diào)度,從最低優(yōu)先級(jí)的任務(wù)的開始
void?OSStartTask()????????
{
??OSTaskRunningPrio=OS_TASKS;
??SP=TCB[OS_TASKS].OSTaskStackTop+17;
??__asm__?__volatile__(????"reti"???????"nt"??);?
}
//進(jìn)行任務(wù)調(diào)度
void?OSSched(void)
{?
??__asm__?__volatile__("LDI??R16,0x01?????????????nt");??
??//清除中斷要求任務(wù)切換的標(biāo)志位,設(shè)置正在任務(wù)切換標(biāo)志位
??__asm__?__volatile__("SEI???????????????????????nt");??????
??//開中斷,因?yàn)槿绻蛑袛嘣谌蝿?wù)調(diào)度中進(jìn)行,要重新進(jìn)行調(diào)度時(shí),已經(jīng)關(guān)中斷
??//根據(jù)中斷時(shí)保存寄存器的次序入棧,模擬一次中斷后,入棧的情況??
??__asm__?__volatile__("PUSH?__zero_reg__?????????nt");??//R1
??__asm__?__volatile__("PUSH?__tmp_reg__??????????nt");??//R0?
??__asm__?__volatile__("IN???__tmp_reg__,__SREG__?nt");??//保存狀態(tài)寄存器SREG
??__asm__?__volatile__("PUSH?__tmp_reg__??????????nt");
??__asm__?__volatile__("CLR??__zero_reg__?????????nt");??//R0重新清零
??__asm__?__volatile__("PUSH?R18??????????????????nt");
??__asm__?__volatile__("PUSH?R19??????????????????nt");
??__asm__?__volatile__("PUSH?R20??????????????????nt");
??__asm__?__volatile__("PUSH?R21??????????????????nt");
??__asm__?__volatile__("PUSH?R22??????????????????nt");
??__asm__?__volatile__("PUSH?R23??????????????????nt");
??__asm__?__volatile__("PUSH?R24??????????????????nt");
??__asm__?__volatile__("PUSH?R25??????????????????nt");
??__asm__?__volatile__("PUSH?R26??????????????????nt");
??__asm__?__volatile__("PUSH?R27??????????????????nt");
??__asm__?__volatile__("PUSH?R30??????????????????nt");????
??__asm__?__volatile__("PUSH?R31??????????????????nt");
????
??__asm__?__volatile__("Int_OSSched:??????????????nt");??//當(dāng)中斷要求調(diào)度,直接進(jìn)入這里
??__asm__?__volatile__("SEI???????????????????????nt");?
//開中斷,因?yàn)槿绻蛑袛嘣谌蝿?wù)調(diào)度中進(jìn)行,已經(jīng)關(guān)中斷?
??__asm__?__volatile__("PUSH?R28??????????????????nt");??//R28與R29用于建立在堆棧上的指針
??__asm__?__volatile__("PUSH?R29??????????????????nt");??//入棧完成
????
??TCB[OSTaskRunningPrio].OSTaskStackTop=SP;???????????//將正在運(yùn)行的任務(wù)的堆棧底保存
??unsigned?char?OSNextTaskPrio;????????????????????????????//在現(xiàn)有堆棧上開設(shè)新的空間?
??for?(OSNextTaskPrio?=?0;?????????????????????????????????//進(jìn)行任務(wù)調(diào)度
????OSNextTaskPrio?????OSNextTaskPrio++);
????OSTaskRunningPrio?=?OSNextTaskPrio?;
??cli();??//保護(hù)堆棧轉(zhuǎn)換
??SP=TCB[OSTaskRunningPrio].OSTaskStackTop;
??sei();
????
??//根據(jù)中斷時(shí)的出棧次序????
??__asm__?__volatile__("POP??R29??????????????????nt");????
??__asm__?__volatile__("POP??R28??????????????????nt");????????
??__asm__?__volatile__("POP??R31??????????????????nt");????
??__asm__?__volatile__("POP??R30??????????????????nt");????
??__asm__?__volatile__("POP??R27??????????????????nt");????
??__asm__?__volatile__("POP??R26??????????????????nt");????
??__asm__?__volatile__("POP??R25??????????????????nt");????
??__asm__?__volatile__("POP??R24??????????????????nt");????
??__asm__?__volatile__("POP??R23??????????????????nt");????
??__asm__?__volatile__("POP??R22??????????????????nt");????
??__asm__?__volatile__("POP??R21??????????????????nt");????
??__asm__?__volatile__("POP??R20??????????????????nt");????
??__asm__?__volatile__("POP??R19??????????????????nt");
??__asm__?__volatile__("POP??R18??????????????????nt");
??__asm__?__volatile__("POP??__tmp_reg__??????????nt");??????//SERG?出棧并恢復(fù)
??__asm__?__volatile__("OUT??__SREG__,__tmp_reg__?nt");??????//
??__asm__?__volatile__("POP??__tmp_reg__??????????nt");??????//R0?出棧
??__asm__?__volatile__("POP??__zero_reg__?????????nt");??????//R1?出棧
??//中斷時(shí)出棧完成
??__asm__?__volatile__("CLI???????????????????????nt");??//關(guān)中斷????
??__asm__?__volatile__("SBRC?R16,1????????????????nt");??//SBRC當(dāng)寄存器位為0剛跳過下一條指令
??//檢查是在調(diào)度時(shí),是否有中斷要求任務(wù)調(diào)度?0x02是中斷要求調(diào)度的標(biāo)志位
??__asm__?__volatile__("RJMP?OSSched??????????????nt");??//重新調(diào)度
??__asm__?__volatile__("LDI??R16,0x00?????????????nt");??
??//清除中斷要求任務(wù)切換的標(biāo)志位,清除正在任務(wù)切換標(biāo)志位
??__asm__?__volatile__("RETI??????????????????????nt");?????//返回并開中斷
}
//從中斷退出并進(jìn)行調(diào)度
void?IntSwitch(void)
{????
??//當(dāng)中斷無嵌套,并且沒有在切換任務(wù)的過程中,直接進(jìn)行任務(wù)切換
??if(OSCoreState?==?0x02?&&?IntNum==0)?
??{
????//進(jìn)入中斷時(shí),已經(jīng)保存了SREG和R0,R1,R18~R27,R30,R31
????__asm__?__volatile__("POP??R31??????????????????nt");??//去除因調(diào)用子程序而入棧的PC
????__asm__?__volatile__("POP??R31??????????????????nt");
????__asm__?__volatile__("LDI??R16,0x01?????????????nt");??
????//清除中斷要求任務(wù)切換的標(biāo)志位,設(shè)置正在任務(wù)切換標(biāo)志位
????__asm__?__volatile__("RJMP?Int_OSSched??????????nt");??//重新調(diào)度
??}
}
//?任務(wù)延時(shí)
void?OSTimeDly(unsigned?int?ticks)
{
??if(ticks)?????????????????????????????//當(dāng)延時(shí)有效
??{
????OSRdyTbl?&=?~(0x01<
????OSSched();??????????????????????????//從新調(diào)度
??}
}
void?TCN0Init(void)????//?計(jì)時(shí)器0
{
??TCCR0?=?0;
??TCCR0?|=?(1<
????
}
SIGNAL(SIG_OVERFLOW0)
{
??IntNum++;?????//中斷嵌套+1
??sei();??//在中斷中,重開中斷
????
??unsigned?char?i,j=0;
??for(i=0;i
????if(TCB[i].OSWaitTick)?
????{
??????TCB[i].OSWaitTick--;
??????if(TCB[i].OSWaitTick==0)?????????//當(dāng)任務(wù)時(shí)鐘到時(shí),必須是由定時(shí)器減時(shí)的才行
??????{??
????????OSRdyTbl?|=?(0x01<????????OSCoreState|=0x02;??????????????//要求任務(wù)切換的標(biāo)志位
??????}
????}
??}
??TCNT0=100;
??cli();
??IntNum--;???????????????//中斷嵌套-1
??IntSwitch();?????????//進(jìn)行任務(wù)調(diào)度
}
void?Task0()
{
??unsigned?int?j=0;
??while(1)
??{????????????
????PORTB=j++;
????OSTimeDly(50);
??}
}
void?Task1()
{
??unsigned?int?j=0;
??while(1)
??{
????PORTC=j++;
????OSTimeDly(20);
??}
}
void?Task2()
{
??unsigned?int?j=0;
??while(1)
??{
????PORTD=j++;?
????OSTimeDly(5);??
??}
}
void?TaskScheduler()
{?
??OSSched();?
??while(1)
??{????????
?????//OSSched();??????//反復(fù)進(jìn)行調(diào)度
??}
}
int?main(void)
{????
??TCN0Init();
??OSRdyTbl=0;
??IntNum=0;
??OSTaskCreate(Task0,&Stack[99],0);
??OSTaskCreate(Task1,&Stack[199],1);
??OSTaskCreate(Task2,&Stack[299],2);
??OSTaskCreate(TaskScheduler,&Stack[399],OS_TASKS);
??OSStartTask();
}
第八篇:占先式內(nèi)核(完善的服務(wù))
如果將前面所提到的占先式內(nèi)核和協(xié)作式內(nèi)核組合在一起,很容易就可以得到一個(gè)功能較為完善的占先式內(nèi)核,它的功能有:
????1,掛起和恢復(fù)任務(wù)
????2,任務(wù)延時(shí)
????3,信號(hào)量(包括共享型和獨(dú)占型)
????另外,在本例中,在各個(gè)任務(wù)中加入了從串口發(fā)送任務(wù)狀態(tài)的功能。
????
#include?
#include?
#include?
unsigned?char?Stack[400];
register?unsigned?char?OSRdyTbl??????????asm("r2");????//任務(wù)運(yùn)行就緒表
register?unsigned?char?OSTaskRunningPrio?asm("r3");????//正在運(yùn)行的任務(wù)
register?unsigned?char?IntNum????????????asm("r4");?????//中斷嵌套計(jì)數(shù)器
//只有當(dāng)中斷嵌套數(shù)為0,并且有中斷要求時(shí),才能在退出中斷時(shí),進(jìn)行任務(wù)調(diào)度
register?unsigned?char?OSCoreState???????asm("r16");?//?系統(tǒng)核心標(biāo)志位?,R16?編譯器沒有使用
//只有大于R15的寄存器才能直接賦值?例LDI?R16,0x01
//0x01?正在任務(wù)?切換??0x02?有中斷要求切換
#define?OS_TASKS?3????????????????????//設(shè)定運(yùn)行任務(wù)的數(shù)量
struct?TaskCtrBlock
{
??unsigned?int?OSTaskStackTop;??//保存任務(wù)的堆棧頂
??unsigned?int?OSWaitTick;??????//任務(wù)延時(shí)時(shí)鐘
}?TCB[OS_TASKS+1];
//防止被編譯器占用
//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?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?unsigned?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)Task>>8;????//將任務(wù)的地址高位壓入堆棧,
??*Stack--=(unsigned?int)Task;?????????//將任務(wù)的地址低位壓入堆棧,
????
??*Stack--=0x00;?????????????????????//R1?__zero_reg__????????????
??*Stack--=0x00;?????????????????????//R0?__tmp_reg__
??*Stack--=0x80;????????????????????????????????????????
//SREG?在任務(wù)中,開啟全局中斷????????
??for(i=0;i<14;i++)????//在?avr-libc?中的?FAQ中的?What?registers?are?used?by?the?C?compiler?
????*Stack--=i;????????????????????//描述了寄存器的作用????
??TCB[TaskID].OSTaskStackTop=(unsigned?int)Stack;????//將人工堆棧的棧頂,保存到堆棧的數(shù)組中
??OSRdyTbl|=0x01<
//開始任務(wù)調(diào)度,從最低優(yōu)先級(jí)的任務(wù)的開始
void?OSStartTask()????????
{
??OSTaskRunningPrio=OS_TASKS;
??SP=TCB[OS_TASKS].OSTaskStackTop+17;
??__asm__?__volatile__(????"reti"???????"nt"??);?
}
//進(jìn)行任務(wù)調(diào)度
void?OSSched(void)
{?
??__asm__?__volatile__("LDI??R16,0x01?????????????nt");??
??//清除中斷要求任務(wù)切換的標(biāo)志位,設(shè)置正在任務(wù)切換標(biāo)志位
??__asm__?__volatile__("SEI???????????????????????nt");??????
??//開中斷,因?yàn)槿绻蛑袛嘣谌蝿?wù)調(diào)度中進(jìn)行,要重新進(jìn)行調(diào)度時(shí),已經(jīng)關(guān)中斷
???//??根據(jù)中斷時(shí)保存寄存器的次序入棧,模擬一次中斷后,入棧的情況??
??__asm__?__volatile__("PUSH?__zero_reg__?????????nt");??//R1
??__asm__?__volatile__("PUSH?__tmp_reg__??????????nt");??//R0?
??__asm__?__volatile__("IN???__tmp_reg__,__SREG__?nt");??//保存狀態(tài)寄存器SREG
??__asm__?__volatile__("PUSH?__tmp_reg__??????????nt");
??__asm__?__volatile__("CLR??__zero_reg__?????????nt");??//R0重新清零
??__asm__?__volatile__("PUSH?R18??????????????????nt");
??__asm__?__volatile__("PUSH?R19??????????????????nt");
??__asm__?__volatile__("PUSH?R20??????????????????nt");
??__asm__?__volatile__("PUSH?R21??????????????????nt");
??__asm__?__volatile__("PUSH?R22??????????????????nt");
??__asm__?__volatile__("PUSH?R23??????????????????nt");
??__asm__?__volatile__("PUSH?R24??????????????????nt");
??__asm__?__volatile__("PUSH?R25??????????????????nt");
??__asm__?__volatile__("PUSH?R26??????????????????nt");
??__asm__?__volatile__("PUSH?R27??????????????????nt");
??__asm__?__volatile__("PUSH?R30??????????????????nt");????
??__asm__?__volatile__("PUSH?R31??????????????????nt");
????
??__asm__?__volatile__("Int_OSSched:??????????????nt");??//當(dāng)中斷要求調(diào)度,直接進(jìn)入這里
??__asm__?__volatile__("SEI???????????????????????nt");?
????//開中斷,因?yàn)槿绻蛑袛嘣谌蝿?wù)調(diào)度中進(jìn)行,已經(jīng)關(guān)中斷?
??__asm__?__volatile__("PUSH?R28??????????????????nt");??//R28與R29用于建立在堆棧上的指針
??__asm__?__volatile__("PUSH?R29??????????????????nt");??//入棧完成
????
??TCB[OSTaskRunningPrio].OSTaskStackTop=SP;???????????//將正在運(yùn)行的任務(wù)的堆棧底保存
??unsigned?char?OSNextTaskPrio;????????????????????????????//在現(xiàn)有堆棧上開設(shè)新的空間?
??for?(OSNextTaskPrio?=?0;?????????????????????????????????//進(jìn)行任務(wù)調(diào)度
????OSNextTaskPrio?????OSNextTaskPrio++);
????OSTaskRunningPrio?=?OSNextTaskPrio?;
??cli();??//保護(hù)堆棧轉(zhuǎn)換
??SP=TCB[OSTaskRunningPrio].OSTaskStackTop;
??sei();
????
??//根據(jù)中斷時(shí)的出棧次序????
??__asm__?__volatile__("POP??R29??????????????????nt");????
??__asm__?__volatile__("POP??R28??????????????????nt");????????
??__asm__?__volatile__("POP??R31??????????????????nt");????
??__asm__?__volatile__("POP??R30??????????????????nt");????
??__asm__?__volatile__("POP??R27??????????????????nt");????
??__asm__?__volatile__("POP??R26??????????????????nt");????
??__asm__?__volatile__("POP??R25??????????????????nt");????
??__asm__?__volatile__("POP??R24??????????????????nt");????
??__asm__?__volatile__("POP??R23??????????????????nt");????
??__asm__?__volatile__("POP??R22??????????????????nt");????
??__asm__?__volatile__("POP??R21??????????????????nt");????
??__asm__?__volatile__("POP??R20??????????????????nt");????
??__asm__?__volatile__("POP??R19??????????????????nt");
??__asm__?__volatile__("POP??R18??????????????????nt");
??__asm__?__volatile__("POP??__tmp_reg__??????????nt");??????//SERG?出棧并恢復(fù)
??__asm__?__volatile__("OUT??__SREG__,__tmp_reg__?nt");??????//
??__asm__?__volatile__("POP??__tmp_reg__??????????nt");??????//R0?出棧
??__asm__?__volatile__("POP??__zero_reg__?????????nt");??????//R1?出棧
??//中斷時(shí)出棧完成
??__asm__?__volatile__("CLI???????????????????????nt");??//關(guān)中斷????
??__asm__?__volatile__("SBRC?R16,1????????????????nt");??//SBRC當(dāng)寄存器位為0剛跳過下一條指令
??//檢查是在調(diào)度時(shí),是否有中斷要求任務(wù)調(diào)度?0x02是中斷要求調(diào)度的標(biāo)志位
??__asm__?__volatile__("RJMP?OSSched??????????????nt");??//重新調(diào)度
??__asm__?__volatile__("LDI??R16,0x00?????????????nt");??
??//清除中斷要求任務(wù)切換的標(biāo)志位,清除正在任務(wù)切換標(biāo)志位
??__asm__?__volatile__("RETI??????????????????????nt");?????//返回并開中斷
}
//從中斷退出并進(jìn)行調(diào)度
void?IntSwitch(void)
{????
??//當(dāng)中斷無嵌套,并且沒有在切換任務(wù)的過程中,直接進(jìn)行任務(wù)切換
??if(OSCoreState?==?0x02?&&?IntNum==0)?
??{
????//進(jìn)入中斷時(shí),已經(jīng)保存了SREG和R0,R1,R18~R27,R30,R31
????__asm__?__volatile__("POP??R31??????????????????nt");??//去除因調(diào)用子程序而入棧的PC
????__asm__?__volatile__("POP??R31??????????????????nt");
????__asm__?__volatile__("LDI??R16,0x01?????????????nt");??
????//清除中斷要求任務(wù)切換的標(biāo)志位,設(shè)置正在任務(wù)切換標(biāo)志位
????__asm__?__volatile__("RJMP?Int_OSSched??????????nt");??//重新調(diào)度
??}
}
////////////////////////////////////////////任務(wù)處理
//掛起任務(wù)
void?OSTaskSuspend(unsigned?char?prio)?
{
??TCB[prio].OSWaitTick=0;
??OSRdyTbl?&=?~(0x01<
????OSSched();???????????????//從新調(diào)度
}
//恢復(fù)任務(wù)?可以讓被OSTaskSuspend或?OSTimeDly暫停的任務(wù)恢復(fù)
void?OSTaskResume(unsigned?char?prio)
{
??OSRdyTbl?|=?0x01<
??if(OSTaskRunningPrio>prio)???//當(dāng)要當(dāng)前任務(wù)的優(yōu)先級(jí)低于重置位的任務(wù)的優(yōu)先級(jí)
????OSSched();???????????????//從新調(diào)度??????????????//從新調(diào)度
}
//?任務(wù)延時(shí)
void?OSTimeDly(unsigned?int?ticks)
{
??if(ticks)?????????????????????????????//當(dāng)延時(shí)有效
??{
????OSRdyTbl?&=?~(0x01<
????OSSched();??????????????????????????//從新調(diào)度
??}
}
//信號(hào)量
struct?SemBlk
{
??unsigned?char?OSEventType;?????//型號(hào)?0,信號(hào)量獨(dú)占型;1信號(hào)量共享型?
??unsigned?char?OSEventState;????//狀態(tài)?0,不可用;1,可用
??unsigned?char?OSTaskPendTbl;???//等待信號(hào)量的任務(wù)列表
}?Sem[10];
//初始化信號(hào)量
void?OSSemCreat(unsigned?char?Index,unsigned?char?Type)
{
??Sem[Index].OSEventType=Type;??//型號(hào)?0,信號(hào)量獨(dú)占型;1信號(hào)量共享型?
??Sem[Index].OSTaskPendTbl=0;
??Sem[Index].OSEventState=0;
}
//任務(wù)等待信號(hào)量,掛起
//當(dāng)Timeout==0xffff時(shí),為無限延時(shí)
unsigned?char?OSTaskSemPend(unsigned?char?Index,unsigned?int?Timeout)
{
??//unsigned?char?i=0;
??if(Sem[Index].OSEventState)??????????????????????//信號(hào)量有效
??{?
????if(Sem[Index].OSEventType==0)??????????????????//如果為獨(dú)占型
????Sem[Index].OSEventState?=?0x00;????????????????//信號(hào)量被獨(dú)占,不可用
??}
??else
??{????????????????????????????????????????????????//加入信號(hào)的任務(wù)等待表
????Sem[Index].OSTaskPendTbl?|=?0x01<
????OSRdyTbl?&=?~(0x01<
????if(TCB[OSTaskRunningPrio].OSWaitTick==0?)?????//超時(shí),未能拿到資源
??????????return?0;????????
??}
??return?1;
}
//發(fā)送一個(gè)信號(hào)量,可以從任務(wù)或中斷發(fā)送
void?OSSemPost(unsigned?char?Index)
{
if(Sem[Index].OSEventType)????????????????//當(dāng)要求的信號(hào)量是共享型
??{
????Sem[Index].OSEventState=0x01;???????????//使信號(hào)量有效
????OSRdyTbl?|=Sem?[Index].OSTaskPendTbl;???//使在等待該信號(hào)的所有任務(wù)就緒
????Sem[Index].OSTaskPendTbl=0;?????????????//清空所有等待該信號(hào)的等待任務(wù)
??}??
??else???????????????????????????????????????//當(dāng)要求的信號(hào)量為獨(dú)占型
??{??????
????unsigned?char?i;
????for?(i?=?0;?i?????if(i?????{
??????Sem[Index].OSTaskPendTbl?&=?~(0x01<??????OSRdyTbl?|=?0x01<????}
????else
????{
??????Sem[Index].OSEventState?=1;????????//使信號(hào)量有效
????}
??}
}
//從任務(wù)發(fā)送一個(gè)信號(hào)量,并進(jìn)行調(diào)度
void?OSTaskSemPost(unsigned?char?Index)?
{
??OSSemPost(Index);
??OSSched();???
}
//清除一個(gè)信號(hào)量,只對(duì)共享型的有用。
//對(duì)于獨(dú)占型的信號(hào)量,在任務(wù)占用后,就交得不可以用了。?
void?OSSemClean(unsigned?char?Index)
{
??Sem[Index].OSEventState?=0;??????????//要求的信號(hào)量無效
}
void?TCN0Init(void)????//?計(jì)時(shí)器0
{
??TCCR0?=?0;
??TCCR0?|=?(1<
????
}
SIGNAL(SIG_OVERFLOW0)
{
??IntNum++;?????//中斷嵌套+1
??sei();??//在中斷中,重開中斷
????
??unsigned?char?i;
??for(i=0;i
????if(TCB[i].OSWaitTick?&&?TCB[i].OSWaitTick!=0xffff)?
????{
??????TCB[i].OSWaitTick--;
??????if(TCB[i].OSWaitTick==0)?????????//當(dāng)任務(wù)時(shí)鐘到時(shí),必須是由定時(shí)器減時(shí)的才行
??????{??
????????OSRdyTbl?|=?(0x01<????????OSCoreState|=0x02;?????????//要求任務(wù)切換的標(biāo)志位
??????}
????}
??}
??TCNT0=100;
??cli();
??IntNum--;???????????????//中斷嵌套-1
??IntSwitch();?????????//進(jìn)行任務(wù)調(diào)度
}
unsigned?char?__attribute__?((progmem))?proStrA[]="Task???????????????????????";
unsigned?char?strA[20];
SIGNAL(SIG_UART_RECV)????????//串口接收中斷
{
??strA[0]=UDR;
}
/////////////////////////////////////串口發(fā)送
unsigned?char?*pstr_UART_Send;
unsigned?int??nUART_Sending=0;
void?UART_Send(unsigned?char?*Res,unsigned?int?Len)????//發(fā)送字符串?dāng)?shù)組
{
??if(Len>0)
??{
????pstr_UART_Send=Res;????//發(fā)送字串的指針
????nUART_Sending=Len;????//發(fā)送字串的長(zhǎng)度
????UCSRB=0xB8;????????????????????//發(fā)送中斷使能
??}
}
//SIGNAL?在中斷期間,其它中斷禁止
SIGNAL(SIG_UART_DATA)???????//串口發(fā)送數(shù)據(jù)中斷
{
??IntNum++;?????//中斷嵌套+1,不充許中斷
??if(nUART_Sending)????????????????????//如果未發(fā)完
??{
????UDR=*pstr_UART_Send;????????//發(fā)送字節(jié)
????pstr_UART_Send++;????????????????//發(fā)送字串的指針加1
????nUART_Sending--;????????????????//等待發(fā)送的字串?dāng)?shù)減1
??}
??if(nUART_Sending==0)????????????//當(dāng)已經(jīng)發(fā)送完
??{????
????OSSemPost(0);
????OSCoreState|=0x02;??????//要求任務(wù)切換的標(biāo)志位
????UCSRB=0x98;????
??}
??cli();????????????????????????//關(guān)發(fā)送中斷
??IntNum--;????
??IntSwitch();?//進(jìn)行任務(wù)調(diào)度
}
void?UARTInit()????//初始化串口
{
#define?fosc?8000000?//晶振8??MHZ?UBRRL=(fosc/16/(baud+1))%256;
#define?baud?9600?????//波特率
??OSCCAL=0x97;??????????//串口波特率校正值,從編程器中讀出
??//UCSRB=(1<
??//UCSRB=0x08;
??UBRRL=(fosc/16/(baud+1))%256;
??UBRRH=(fosc/16/(baud+1))/256;
??UCSRC=(1<
??UDR=0;
}
//打印unsigned?int?到字符串中?00000
void?strPUT_uInt(unsigned?char?*Des,unsigned?int?i)
{
??unsigned?char?j;
??Des=Des+4;
??for(j=0;j<5;j++)
??{
????*Des=i%10+’0’;
????i=i/10;
????Des--;
??}
}
void?strPUT_Star(unsigned?char?*Des,unsigned?char?i)
{
??unsigned?char?j;
??for(j=0;j??{
????*Des++=’*’;
??}
??*Des++=13;
}
unsigned?int?strPUT_TaskState(unsigned?char?*Des,
??????????????????????????????unsigned?char?TaskID,
??????????????????unsigned?char?Num)
{
??//unsigned?int?i=0;
??*(Des+4)=’0’+TaskID;
??strPUT_uInt(Des+6,Num);
??strPUT_Star(Des+12,TaskID);
??return?12+TaskID+1;
}
void?Task0()
{
??unsigned?int?j=0;
??while(1)
??{????????????
????PORTB=j++;????????????
????if(OSTaskSemPend(0,0xffff))
????{
??????unsigned?int?m;
??????m=strPUT_TaskState(strA,OSTaskRunningPrio,j);
??????UART_Send(strA,m);
????}
????OSTimeDly(200);
??}
}
void?Task1()
{
??unsigned?int?j=0;
??while(1)
??{
????PORTC=j++;
????if(OSTaskSemPend(0,0xffff))
????{
??????unsigned?int?m;
??????m=strPUT_TaskState(strA,OSTaskRunningPrio,j);
??????UART_Send(strA,m);
????}
????OSTimeDly(100);
??}
}
void?Task2()
{
??unsigned?int?j=0;
??while(1)
??{
????if(OSTaskSemPend(0,0xffff))
????{
??????unsigned?int?m;
??????m=strPUT_TaskState(strA,OSTaskRunningPrio,j);
??????UART_Send(strA,m);
????}
????PORTD=j++;?
????OSTimeDly(50);??
??}
}
void?TaskScheduler()
{?
??OSSched();?
??while(1)
??{????????
??}
}
int?main(void)
{????????
??strlcpy_P(strA,proStrA,20);
??UARTInit();
??TCN0Init();
??OSRdyTbl=0;
??IntNum=0;
??OSTaskCreate(Task0,&Stack[99],0);
??OSTaskCreate(Task1,&Stack[199],1);
??OSTaskCreate(Task2,&Stack[299],2);
??OSTaskCreate(TaskScheduler,&Stack[399],OS_TASKS);
??OSStartTask();
}
結(jié)束語?
????本文中的例子,基本上用WinAVR和?Proteus調(diào)試仿真成功,一定可能存在某些方面的缺陷,因?yàn)楣ぷ魃蠒r(shí)間的壓力,就沒有進(jìn)一步查找。
- RTOS(118666)
相關(guān)推薦
RTOS中的線程、進(jìn)程和協(xié)程詳解


3天開發(fā)一個(gè)RTOS挑戰(zhàn)
AVR單片機(jī)的C語言開發(fā)環(huán)境建立
RTOS在中國(guó)
RTOS的ABC討論(轉(zhuǎn))
avr proteus仿真第一課:安裝設(shè)置avr studio和winavr
DIY一款屬于自己的智能家居
DIY制作屬于自己的數(shù)字示波器
STM32 RTOS介紹
[推薦]·零基礎(chǔ)新手建站教程系列:如何一步一步的搭建屬于自己的獨(dú)立網(wǎng)站
[討論]如何一步一步的搭建屬于自己的獨(dú)立網(wǎng)站
【先楫HPM5361EVK開發(fā)板試用體驗(yàn)】-06-如何自己建立一個(gè)工程
【福利】手把手教你 從“0”開始去獨(dú)立寫一個(gè)RTOS
【設(shè)計(jì)技巧】rtos的核心原理簡(jiǎn)析
為什么需要RTOS?
介紹基于AD來繪制一款屬于自己的DAPLink在線仿真+脫機(jī)燒錄器
使用Vitis HLS創(chuàng)建屬于自己的IP相關(guān)資料分享
關(guān)于自己建立PCB庫(kù)的問題,有點(diǎn)兒急。。。。
內(nèi)部時(shí)鐘和RTOS系統(tǒng)
剛剛打開一個(gè)AVR工程,出問題,編譯也沒有辦法進(jìn)行
剛開始接觸AVR 自己DIY AVR ISP下載 成功
剛開始接觸AVR 自己DIY AVR ISP下載 成功
發(fā)一個(gè)自制的RTOS,適合學(xué)習(xí)和極簡(jiǎn)開發(fā)
在RTOS框架下使用ROSSerial
如何建立一個(gè)屬于自己的AVR的RTOS
如何去實(shí)現(xiàn)一種基于ARM9的多任務(wù)搶占式調(diào)度器設(shè)計(jì)
如何在RTOS中使用看門狗
如何學(xué)習(xí)RTOS
如何用ICCV7 For AVR建立單片機(jī)程序工程
如何編寫屬于自己的算法呢
如何規(guī)劃建立屬于自己的電子工作室
嵌入式系列:RTOS專題資料合集
帶有Arduion IDE和RTOS的ESP8266可能嗎?
開發(fā)中用到的RTOS和TSOS有什么區(qū)別
怎樣去創(chuàng)建屬于自己的Iconfont圖標(biāo)庫(kù)呢
用protel99se時(shí)建立自己原件庫(kù)時(shí)求助?
能否提供一個(gè)關(guān)于如何使用RTOS配置TouchGFX的示例
請(qǐng)大神給一個(gè)AVR燒寫器的原理圖
讀什么,才能找到屬于自己的生命的意義?
轉(zhuǎn):構(gòu)建屬于自己的AVR操作系統(tǒng)
如何建立一個(gè)屬于自己的AVR的RTOS

編寫屬于自己的PCB設(shè)計(jì)規(guī)則檢查器

微軟白皮書 屬于自己的全新物聯(lián)網(wǎng)

如何在Altium Designer上面建立自己的3D庫(kù)

AVR單片機(jī)的RTOS AVRX應(yīng)用的資料介紹

曝特斯拉正在秘密實(shí)驗(yàn)室開發(fā)屬于自己的電池

如何才能建立一個(gè)屬于自己AVR的RTOS

如何建立一個(gè)屬于自己的AVR的RTOS詳細(xì)教程說明

淺析OS中的線程、進(jìn)程和協(xié)程與RTOS任務(wù)屬于那種


如何搭建一個(gè)屬于自己的簡(jiǎn)易電動(dòng)滑板?


51操作系統(tǒng)學(xué)習(xí)筆記(三):建立一個(gè)屬于自己的AVR的RTOS(1)

51操作系統(tǒng)學(xué)習(xí)筆記(四):建立一個(gè)屬于自己的AVR的RTOS(2)

RTOS消息隊(duì)列的應(yīng)用


RTOS中的任務(wù)是線程?進(jìn)程?還是協(xié)程?


如何快速打造屬于自己的工業(yè)物聯(lián)網(wǎng)云平臺(tái)


評(píng)論