![博客操作系統(tǒng)_第1頁](http://file4.renrendoc.com/view/14ceb60e548fbef0715598589d6abeea/14ceb60e548fbef0715598589d6abeea1.gif)
![博客操作系統(tǒng)_第2頁](http://file4.renrendoc.com/view/14ceb60e548fbef0715598589d6abeea/14ceb60e548fbef0715598589d6abeea2.gif)
![博客操作系統(tǒng)_第3頁](http://file4.renrendoc.com/view/14ceb60e548fbef0715598589d6abeea/14ceb60e548fbef0715598589d6abeea3.gif)
![博客操作系統(tǒng)_第4頁](http://file4.renrendoc.com/view/14ceb60e548fbef0715598589d6abeea/14ceb60e548fbef0715598589d6abeea4.gif)
![博客操作系統(tǒng)_第5頁](http://file4.renrendoc.com/view/14ceb60e548fbef0715598589d6abeea/14ceb60e548fbef0715598589d6abeea5.gif)
版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
整些基本概念
什么是操作系統(tǒng)?
操作系統(tǒng)(OperatingSystem,OS)是一種基本系統(tǒng)軟件。它在計(jì)算機(jī)硬件和計(jì)算機(jī)應(yīng)用程序之間,通過提供應(yīng)用程序接口(ApplicationProgrammingInterface,API),屏蔽了計(jì)算機(jī)硬件工作的一些細(xì)節(jié),從而使應(yīng)用程序的設(shè)計(jì)人員得以在一個(gè)友好的平臺(tái)上進(jìn)行應(yīng)用程序的設(shè)計(jì)和開發(fā),大大提高了應(yīng)用程序的開發(fā)效率。操作系統(tǒng)的作用
操作系統(tǒng)為應(yīng)用程序提供一個(gè)界面友好,性能穩(wěn)定,安全,效率高,操作方便的虛擬計(jì)算機(jī)。操作系統(tǒng)的功能
1.處理器的管理
2.存儲(chǔ)的管理
3.設(shè)備的管理
4.文件的管理
5.網(wǎng)絡(luò)和通信的管理
6.提供用戶接口嵌入式系統(tǒng)
嵌入式系統(tǒng)是對(duì)對(duì)象進(jìn)行自動(dòng)控制而使其具有智能化并可嵌入對(duì)象體系中的專用計(jì)算機(jī)系統(tǒng)。嵌入式系統(tǒng)的特點(diǎn)
1.專用性強(qiáng)
2.可裁剪性好
3.實(shí)時(shí)性與可靠性好
4.功耗低嵌入式操作系統(tǒng)的特點(diǎn)
1.微型化
2.可裁剪性
3.實(shí)時(shí)性
4.高可靠性
5.易移植性實(shí)時(shí)操作系統(tǒng)
能使計(jì)算機(jī)系統(tǒng)及時(shí)響應(yīng)外部事件的請(qǐng)求,并能及時(shí)控制所有實(shí)施設(shè)備與實(shí)時(shí)任務(wù)協(xié)調(diào)運(yùn)行,且能在一個(gè)規(guī)定的時(shí)間內(nèi)完成對(duì)事件的處理。
實(shí)時(shí)操作系統(tǒng)需要滿足的條件
1.多任務(wù)系統(tǒng)
2.任務(wù)的切換時(shí)間與系統(tǒng)中的任務(wù)數(shù)無關(guān)
3.中斷延時(shí)的時(shí)間可預(yù)知并盡可能短ucos-ii
ucos-ii是由JeanJ.Labrosse于1992年編寫的一個(gè)嵌入式多任務(wù)實(shí)時(shí)操作系統(tǒng),最早這個(gè)系統(tǒng)叫做ucos,后來進(jìn)過10年的應(yīng)用和修改,被美國聯(lián)邦航空管理局認(rèn)證。
它構(gòu)思巧妙,結(jié)構(gòu)精煉,很適合初次接觸操作系統(tǒng)的人去學(xué)習(xí)并應(yīng)用。說點(diǎn)自己的初步感受
1.多任務(wù),比如以前用單片機(jī),一次幾乎只做一個(gè)任務(wù),有了操作系統(tǒng)可以做多個(gè)任務(wù),而且互不干擾。
2.使編程變的很方便,程序員只負(fù)責(zé)編寫任務(wù),對(duì)任務(wù)的管理交給操作系統(tǒng)去做。
3.效率高,比如以前常常用一個(gè)delay函數(shù)做一個(gè)延時(shí),但是現(xiàn)在可以把這個(gè)delay時(shí)間用于CPU執(zhí)行別的任務(wù),CPU就不會(huì)閑著沒事數(shù)數(shù)玩ucos創(chuàng)建任務(wù)
ucos的任務(wù)有5種狀態(tài):
1.休眠態(tài):任務(wù)駐留在內(nèi)存中,但并不被操作系統(tǒng)調(diào)度
2.就緒態(tài):任務(wù)已經(jīng)準(zhǔn)備好,可以運(yùn)行,但是由于比它優(yōu)先級(jí)更高的任務(wù)在運(yùn)行,所以它暫時(shí)還不能運(yùn)行
3.運(yùn)行態(tài):任務(wù)掌握了CPU的使用權(quán),正在運(yùn)行
4.掛起態(tài)(等待事件態(tài)):任務(wù)在等待某一事件(共享資源、信號(hào))的發(fā)生。
5.被中斷態(tài):任務(wù)被中斷,暫時(shí)得不到運(yùn)行。其轉(zhuǎn)換關(guān)系如下圖:
下面用VC做個(gè)試驗(yàn):
//***********************************************************************************
#include<includes.h>#define
TASK_STK_SIZE
128
//定義任務(wù)堆棧的大小OS_STK
TaskOneStack[TASK_STK_SIZE];
//為任務(wù)TaskOne建立一個(gè)堆棧voidTaskOne(void*p_arg);voidmain(void)
{
OSInit();
//初始化ucos
//建立任務(wù)TaskOne,無數(shù)據(jù)區(qū)指針,
堆棧指針,
優(yōu)先級(jí)6
OSTaskCreate(TaskOne,
0
,&TaskOneStack[TASK_STK_SIZE-1],
6
);
OSStart();
//開始運(yùn)行ucos
}
void
TaskOne(void*p_arg)
{
p_arg=p_arg;
//無用,僅為消除編譯器報(bào)警
while(1)
//任務(wù)體,總是死循環(huán)
{
printf("TaskOne:我在運(yùn)行!\n");
//打印
OSTimeDlyHMSM(0,0,1,0);
//延時(shí)0小時(shí)0分1秒0毫秒
}
}
//***********************************************************************************運(yùn)行結(jié)果如下圖:
以上注意幾點(diǎn):
1.每個(gè)任務(wù)都要有一個(gè)合適大小的堆棧,并用OS_STK類型定義
2.main中基本步驟是OSInit()->任務(wù)、信號(hào)等的管理->OSStart()
。
3.任務(wù)要做成一個(gè)無限循環(huán)體
4.任務(wù)的延時(shí)要用ucos的延時(shí)函數(shù)OSTimeDlyHMSM或OSTimeDly,把CPU交出,誰也不能獨(dú)占嘛。
5.OSTaskCreateExt也可以創(chuàng)建任務(wù),功能更多。
6.此版本支持64個(gè)任務(wù)(目前最新的ucos支持256個(gè)任務(wù)),最低兩個(gè)任務(wù)為系統(tǒng)任務(wù),不要用,按作者的建議,優(yōu)先級(jí)最低4個(gè)和最高4個(gè)任務(wù)不要用。關(guān)于內(nèi)核的分析:1.任務(wù)在OSTaskCreate之前處于休眠態(tài),OSTaskCreate之后處于就緒態(tài),打印printf時(shí)明顯是運(yùn)行態(tài),OSTimeDlyHMSM后處于等待狀態(tài)。
2.OS_TCB是一個(gè)管理任務(wù)的結(jié)構(gòu)類型,每次創(chuàng)建任務(wù)后,OS會(huì)為該任務(wù)創(chuàng)建一個(gè)任務(wù)控制塊,該任務(wù)控制塊中的OSTCBPrio存放該任務(wù)的優(yōu)先級(jí)。
3.OS中有一個(gè)就緒表(INT8U)OSRdyTbl[8],記錄各個(gè)任務(wù)的就緒情況,每一個(gè)變量8位對(duì)應(yīng)8個(gè)任務(wù),代表一組,整個(gè)數(shù)組64位正好對(duì)應(yīng)64個(gè)任務(wù),置一為就緒。還有一個(gè)(INT8U)OSRdyGrp共8位,如果8組任務(wù)中只要某組中有就緒任務(wù),那么OSRdyGrp對(duì)應(yīng)位被置一。
4。登記就緒表:
OSRdyGrp|=OSMapTbl[prio>>3];
OSRdyTbl[prio>>3]|=OSMapTbl[prio&0x07];OSMapTbl是一個(gè)查找表,ucos為了加快速度,盡量用查找表的方法來處理數(shù)據(jù),這樣比普通的算法要快,但用費(fèi)些空間。INT8U
const
OSMapTbl[]
={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};按照這種方式:就緒表OSRdyTbl[8]和OSRdyGrp就被順利登記了,原理如下圖:
ucos任務(wù)的切換只要你會(huì)創(chuàng)建一個(gè)任務(wù),就會(huì)創(chuàng)建跟多的任務(wù),但要注意,每個(gè)任務(wù)必須有獨(dú)自的任務(wù)堆棧和優(yōu)先級(jí),還有每個(gè)任務(wù)必須有OS延時(shí)函數(shù),這樣才能在自己運(yùn)行過一次時(shí),把CPU讓給別的任務(wù),有福同享嘛。下面做個(gè)雙任務(wù)程序:
//***********************************************************************************
#include<includes.h>#define
TASK_STK_SIZE
128
//定義任務(wù)堆棧的大小OS_STK
TaskOneStack[TASK_STK_SIZE];
//為任務(wù)TaskOne建立一個(gè)堆棧
OS_STK
TaskTwoStack[TASK_STK_SIZE];
//為任務(wù)TaskTwo建立一個(gè)堆棧voidTaskOne(void*p_arg);
voidTaskTwo(void*p_arg);voidmain(void)
{
OSInit();
//初始化ucos
//建立任務(wù)TaskOne,無數(shù)據(jù)區(qū)指針,
堆棧指針,
優(yōu)先級(jí)6
OSTaskCreate(TaskOne,
0
,&TaskOneStack[TASK_STK_SIZE-1],
6
);
//建立任務(wù)TaskTwo,無數(shù)據(jù)區(qū)指針,
堆棧指針,
優(yōu)先級(jí)8
OSTaskCreate(TaskTwo,
0
,&TaskTwoStack[TASK_STK_SIZE-1],
8
);
OSStart();
//開始運(yùn)行ucos
}
void
TaskOne(void*p_arg)
{
p_arg=p_arg;
//無用,僅為消除編譯器報(bào)警
while(1)
//任務(wù)體,總是死循環(huán)
{
printf("TaskOne:我在運(yùn)行!\n");
//打印
OSTimeDlyHMSM(0,0,1,0);
//延時(shí)0小時(shí)0分1秒0毫秒
}
}void
TaskTwo(void*p_arg)
{
p_arg=p_arg;
//無用,僅為消除編譯器報(bào)警
while(1)
//任務(wù)體,總是死循環(huán)
{
printf("
TaskTwo:我處在運(yùn)行中!\n");
//打印
OSTimeDlyHMSM(0,0,2,0);
//延時(shí)0小時(shí)0分2秒0毫秒
}
}
//***********************************************************************************運(yùn)行結(jié)果如下圖:
可以看出TaskOne和TaskTwo輪流運(yùn)行,由于TaskTwo延時(shí)是2秒,所以它運(yùn)行頻率是TaskOne的一半,每個(gè)任務(wù)必須有一個(gè)OSTimeDlyHMSM,以便在自己運(yùn)行一次后,把CPU讓給優(yōu)先級(jí)最高的就緒任務(wù)。如果不給延時(shí),只有這一個(gè)任務(wù)一直處于運(yùn)行中。
內(nèi)核分析:
1.當(dāng)前任務(wù)運(yùn)行OSTimeDlyHMSM后,它被移出任務(wù)就緒表://延時(shí)后處于等待狀態(tài)
if((OSRdyTbl[OSTCBCur->OSTCBY]&=~OSTCBCur->OSTCBBitX)==0){
/*Delaycurrenttask
*/
OSRdyGrp&=~OSTCBCur->OSTCBBitY;
2.這種移出不是無限制的,它的任務(wù)控制塊中的OSTCBDly被賦值,值為延時(shí)大?。?/p>
OSTCBCur->OSTCBDly=ticks;
3.ucos每一個(gè)時(shí)間片(比如10ms)進(jìn)行OSTickISR(),執(zhí)行一次OSTimeTick,將每個(gè)等待任務(wù)的OSTCBDly減一,一旦到0,就把它放入任務(wù)就緒表:void
OSTimeTick(void):
ptcb=OSTCBList;
/*PointatfirstTCBinTCBlist
*/
while(ptcb->OSTCBPrio!=OS_IDLE_PRIO){
/*GothroughallTCBsinTCBlist
*/
OS_ENTER_CRITICAL();
if(ptcb->OSTCBDly!=0){
/*DelayedorwaitingforeventwithTO
*/
if(--ptcb->OSTCBDly==0){
/*Decrementnbroftickstoendofdelay
*/
if((ptcb->OSTCBStat&OS_STAT_SUSPEND)==OS_STAT_RDY){/*Istasksuspended?
*/
OSRdyGrp
|=ptcb->OSTCBBitY;/*No,
MaketaskR-to-R(timedout)*/
OSRdyTbl[ptcb->OSTCBY]|=ptcb->OSTCBBitX;
}else{
/*Yes,Leave1ticktoprevent...
*/
ptcb->OSTCBDly=1;
/*...loosingthetaskwhenthe...
*/
}
/*...suspensionisremoved.
*/
}
}
ptcb=ptcb->OSTCBNext;
/*PointatnextTCBinTCBlist
*/
4.OSTickISR()然后運(yùn)行OSIntExit,OSIntExit先找到最高優(yōu)先級(jí)的任務(wù),將其優(yōu)先級(jí)放入OSTCBHighRdy中:
OSIntExitY
=OSUnMapTbl[OSRdyGrp];
/*...andnotlocked.
*/
OSPrioHighRdy=(INT8U)((OSIntExitY<<3)+OSUnMapTbl[OSRdyTbl[OSIntExitY]]);
if(OSPrioHighRdy!=OSPrioCur){
/*NoCtxSwifcurrenttaskishighestrdy*/
OSTCBHighRdy
=OSTCBPrioTbl[OSPrioHighRdy];
OSCtxSwCtr++;
/*Keeptrackofthenumberofctxswitches*/
OSIntCtxSw();
/*Performinterruptlevelctxswitch
*/從就緒表中查找最高優(yōu)先級(jí)的任務(wù),用幾個(gè)循環(huán)就可以這樣,但作者并沒這樣做,作者用查找表的方式,極大的提高速度,表如下:INT8U
const
OSUnMapTbl[256]={
0,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
/*0x00to0x0F
*/
4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
/*0x10to0x1F
*/
5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
/*0x20to0x2F
*/
4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
/*0x30to0x3F
*/
6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
/*0x40to0x4F
*/
4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
/*0x50to0x5F
*/
5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
/*0x60to0x6F
*/
4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
/*0x70to0x7F
*/
7,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
/*0x80to0x8F
*/
4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
/*0x90to0x9F
*/
5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
/*0xA0to0xAF
*/
4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
/*0xB0to0xBF
*/
6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
/*0xC0to0xCF
*/
4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
/*0xD0to0xDF
*/
5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
/*0xE0to0xEF
*/
4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0
/*0xF0to0xFF
*/
};
如果你看到表很困惑,不要著急,自己假設(shè)幾個(gè)任務(wù)處于就緒狀態(tài),然后按程序給出的方法查一下表,從這個(gè)過程中你會(huì)發(fā)現(xiàn)此表的內(nèi)涵。
5.OSIntExit再運(yùn)行OSIntCtxSw(),讓優(yōu)先級(jí)的就緒任務(wù)運(yùn)行,其實(shí)就是把當(dāng)前CPU的所有寄存器壓入當(dāng)前任務(wù)的堆棧,將最高優(yōu)先級(jí)的就緒任務(wù)的堆棧中的內(nèi)容填充CPU各個(gè)寄存器。
這樣每個(gè)任務(wù)就可以按你延時(shí)的方式,有條不紊的穿插運(yùn)行。ucos刪除任務(wù)
刪除任務(wù)并非真的刪除任務(wù)的代碼,而是將此任務(wù)回到休眠態(tài)。
其函數(shù)為OSTaskDel(?);
//?為該任務(wù)的優(yōu)先級(jí)先做個(gè)程序?qū)嶒?yàn)下:
//***********************************************************************************
#include<includes.h>#define
TASK_STK_SIZE
128
//定義任務(wù)堆棧的大小OS_STK
TaskOneStack[TASK_STK_SIZE];
//為任務(wù)TaskOne建立一個(gè)堆棧
OS_STK
TaskTwoStack[TASK_STK_SIZE];
//為任務(wù)TaskTwo建立一個(gè)堆棧
OS_STK
TaskThreeStack[TASK_STK_SIZE];
//為任務(wù)TaskTwo建立一個(gè)堆棧voidTaskOne(void*p_arg);
voidTaskTwo(void*p_arg);
voidTaskThree(void*p_arg);voidmain(void)
{
OSInit();
//初始化ucos
//建立任務(wù)TaskOne,無數(shù)據(jù)區(qū)指針,
堆棧指針,
優(yōu)先級(jí)6
OSTaskCreate(TaskOne,
0
,&TaskOneStack[TASK_STK_SIZE-1],
6
);
//建立任務(wù)TaskTwo,無數(shù)據(jù)區(qū)指針,
堆棧指針,
優(yōu)先級(jí)7
OSTaskCreate(TaskTwo,
0
,&TaskTwoStack[TASK_STK_SIZE-1],
7
);
//建立任務(wù)TaskThree,無數(shù)據(jù)區(qū)指針,
堆棧指針,
優(yōu)先級(jí)8
OSTaskCreate(TaskThree,
0
,&TaskThreeStack[TASK_STK_SIZE-1],
8
);
OSStart();
//開始運(yùn)行ucos
}
void
TaskOne(void*p_arg)
{
intx=0;
p_arg=p_arg;
//無用,僅為消除編譯器報(bào)警
while(1)
//任務(wù)體,總是死循環(huán)
{
x++;
if(x==4)
{
OSTaskDel(7);
//優(yōu)先級(jí)代表任務(wù)
printf("TaskOne:我刪除了TaskTwo!\n");
//打印
}
if(x==8)
{
OSTaskDel(8);
//優(yōu)先級(jí)代表任務(wù)
printf("TaskOne:我刪除了TaskThree!\n");
//打印
}
printf("TaskOne:我在運(yùn)行!\n");
//打印
OSTimeDlyHMSM(0,0,1,0);
//延時(shí)0小時(shí)0分1秒0毫秒
}
}void
TaskTwo(void*p_arg)
{
p_arg=p_arg;
//無用,僅為消除編譯器報(bào)警
while(1)
//任務(wù)體,總是死循環(huán)
{
printf("
TaskTwo:運(yùn)行中我也!\n");
//打印
OSTimeDlyHMSM(0,0,1,0);
//延時(shí)0小時(shí)0分2秒0毫秒
}
}void
TaskThree(void*p_arg)
{
p_arg=p_arg;
//無用,僅為消除編譯器報(bào)警
while(1)
//任務(wù)體,總是死循環(huán)
{
printf("
TaskThree:我還在!\n");
//打印
OSTimeDlyHMSM(0,0,2,0);
//延時(shí)0小時(shí)0分2秒0毫秒
}
}
//***********************************************************************************
運(yùn)行結(jié)果如下圖:
OSTaskDel()內(nèi)核分析:
執(zhí)行OSTaskDel()后,系統(tǒng)將該任務(wù)從任務(wù)控制塊鏈表中刪除:
1.先從就緒表中刪除:
OSRdyTbl[ptcb->OSTCBY]&=~ptcb->OSTCBBitX{
/*Maketasknotready
*/
OSRdyGrp&=~ptcb->OSTCBBitY;
2.然后從事件等待表中刪除:
pevent=ptcb->OSTCBEventPtr;
if(pevent!=(OS_EVENT*)0){
/*Iftaskiswaitingonevent
*/
if((pevent->OSEventTbl[ptcb->OSTCBY]&=~ptcb->OSTCBBitX)==0){/*...removetaskfrom*/
pevent->OSEventGrp&=~ptcb->OSTCBBitY;
/*...eventctrlblock*/
}
}
3.再從事件等待表中刪除:
pnode=ptcb->OSTCBFlagNode;
if(pnode!=(OS_FLAG_NODE*)0){
/*Iftaskiswaitingoneventflag
*/
OS_FlagUnlink(pnode);
/*Removefromwaitlist
*/
}
4.最后把任務(wù)從任務(wù)控制塊鏈表中刪除:
OSTCBPrioTbl[prio]=(OS_TCB*)0;
/*Clearoldpriorityentry
*/
if(ptcb->OSTCBPrev==(OS_TCB*)0){
/*RemovefromTCBchain
*/
ptcb->OSTCBNext->OSTCBPrev=(OS_TCB*)0;
OSTCBList
=ptcb->OSTCBNext;
}else{
ptcb->OSTCBPrev->OSTCBNext=ptcb->OSTCBNext;
ptcb->OSTCBNext->OSTCBPrev=ptcb->OSTCBPrev;
}
ptcb->OSTCBNext=OSTCBFreeList;
/*ReturnTCBtofreeTCBlist
*/
OSTCBFreeList
=ptcb;
其實(shí)這樣直接刪除任務(wù)是不對(duì)的,因?yàn)榭赡苣硞€(gè)任務(wù)還占有資源時(shí),你就把它刪除了,這個(gè)資源得不到釋放而丟失,這對(duì)操作系統(tǒng)來說是不行的。所以在刪除之前,應(yīng)該先提出申請(qǐng),如果系統(tǒng)同意了,才能把它刪除。測(cè)試程序如下:
//***********************************************************************************
#include<includes.h>#define
TASK_STK_SIZE
128
//定義任務(wù)堆棧的大小OS_STK
TaskOneStack[TASK_STK_SIZE];
//為任務(wù)TaskOne建立一個(gè)堆棧
OS_STK
TaskTwoStack[TASK_STK_SIZE];
//為任務(wù)TaskTwo建立一個(gè)堆棧
OS_STK
TaskThreeStack[TASK_STK_SIZE];
//為任務(wù)TaskTwo建立一個(gè)堆棧voidTaskOne(void*p_arg);
voidTaskTwo(void*p_arg);
voidTaskThree(void*p_arg);voidmain(void)
{
OSInit();
//初始化ucos
//建立任務(wù)TaskOne,無數(shù)據(jù)區(qū)指針,
堆棧指針,
優(yōu)先級(jí)6
OSTaskCreate(TaskOne,
0
,&TaskOneStack[TASK_STK_SIZE-1],
6
);
//建立任務(wù)TaskTwo,無數(shù)據(jù)區(qū)指針,
堆棧指針,
優(yōu)先級(jí)7
OSTaskCreate(TaskTwo,
0
,&TaskTwoStack[TASK_STK_SIZE-1],
7
);
//建立任務(wù)TaskThree,無數(shù)據(jù)區(qū)指針,
堆棧指針,
優(yōu)先級(jí)8
OSTaskCreate(TaskThree,
0
,&TaskThreeStack[TASK_STK_SIZE-1],
8
);
OSStart();
//開始運(yùn)行ucos
}
void
TaskOne(void*p_arg)
{
intx=0;
p_arg=p_arg;
//無用,僅為消除編譯器報(bào)警
while(1)
//任務(wù)體,總是死循環(huán)
{
x++;
if(x==4)
{
printf("TaskOne:我要求刪除TaskTwo!\n");
//打印
if(OSTaskDelReq(7)==OS_NO_ERR)
{
OSTaskDel(7);
//優(yōu)先級(jí)代表任務(wù)
printf("TaskOne:我刪除了TaskTwo!\n");
//打印
}
else
{
printf("TaskOne:我現(xiàn)在還不能刪除TaskTwo!\n");
//打印
}
}
if(x==8)
{
printf("TaskOne:我要求刪除TaskThree!\n");
//打印
if(OSTaskDelReq(8)==OS_NO_ERR)
{
OSTaskDel(8);
//優(yōu)先級(jí)代表任務(wù)
printf("TaskOne:我刪除了TaskThree!\n");
//打印
}
else
{
printf("TaskOne:我現(xiàn)在還不能刪除TaskThree!\n");
//打印
}
}
if(x==10)
{
printf("TaskOne:我要求刪除自己!\n");
//打印
if(OSTaskDelReq(6)==OS_NO_ERR)
//刪除自己還可以用OS_PRIO_SELF作為參數(shù)
{
OSTaskDel(6);
//優(yōu)先級(jí)代表任務(wù)
printf("TaskOne:我刪除了我自己!\n");
//打印
}
else
{
printf("TaskOne:沒人聽得見我說話了……!\n");
//打印
}
}
printf("TaskOne:我在運(yùn)行!\n");
//打印
OSTimeDlyHMSM(0,0,1,0);
//延時(shí)0小時(shí)0分1秒0毫秒
}
}void
TaskTwo(void*p_arg)
{
p_arg=p_arg;
//無用,僅為消除編譯器報(bào)警
while(1)
//任務(wù)體,總是死循環(huán)
{
printf("
TaskTwo:運(yùn)行中我也!\n");
//打印
OSTimeDlyHMSM(0,0,1,0);
//延時(shí)0小時(shí)0分2秒0毫秒
}
}void
TaskThree(void*p_arg)
{
p_arg=p_arg;
//無用,僅為消除編譯器報(bào)警
while(1)
//任務(wù)體,總是死循環(huán)
{
printf("
TaskThree:我思故我在!\n");
//打印
OSTimeDlyHMSM(0,0,2,0);
//延時(shí)0小時(shí)0分2秒0毫秒
}
}
//***********************************************************************************結(jié)果如下圖:
由于此程序中每個(gè)任務(wù)未用到資源,所以沒出現(xiàn)刪除請(qǐng)求被拒絕的情況。OSTaskDelReq()內(nèi)核分析:OSTaskDelReq()查看該任務(wù)的各種情況,如果遇到某種刪除不適情況,將其返回:INT8U
OSTaskDelReq(INT8Uprio)
{
#ifOS_CRITICAL_METHOD==3
/*AllocatestorageforCPUstatusregister
*/
OS_CPU_SR
cpu_sr;
#endif
BOOLEAN
stat;
INT8U
err;
OS_TCB
*ptcb;
#ifOS_ARG_CHK_EN>0
if(prio==OS_IDLE_PRIO){
/*Notallowedtodeleteidletask
*/
return(OS_TASK_DEL_IDLE);
}
if(prio>=OS_LOWEST_PRIO&&prio!=OS_PRIO_SELF){
/*Taskpriorityvalid?
*/
return(OS_PRIO_INVALID);
}
#endif
if(prio==OS_PRIO_SELF){
/*Seeifataskisrequestingto...
*/
OS_ENTER_CRITICAL();
/*...thistasktodeleteitself
*/
stat=OSTCBCur->OSTCBDelReq;
/*Returnrequeststatustocaller
*/
OS_EXIT_CRITICAL();
return(stat);
}
OS_ENTER_CRITICAL();
ptcb=OSTCBPrioTbl[prio];
if(ptcb!=(OS_TCB*)0){
/*Tasktodeletemustexist
*/
ptcb->OSTCBDelReq=OS_TASK_DEL_REQ;
/*SetflagindicatingtasktobeDEL.*/
err
=OS_NO_ERR;
}else{
err
=OS_TASK_NOT_EXIST;
/*Taskmustbedeleted
*/
}
OS_EXIT_CRITICAL();
return(err);
}
#endifucos任務(wù)的掛起和恢復(fù)
任務(wù)的掛起OSTaskSuspend()是將一個(gè)就緒任務(wù)轉(zhuǎn)換為等待任務(wù),任務(wù)的恢復(fù)是將一個(gè)等待任務(wù)。做個(gè)程序?qū)嶒?yàn)下:
//***********************************************************************************
#include<includes.h>#define
TASK_STK_SIZE
128
//定義任務(wù)堆棧的大小OS_STK
TaskOneStack[TASK_STK_SIZE];
//為任務(wù)TaskOne建立一個(gè)堆棧
OS_STK
TaskTwoStack[TASK_STK_SIZE];
//為任務(wù)TaskTwo建立一個(gè)堆棧voidTaskOne(void*p_arg);
voidTaskTwo(void*p_arg);voidmain(void)
{
OSInit();
//初始化ucos
//建立任務(wù)TaskOne,無數(shù)據(jù)區(qū)指針,
堆棧指針,
優(yōu)先級(jí)6
OSTaskCreate(TaskOne,
0
,&TaskOneStack[TASK_STK_SIZE-1],
6
);
//建立任務(wù)TaskTwo,無數(shù)據(jù)區(qū)指針,
堆棧指針,
優(yōu)先級(jí)7
OSTaskCreate(TaskTwo,
0
,&TaskTwoStack[TASK_STK_SIZE-1],
7
);
OSStart();
//開始運(yùn)行ucos
}
void
TaskOne(void*p_arg)
{
intx=0;
p_arg=p_arg;
//無用,僅為消除編譯器報(bào)警
while(1)
//任務(wù)體,總是死循環(huán)
{
x++;
if(x==4)
{
if(OSTaskSuspend(7)==OS_NO_ERR)
printf("TaskOne:我掛起了TaskTwo!\n");
//打印
else
printf("TaskOne:我沒能掛起TaskTwo!\n");
//打印
}
if(x==8)
{
if(OSTaskResume(7)==OS_NO_ERR)
printf("TaskOne:我恢復(fù)了TaskTwo!\n");
//打印
else
printf("TaskOne:我沒能恢復(fù)TaskTwo!\n");
//打印
}
printf("TaskOne:我在運(yùn)行!\n");
//打印
OSTimeDlyHMSM(0,0,1,0);
//延時(shí)0小時(shí)0分1秒0毫秒
}
}void
TaskTwo(void*p_arg)
{
p_arg=p_arg;
//無用,僅為消除編譯器報(bào)警
while(1)
//任務(wù)體,總是死循環(huán)
{
printf("
TaskTwo:我在運(yùn)行!\n");
//打印
OSTimeDlyHMSM(0,0,1,0);
//延時(shí)0小時(shí)0分2秒0毫秒
}
}
//***********************************************************************************運(yùn)行結(jié)果如下:
內(nèi)核分析:
1.OSTaskSuspend(X)將優(yōu)先級(jí)為X的任務(wù)移出就緒表,并將此任務(wù)的狀態(tài)設(shè)置為掛起狀態(tài):
y
=ptcb->OSTCBY;
OSRdyTbl[y]&=~ptcb->OSTCBBitX;
/*Maketasknotready
*/
if(OSRdyTbl[y]==0){
OSRdyGrp&=~ptcb->OSTCBBitY;
}
ptcb->OSTCBStat|=OS_STAT_SUSPEND;
/*Statusoftaskis'SUSPENDED'
*/
2.OSTaskResume()將任務(wù)恢復(fù)(即取消掛起狀態(tài)),如果該任務(wù)不在延時(shí),那么放入就緒表中:
if(((ptcb->OSTCBStat&=~OS_STAT_SUSPEND)==OS_STAT_RDY)&&
/*Removesuspension
*/
(ptcb->OSTCBDly
==0)){
/*Mustnotbedelayed
*/
OSRdyGrp
|=ptcb->OSTCBBitY;
/*Maketaskreadytorun
*/
OSRdyTbl[ptcb->OSTCBY]|=ptcb->OSTCBBitX;
可以掛起當(dāng)前任務(wù),而且方便起見可以用OS_PRIO_SELF作為優(yōu)先級(jí)參數(shù)。ucos初始化和啟動(dòng)
一、ucos的初始化:OSInit()
在使用ucos的所有服務(wù)之前,必須調(diào)用OSInit(),對(duì)ucos自身的運(yùn)行環(huán)境進(jìn)行初始化。OSInit()運(yùn)行如下函數(shù):1.OS_InitMisc()
初始化一些全局變量:
OSTime
=0L
系統(tǒng)當(dāng)前時(shí)間(節(jié)拍數(shù))
OSIntNesting
=0
中斷嵌套的層數(shù)
OSLockNesting=0
調(diào)用OSSchededLock的嵌套層數(shù)
OSTaskCtr
=0
已建立的任務(wù)數(shù)
OSRunning
=FALSE
判斷系統(tǒng)是否正在運(yùn)行的標(biāo)志
OSCtxSwCtr
=0
上下文切換的次數(shù)
OSIdleCtr
=0L
空閑任務(wù)計(jì)數(shù)器
OSIdleCtrRun
=0L
空閑任務(wù)每秒的計(jì)數(shù)值
OSIdleCtrMax
=0L
空閑任務(wù)每秒計(jì)數(shù)的最大值
OSStatRdy
=FALSE
統(tǒng)計(jì)任務(wù)是否就緒2.OS_InitRdyList()
將就緒表及相關(guān)變量清03.OS_InitTCBList()
建立任務(wù)控制塊TCB鏈表,OSTCBList用于指向這個(gè)鏈表,鏈表中的每個(gè)結(jié)點(diǎn)存放每個(gè)任務(wù)的信息(優(yōu)先級(jí)、堆棧指針等)。
OSTCBPrioTbl[]是一個(gè)指針數(shù)組,指向每個(gè)任務(wù)結(jié)點(diǎn),方便快速定位。
如下圖:
4.OS_InitEventList()
建立事件控制塊ECB鏈表,鏈表中的每個(gè)結(jié)點(diǎn)存放每個(gè)事件的類型(信號(hào)量、互斥量等),計(jì)數(shù)、等待任務(wù)表等。
5.OS_FlagInit
事件標(biāo)志初始化6.OS_MemInit
內(nèi)存初始化
7.OS_QInit
郵箱初始化
8.OS_InitTaskIdle
建立空閑任務(wù),該任務(wù)必須建立,即系統(tǒng)必須至少有一個(gè)任務(wù)運(yùn)行,該任務(wù)只做簡單的計(jì)數(shù)工作。9.OS_InitTaskStat
建立統(tǒng)計(jì)任務(wù),可選(OS_TASK_STAT_EN>0),用于計(jì)算當(dāng)前CPU利用率。*
OSIdleCtr
*
CPUUsage(%)=100*(
1
-
------------
)
*
OSIdleCtrMax
二、多任務(wù)的啟動(dòng):OSStart()
void
OSStart(void)
{
INT8Uy;
INT8Ux;
if(OSRunning==FALSE){
y
=OSUnMapTbl[OSRdyGrp];
/*Findhighestpriority'staskprioritynumber
*/
x
=OSUnMapTbl[OSRdyTbl[y]];
OSPrioHighRdy=(INT8U)((y<<3)+x);
OSPrioCur
=OSPrioHighRdy;
OSTCBHighRdy
=OSTCBPrioTbl[OSPrioHighRdy];/*Pointtohighestprioritytaskreadytorun
*/
OSTCBCur
=OSTCBHighRdy;
OSStartHighRdy();
/*Executetargetspecificcodetostarttask
*/
}
}
找到優(yōu)先級(jí)最高的就緒任務(wù),標(biāo)記及運(yùn)行。OSStartHighRdy()就是運(yùn)行優(yōu)先級(jí)最高的就緒任務(wù),這個(gè)函數(shù)實(shí)際上是用匯編語言寫的,即用該任務(wù)的內(nèi)容填充CPU寄存器。ucos事件控制塊及處理函數(shù)
一.時(shí)間控制塊ECB的數(shù)據(jù)結(jié)構(gòu)
typedefstruct{
INT8U
OSEventType;
/*Typeofeventcontrolblock(seeOS_EVENT_TYPE_???)
*/
INT8U
OSEventGrp;
/*Groupcorrespondingtotaskswaitingforeventtooccur
*/
INT16U
OSEventCnt;
/*SemaphoreCount(notusedifotherEVENTtype)
*/
void
*OSEventPtr;
/*Pointertomessageorqueuestructure
*/
INT8U
OSEventTbl[OS_EVENT_TBL_SIZE];/*Listoftaskswaitingforeventtooccur
*/
}OS_EVENT;.OSEventType
ECB類型
有以下幾種:
#define
OS_EVENT_TYPE_UNUSED
0
#define
OS_EVENT_TYPE_MBOX
1
#define
OS_EVENT_TYPE_Q
2
#define
OS_EVENT_TYPE_SEM
3
#define
OS_EVENT_TYPE_MUTEX
4
#define
OS_EVENT_TYPE_FLAG
5
.OSEventCnt
信號(hào)量計(jì)數(shù)
表示最大空共享的數(shù)目
.*OSEventPtr
用于消息和隊(duì)列
.OSEventTbl[]和.OSEventGrp
分別與管理任務(wù)的OSRdyTbl[]和OSRdyGrp類似,OSEventTbl[]用于放置該事件的所有等待任務(wù)。原理圖如下:
二、將任務(wù)置于等待事件的任務(wù)列表
pevent->OSEventGrp|=OSMapTbl[prio>>3];
pevent->OSEventTbl[prio>>3]|=OSMapTbl[prio&0x07];三、從等待任務(wù)列表中刪除一個(gè)任務(wù)
if((pevent->OSEventTbl[prio>>3]&=~OSMapTbl[prio&0x07])==0){
pevent->OSEventGrp&=~OSMapTbl[prio>>3];
}
四、在等待任務(wù)列表中查找最高優(yōu)先級(jí)的任務(wù)
y=OSUnMapTbl[pevent->OSEventGrp];
x=OSUnMapTbl[pevent->OSEventTbl[y]];
prio=(y<<3)+x;
五、空余事件控制塊鏈表
在調(diào)用OSInit()時(shí),所有事件控制塊被鏈接成一個(gè)單向鏈表——空閑事件控制塊鏈表。每當(dāng)建立一個(gè)信號(hào)量、郵箱或者消息隊(duì)列時(shí),就從該鏈表中取出一個(gè)空閑事件控制塊,并對(duì)它進(jìn)行初始化。刪除時(shí),可將事件控制塊放回到空余事件控制塊鏈表中。
六、初始化一個(gè)事件控制塊,OS_EventWaitListInit()
就是將該ECB中的.OSEventTbl[]和.OSEventGrp全部清0
七、使一個(gè)任務(wù)進(jìn)入就緒態(tài),OS_EventTaskRdy()
先從等待任務(wù)列表中刪除這個(gè)任務(wù):
if((pevent->OSEventTbl[y]&=~bitx)==0x00){
/*Removethistaskfromthewaitinglist
*/
pevent->OSEventGrp&=~bity;
/*Clrgroupbitifthiswasonlytaskpending
*/
}
再將這個(gè)任務(wù)置于任務(wù)就緒表:
if(ptcb->OSTCBStat==OS_STAT_RDY){
/*Seeiftaskisready(couldbesusp'd)
*/
OSRdyGrp
|=
bity;
/*Puttaskinthereadytorunlist
*/
OSRdyTbl[y]
|=
bitx;
}
八、使一個(gè)任務(wù)進(jìn)入等待某事件發(fā)生狀態(tài),OS_EventTaskWait()
將任務(wù)移出就緒表
if((OSRdyTbl[OSTCBCur->OSTCBY]&=~OSTCBCur->OSTCBBitX)==0x00){
/*Tasknolongerready
*/
OSRdyGrp&=~OSTCBCur->OSTCBBitY;
/*Cleareventgrpbitifthiswasonlytaskpending
*/
}
將任務(wù)進(jìn)入該事件的等待列表
pevent->OSEventTbl[OSTCBCur->OSTCBY]|=OSTCBCur->OSTCBBitX;
/*Puttaskinwaitinglist
*/
pevent->OSEventGrp
|=OSTCBCur->OSTCBBitY;
有了這些基本知識(shí),后面的事件處理就簡單多了ucos
信號(hào)量
信號(hào)量是一類事件,用來標(biāo)志資源被占用的情況,當(dāng)任務(wù)在使用資源之前,應(yīng)對(duì)信號(hào)量進(jìn)行查詢,以了解資源的被占用情況,從而決定下一步行為。
如果沒有信號(hào)量,任務(wù)對(duì)資源的使用將發(fā)生混亂。下面的程序中兩個(gè)任務(wù)依靠一個(gè)字符變量card傳遞信息,因?yàn)闆]有使用信號(hào)量,所以信息沒有被正確的接收。//***********************************************************************************
#include<includes.h>#define
TASK_STK_SIZE
128
//定義任務(wù)堆棧的大小OS_STK
TaskOneStack[TASK_STK_SIZE];
//為任務(wù)TaskOne建立一個(gè)堆棧
OS_STK
TaskTwoStack[TASK_STK_SIZE];
//為任務(wù)TaskTwo建立一個(gè)堆棧voidTaskOne(void*p_arg);
voidTaskTwo(void*p_arg);charcard;//TaskOne每次利用card向TaskTwo發(fā)一個(gè)字符,card作為共享資源voidmain(void)
{
OSInit();
//初始化ucos
//建立任務(wù)TaskOne,無數(shù)據(jù)區(qū)指針,
堆棧指針,
優(yōu)先級(jí)6
OSTaskCreate(TaskOne,
0
,&TaskOneStack[TASK_STK_SIZE-1],
6
);
//建立任務(wù)TaskTwo,無數(shù)據(jù)區(qū)指針,
堆棧指針,
優(yōu)先級(jí)7
OSTaskCreate(TaskTwo,
0
,&TaskTwoStack[TASK_STK_SIZE-1],
7
);
OSStart();
//開始運(yùn)行ucos
}
void
TaskOne(void*p_arg)
{
charstr[]="Iloveyou!";
char*p=str;
p_arg=p_arg;
//無用,僅為消除編譯器報(bào)警
while(1)
//任務(wù)體,總是死循環(huán)
{
card=*p;
if(card!='\0')
{
printf("TaskOne:%c
\n",card);
//打印
p++;
}
OSTimeDlyHMSM(0,0,1,0);
//延時(shí)0小時(shí)0分1秒0毫秒
}
}void
TaskTwo(void*p_arg)
{
p_arg=p_arg;
//無用,僅為消除編譯器報(bào)警
while(1)
//任務(wù)體,總是死循環(huán)
{
if(card!='\0')
printf("
TaskTwo:%c
\n",card);
OSTimeDlyHMSM(0,0,1,345);
//延時(shí)0小時(shí)0分1秒345毫秒
}
}
//***********************************************************************************運(yùn)行結(jié)果如下:
TaskOne發(fā)出:"Iloveyou!",但是TaskTwo收到的是"Ilveou!"。
為了克服這個(gè)占用資源混亂的問題,這里使用信號(hào)量,它就像一把鑰匙,只有拿到鑰匙的人才能使用相應(yīng)的資源,使用完資源后需要后,需要釋放這把鑰匙給別人用。鑰匙的數(shù)量(信號(hào)量計(jì)數(shù))可以設(shè)定,這里設(shè)置為1,即二值信號(hào)量,任一時(shí)刻只能有一個(gè)任務(wù)持有該鑰匙。下面是這個(gè)實(shí)驗(yàn)程序:
//***********************************************************************************
#include<includes.h>#define
TASK_STK_SIZE
128
//定義任務(wù)堆棧的大小OS_STK
TaskOneStack[TASK_STK_SIZE];
//為任務(wù)TaskOne建立一個(gè)堆棧
OS_STK
TaskTwoStack[TASK_STK_SIZE];
//為任務(wù)TaskTwo建立一個(gè)堆棧voidTaskOne(void*p_arg);
voidTaskTwo(void*p_arg);OS_EVENT*key;
//事件控制塊指針
charcard;
//TaskOne每次利用card向TaskTwo發(fā)一個(gè)字符,card作為共享資源
charerr;
//錯(cuò)誤信息voidmain(void)
{
OSInit();
//初始化ucos
//建立任務(wù)TaskOne,無數(shù)據(jù)區(qū)指針,
堆棧指針,
優(yōu)先級(jí)6
OSTaskCreate(TaskOne,
0
,&TaskOneStack[TASK_STK_SIZE-1],
6
);
//建立任務(wù)TaskTwo,無數(shù)據(jù)區(qū)指針,
堆棧指針,
優(yōu)先級(jí)7
OSTaskCreate(TaskTwo,
0
,&TaskTwoStack[TASK_STK_SIZE-1],
7
);
key=OSSemCreate(1);
//建立一個(gè)信號(hào)量,允許共享數(shù)為1,該控制塊的地址給key
OSStart();
//開始運(yùn)行ucos
}
void
TaskOne(void*p_arg)
{
charstr[]="Iloveyou!";
char*p=str;
p_arg=p_arg;
//無用,僅為消除編譯器報(bào)警
while(1)
//任務(wù)體,總是死循環(huán)
{
OSSemPend(key,0,&err);
//申請(qǐng)信號(hào)量key,延時(shí)為無限長(0)
card=*p;
if(card!='\0')
{
printf("TaskOne:%c
\n",card);
//打印
p++;
}
OSTimeDlyHMSM(0,0,1,0);
//延時(shí)0小時(shí)0分1秒0毫秒
}
}void
TaskTwo(void*p_arg)
{
p_arg=p_arg;
//無用,僅為消除編譯器報(bào)警
while(1)
//任務(wù)體,總是死循環(huán)
{
if(card!='\0')
printf("
TaskTwo:%c
\n",card);
OSSemPost(key);
//釋放信號(hào)量key
OSTimeDlyHMSM(0,0,1,345);
//延時(shí)0小時(shí)0分1秒345毫秒
}
}
//***********************************************************************************運(yùn)行結(jié)果如下圖:
可見,TaskOne要說的話通過全局字符變量card順利傳遞給TaskTwo。
內(nèi)核分析:
1.OSSemCreate()先將空余事件控制塊鏈表的指針向后推進(jìn)一結(jié)
if(OSEventFreeList!=(OS_EVENT*)0){
/*SeeifpooloffreeECBpoolwasempty
*/
OSEventFreeList=(OS_EVENT*)OSEventFreeList->OSEventPtr;
}在將這個(gè)留出結(jié)點(diǎn)用所創(chuàng)造的信號(hào)量去填充
pevent->OSEventType=OS_EVENT_TYPE_SEM;
pevent->OSEventCnt
=cnt;
/*Setsemaphorevalue
*/
pevent->OSEventPtr
=(void*)0;
/*UnlinkfromECBfreelist
*/
OS_EventWaitListInit(pevent);
/*Initializeto'nobodywaiting'onsem.
*/
2.等待一個(gè)信號(hào)量,OSSemPend()將pevent->OSEventCnt減一,表示已經(jīng)有一個(gè)任務(wù)去占用它:
pevent->OSEventCnt--;任務(wù)狀態(tài)設(shè)置:OSTCBCur->OSTCBStat|=OS_STAT_SEM;將任務(wù)置于該ECB的等待列表
OS_EventTaskWait(pevent);
/*Suspendtaskuntileventortimeoutoccurs
*/
3.發(fā)出一個(gè)信號(hào)量,OSSemPost()使當(dāng)前任務(wù)移出該ECB的等待列表,并進(jìn)入就緒態(tài):OS_EventTaskRdy()讓出信號(hào)量
:pevent->OSEventCnt++;ucos移植前的準(zhǔn)備——自己寫一個(gè)調(diào)度的系統(tǒng)(一)2011-09-1710:24現(xiàn)在想把ucos的移植經(jīng)驗(yàn)分享給大家,如果你沒有基礎(chǔ),建議先別急于移植,因?yàn)槟悴幻靼渍{(diào)度的原理,即使是模仿別人的方法,如果寫錯(cuò)一條匯編指令,系統(tǒng)也會(huì)崩潰,你也始終找不到頭緒。
所以在移植之前,1.你要會(huì)使用ucos,即在ucos下編程。2.熟悉調(diào)度的原理,能夠獨(dú)立編寫任務(wù)調(diào)度程序。
只有會(huì)這兩點(diǎn),移植ucos才可能。
前面已經(jīng)說了ucos下編程(雖然消息、郵箱等沒說,相信入門后
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 2024年春七年級(jí)語文下冊(cè) 第三單元 12 賣油翁說課稿 新人教版
- 12古詩三首《己亥雜詩》說課稿-2024-2025學(xué)年語文五年級(jí)上冊(cè)統(tǒng)編版
- 15 分享真快樂(說課稿)2023-2024學(xué)年統(tǒng)編版道德與法治 一年級(jí)下冊(cè)001
- 2025裝修工程泥工承包合同
- 7讓弦發(fā)出高低不同的聲音 說課稿-2024-2025學(xué)年科學(xué)四年級(jí)上冊(cè)教科版
- 2024-2025學(xué)年高中歷史 專題四 王安石變法 一 積貧積弱的北宋教學(xué)說課稿 人民版選修1
- 14 請(qǐng)幫我一下吧 第一課時(shí) 說課稿-2023-2024學(xué)年道德與法治一年級(jí)下冊(cè)統(tǒng)編版
- 6我們神圣的國土 第1課時(shí)(說課稿)-部編版道德與法治五年級(jí)上冊(cè)
- 2023八年級(jí)英語下冊(cè) Module 1 Feelings and impressions Unit 2 I feel nervous when I speak Chinese第三課時(shí)說課稿 (新版)外研版
- 2024-2025學(xué)年新教材高中語文 第二單元 6.2 文氏外孫入村收麥說課稿(3)部編版必修上冊(cè)
- 科技論文圖表等規(guī)范表達(dá)
- 高考寫作指導(dǎo)議論文標(biāo)準(zhǔn)語段寫作課件32張
- 2021年普通高等學(xué)校招生全國英語統(tǒng)一考試模擬演練八省聯(lián)考解析
- 華能火力發(fā)電機(jī)組節(jié)能降耗技術(shù)導(dǎo)則(2023年版)
- 基礎(chǔ)知識(shí)3500個(gè)常用漢字附拼音
- 企業(yè)易制毒化學(xué)品管理培訓(xùn)
- JJF(紡織)072-2018紡織滾筒式烘干機(jī)校準(zhǔn)規(guī)范
- 北京故宮作文600字
- 羊水栓塞的應(yīng)急預(yù)案演練腳本
- 物業(yè)保潔及餐飲服務(wù)項(xiàng)目方案
- (新版教材)粵教粵科版六年級(jí)下冊(cè)科學(xué)全冊(cè)課時(shí)練(同步練習(xí))
評(píng)論
0/150
提交評(píng)論