ucOSII范例分析01匯總課件_第1頁
ucOSII范例分析01匯總課件_第2頁
ucOSII范例分析01匯總課件_第3頁
ucOSII范例分析01匯總課件_第4頁
ucOSII范例分析01匯總課件_第5頁
已閱讀5頁,還剩191頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

嵌入式操作系統(tǒng)ucOS-II分析嵌入式操作系統(tǒng)ucOS-II分析1ucOS-II應(yīng)用程序基本結(jié)構(gòu)voidtask(void*pdata){INT8U

err;InitTimer();//可選For(;;){

//你的應(yīng)用程序代碼

……..

OSTimeDly(1);//可選}}ucOS-II應(yīng)用程序基本結(jié)構(gòu)voidtask(voi2一些重要的ucOS-IIAPI1)任務(wù)類2)消息類3)同步類4)時間類5)臨界區(qū)與事件類任務(wù)類和時間類是必須要首先掌握的兩種類型的API一些重要的ucOS-IIAPI1)任務(wù)類任務(wù)類和時間類是必31)OSTaskCreate函數(shù)

這個函數(shù)應(yīng)該至少在main函數(shù)內(nèi)調(diào)用一次,在OSInit函數(shù)調(diào)用之后調(diào)用,以創(chuàng)建一個任務(wù)。系統(tǒng)首先從TCB空閑列表內(nèi)申請一個空的TCB指針,然后根據(jù)用戶給出的參數(shù)初始化任務(wù)堆棧,并在內(nèi)部的任務(wù)就緒表內(nèi)標記該任務(wù)為就緒狀態(tài)。最后返回,這樣一個任務(wù)就創(chuàng)建成功了。1)OSTaskCreate函數(shù)這個函數(shù)應(yīng)該至少在main42)OSTaskSuspend函數(shù)

將指定的任務(wù)掛起。如果掛起的是當前任務(wù),會引發(fā)系統(tǒng)執(zhí)行任務(wù)切換先導函數(shù)OSShed來進行一次任務(wù)切換。這個函數(shù)只有一個優(yōu)先級參數(shù),在系統(tǒng)內(nèi)部,優(yōu)先級除了表示一個任務(wù)執(zhí)行的先后次序外,還起著區(qū)分每一個任務(wù)的作用,即優(yōu)先級也是任務(wù)的ID。所以uCOS-II不允許出現(xiàn)相同優(yōu)先級的任務(wù)。2)OSTaskSuspend函數(shù)將指定的任務(wù)掛起。如果掛53)OSTaskResume函數(shù)

將指定的已經(jīng)掛起的任務(wù)恢復成就緒狀態(tài)。如果恢復任務(wù)的優(yōu)先級高于當前任務(wù),那么還會引發(fā)一次任務(wù)切換。參數(shù)類似OSTaskSuspend函數(shù),為指定任務(wù)的優(yōu)先級。需要特別說明是,本函數(shù)并不要求和OSTaskSuspend函數(shù)成對使用。3)OSTaskResume函數(shù)將指定的已經(jīng)掛起的任務(wù)恢復64)OS_ENTER_CRITICAL宏

分析一下OS_CPU.H文件,它涉及特定CPU的實現(xiàn)。一般都被替換為一條或者幾條嵌入式匯編代碼。其實,它就是關(guān)中斷。只要任務(wù)不主動放棄CPU使用權(quán),別的任務(wù)就沒有占用CPU的機會,這個任務(wù)就是獨占了。進入臨界區(qū)后,這個應(yīng)宏盡量少用,它會破壞系統(tǒng)的一些服務(wù),尤其是時間服務(wù)。并使系統(tǒng)對外界響應(yīng)性能降低。4)OS_ENTER_CRITICAL宏分析一下OS_CP75)OS_EXIT_CRITICAL宏

與OS_ENTER_CRITICAL配套使用的一個宏,在系統(tǒng)手冊說明里它是退出臨界區(qū),其實就是重新開中斷。它必須和OS_ENTER_CRITICAL成對出現(xiàn),否則會帶來意想不到的后果,如系統(tǒng)會崩潰。我們應(yīng)盡量少用這兩個宏調(diào)用,因為他們的確會破壞系統(tǒng)的多任務(wù)性能。5)OS_EXIT_CRITICAL宏與OS_ENTER_86)OSTimeDly函數(shù)

這是調(diào)用最多的一個函數(shù),它的功能是先掛起當前任務(wù),然后進行任務(wù)切換,在指定的時間到來之后,將當前任務(wù)恢復為就緒狀態(tài),但是并不一定運行,如果恢復后是優(yōu)先級最高的就緒任務(wù)話,那么就運行之??梢詫⑷蝿?wù)延時一定時間后再執(zhí)行它,依靠時鐘機制進行任務(wù)切換,暫時放棄CPU的使用權(quán),但多任務(wù)性能會降低。6)OSTimeDly函數(shù)這是調(diào)用最多的一個函數(shù),它的功能9ucOS-II范例的源碼分析ucOS-II范例的源碼分析10INCLUDES.H

ucOS-II中所有的*.C文件都包括了以下定義:#include"includes.h“唯一的缺點是INCLUDES.H中許多頭文件在一些*.C文件的編譯中是不需要的。雖然逐個編譯這些文件要花費額外的時間,但代碼的可移植性卻增加了。

INCLUDES.HucOS-II中所有的*.C文件都11不依賴于編譯的數(shù)據(jù)類型可移植型數(shù)據(jù)類型的程序TypedefunsignedcharBOOLEAN;TypedefunsignedcharINT8U;TypedefsignedcharINT8S;TypedefunsignedintINT16U;TypedefsignedintINT16S;TypedefunsignedlongINT32U;TypedefsignedlongINT32S;TypedeffloatFP32;TypedefdoubleFP64;#defineBYTEINT8S-----------|#defineUBYTEINT8U-----------|#defineWORDINT16S------------|ucos->ucosII#defineUWORDINT16U-----------|#defineLONGINT32S-----------|#defineULONGINT32U-----------|不依賴于編譯的數(shù)據(jù)類型可移植型數(shù)據(jù)類型的程序12全局變量定義全局宏的程序#ifdefxxx_GLOBALS#definexxx_EXT#else#definexxx_EXTextern#endif .H文件中每個全局變量都加上了xxx_EXT的前綴。xxx代表模塊的名字。該模塊的.C文件中有以下定義:#definexxx_GLOBALS#include"includes.h"全局變量定義全局宏的程序13uCOS_II.H中有以下定義:#ifdefOS_GLOBALS#defineOS_EXT#else#defineOS_EXTextern#endif

OS_EXTINT32UOSIdleCtr;OS_EXTINT32UOSIdleCtrRun;OS_EXTINT32UOSIdleCtrMax;uCOS_II.H中有以下定義:#ifdefOS_G14uCOS_II.C中有以下定義:#defineOS_GLOBALS#include“includes.h”當編譯器處理uCOS_II.C時,它使uCOS_II.H變成如下所示,因為OS_EXT被設(shè)置為空。編譯器就會將這些全局變量分配到內(nèi)存中。

INT32UOSIdleCtr;INT32UOSIdleCtrRun;INT32UOSIdleCtrMax;uCOS_II.C中有以下定義:#defineOS_G15當編譯器處理其他.C文件時,頭文件變成了如下的樣子,因為OS_GLOBAL沒有定義,所以O(shè)S_EXT被定義為extern。externINT32UOSIdleCtr;externINT32UOSIdleCtrRun;externINT32UOSIdleCtrMax; 在這種情況下,不產(chǎn)生內(nèi)存分配,而任何.C文件都可以使用這些變量。這樣的就只需在.H文件中定義一次就可以了。當編譯器處理其他.C文件時,頭文件變成了如下的樣子,因為OS16OS_ENTER_CRITICAL()和

OS_EXIT_CRITICAL()OS_ENTER_CRITICAL()關(guān)中斷;OS_EXIT_CRITICAL()開中斷。是為了保護臨界段代碼,這些代碼與處理器有關(guān)。宏的定義在OS_CPU.H中。關(guān)中斷會影響中斷延遲,所以要特別小心。用戶還可以用信號量來保護臨界段代碼。OS_ENTER_CRITICAL()和

OS_EXIT17基于PC的服務(wù)PC.C文件和PC.H文件是范例中使用到的一些基于PC的服務(wù)程序。PC.C包括字符顯示,時間度量和其他各種服務(wù)。所有的函數(shù)都以PC_為前綴?;赑C的服務(wù)PC.C文件和PC.H文件是范例中使用18字符顯示PC_DispClrScr() ClearthescreenPC_DispClrLine() Clearasinglerow(orline)PC_DispChar() DisplayasingleASCIIcharacteranywhereonthescreenPC_DispStr() DisplayanASCIIstringanywhereonthescreen字符顯示PC_DispClrScr() Clearth19時間度量用PC的82C54定時器2測試一個函數(shù)的運行花了多少時間。被測的程序代碼放在函數(shù)PC_ElapsedStart()和PC_ElapsedStop()之間來測量。在用這兩個函數(shù)之前,應(yīng)該調(diào)用PC_ElapsedInit()來初始化,它主要是計算運行這兩個函數(shù)本身所附加的的時間。這樣,PC_ElapsedStop()函數(shù)中返回的數(shù)值就是準確的測量結(jié)果了。這兩個函數(shù)都不具備可重入性,不要有多個任務(wù)同時調(diào)用這兩個函數(shù)。時間度量用PC的82C54定時器2測試一個函數(shù)的運行花了多20測量PC_DisplayChar()的執(zhí)行時間(us)測量代碼執(zhí)行時間的程序INT16Utime;

PC_ElapsedInit();..PC_ElapsedStart();PC_DispChar(40,24,‘A’,DISP_FGND_WHITE);time=PC_ElapsedStop();測量PC_DisplayChar()的執(zhí)行時間(us)測量代21應(yīng)用μC/OS-II的范例

用BCIDE(IntegratedDevelopmentEnvironment)編譯通過,在WindowsXP的DOS窗口下編譯運行??蓤?zhí)行代碼在每個范例的OBJ子目錄中。應(yīng)用μC/OS-II的范例用BCIDE(Integ22IDE中編譯選項Codegeneration

Model:LargeOptions:TreatenumsasintsAssumeSSEqualsDS:DefaultformemorymodelAdvancedcodegeneration

Floatingpoint:EmulationInstructionset:80186Options:Generateunderbars

DebuginfoinOBJs

FastfloatingpointIDE中編譯選項Codegeneration

23IDE中編譯選項OptimizationsGlobalregisterallocation

Invariantcodemotion

Inductionvariables

Loopoptimization

Suppressredundantloads

Copypropagation

Deadcodeelimination

Jumpoptimization

In-lineintrinsicfunctionsIDE中編譯選項Optimizations24IDE中編譯選項RegistervariablesAutomaticCommonsubexpressionsOptimizegloballyOptimizeforSpeedIDE中編譯選項Registervariables25例1有13個任務(wù)(包括μC/OS-II的空閑任務(wù)和一個計算CPU利用率的任務(wù))。TaskStart()在函數(shù)main()中建立,功能是建立其它任務(wù)并且在屏幕上顯示如下統(tǒng)計信息:每秒鐘任務(wù)切換次數(shù);CPU利用百分率;寄存器切換次數(shù);目前日期和時間;μC/OS-II的版本號;TaskStart()還檢查是否按下ESC鍵,以決定是否返回到DOS。其余10個任務(wù)基于相同的代碼——Task();每個任務(wù)在屏幕上隨機的位置顯示一個0到9的數(shù)字。例1有13個任務(wù)(包括μC/OS-II的空閑任務(wù)和一個計26main()main()程序從清整個屏幕開始,為的是保證屏幕上不留有以前的DOS下的顯示。用戶在使用任何服務(wù)之前先調(diào)用OSInit()。建立兩個任務(wù):空閑任務(wù)和統(tǒng)計任務(wù),前者在沒有其它任務(wù)處于就緒態(tài)時運行;后者計算CPU的利用率。main()main()程序從清整個屏幕開始,為的是保證屏27main()程序voidmain(void){PC_DispClrScr(DISP_FGND_WHITE+DISP_BGND_BLACK);(1)OSInit(); (2)PC_DOSSaveReturn();/保存當前DOS環(huán)境(3)PC_VectSet(uCOS,OSCtxSw);/設(shè)置CPU寄存器切換(4)RandomSem=OSSemCreate(1);/信號量置為1,在某一時刻只有一個任務(wù)可以調(diào)用隨機數(shù)產(chǎn)生函數(shù)(5)OSTaskCreate(TaskStart,(void*)0,/啟動多任務(wù)OSStart()之前,用戶至少要先建立一個任務(wù)如TaskStart()(void*)&TaskStartStk[TASK_STK_SIZE-1],0);(6)OSStart();/啟動多任務(wù)(7)}main()程序voidmain(void)28OSInit()初始化【在OS_CORE.C中定義】void

OSInit(void)

{

#ifOS_VERSION>=204

OSInitHookBegin();

/系統(tǒng)初始化開始接口函數(shù)

#endif

OS_InitMisc();

/初始化變量

OS_InitRdyList();

/初始化任務(wù)就緒列表

OS_InitTCBList();

/初始化任務(wù)控制塊列表

OS_InitEventList();

/初始化事件控制塊列表

OSInit()初始化【在OS_CORE.C中定義】voi29OSInit()初始化(續(xù))#if(OS_VERSION>=251)&&(OS_FLAG_EN>0)&&(OS_MAX_FLAGS>0)

OS_FlagInit();

/事件標志結(jié)構(gòu)初始化

#endif#if(OS_MEM_EN>0)&&(OS_MAX_MEM_PART>0)

OS_MemInit();

/內(nèi)存管理初始化#endif#if(OS_Q_EN>0)&&(OS_MAX_QS>0)

OS_QInit();

/消息隊列初始化#endifOS_InitTaskIdle();

/創(chuàng)建空閑任務(wù)(無條件)

#ifOS_TASK_STAT_EN>0

OS_InitTaskStat();

/創(chuàng)建統(tǒng)計任務(wù)

#endif#ifOS_VERSION>=204

OSInitHookEnd();

/系統(tǒng)初始化結(jié)束接口函數(shù)#endif#ifOS_VERSION>=270&&OS_DEBUG_EN>0

OSDebugInit();#endif}OSInit()初始化(續(xù))#if(OS_VERSION30OS_InitMisc()初始化變量OSIntNesting

=0;

/清除中斷嵌套計數(shù)器

OSLockNesting=0;

/清除調(diào)度鎖定計數(shù)器

OSTaskCtr

=0;

/任務(wù)數(shù)清零OSRunning

=FALSE;

/系統(tǒng)多任務(wù)沒有執(zhí)行

OSIdleCtr

=0L;

/清除空閑任務(wù)計數(shù)器OSCtxSwCtr

=0;

/清除程序切換計數(shù)器

OS_InitMisc()初始化變量OSIntNestin31OS_InitRdyList()初始化任務(wù)就緒列表static

void

OS_InitRdyList(void)

{

INT8U

i;

INT8U

*prdytbl;

OSRdyGrp

=0x00;

/清除任務(wù)就緒表

prdytbl

=&OSRdyTbl[0];/將OSRdyTbl[]數(shù)組全部初始化0

for(i=0;i<OS_RDY_TBL_SIZE;i++){

*prdytbl++=0x00;

}/把任務(wù)就緒表里面所有的項目全部清零OSPrioCur

=0;/當前運行任務(wù)的優(yōu)先級寄存器清零

OSPrioHighRdy=0;/將處于就緒狀態(tài)的最高優(yōu)先級的任務(wù)寄存器清零OSTCBHighRdy

=(OS_TCB*)0;

/將處于就緒態(tài)的最高優(yōu)先級的任務(wù)控制塊指針寄存器清零

OSTCBCur

=(OS_TCB*)0;/將當前運行任務(wù)的任務(wù)控制塊指針寄存器清零

OSTCBList

=(OS_TCB*)0;/任務(wù)控制塊列表清零for(i=0;i<(OS_LOWEST_PRIO+1);i++){OSTCBPrioTbl[i]=(OS_TCB*)0;}/清除優(yōu)先級列表,這個列表存儲各個優(yōu)先級對應(yīng)的任務(wù)控制塊的地址,系統(tǒng)用它來尋找下一個要運行的任務(wù)地址

}OS_InitRdyList()初始化任務(wù)就緒列表stat32OS_InitTCBList()初始化任務(wù)控制塊列表static

void

OS_InitTCBList(void)

{

INT8U

i;

OS_TCB

*ptcb1;

OS_TCB

*ptcb2;OS_MemClr((INT8U*)&OSTCBTbl[0],

sizeof(OSTCBTbl));

/清除TCB

OS_MemClr((INT8U*)&OSTCBPrioTbl[0],sizeof(OSTCBPrioTbl));

/清除優(yōu)先級表

ptcb1=&OSTCBTbl[0];/任務(wù)控制塊列表的第一個任務(wù)塊地址給變量PTCB1

ptcb2=&OSTCBTbl[1];/任務(wù)控制塊列表的第二個任務(wù)塊地址給變量PTCB2

for(i=0;i<(OS_MAX_TASKS+OS_N_SYS_TASKS-1);i++){

/初始化任務(wù)控制塊列表

ptcb1->OSTCBNext=ptcb2;

#ifOS_TASK_NAME_SIZE>1

ptcb1->OSTCBTaskName[0]='?';

/*Unknownname

*/

ptcb1->OSTCBTaskName[1]=OS_ASCII_NUL;/把前一個任務(wù)控制塊的下一個任務(wù)指針指向下一個任務(wù)控制塊#endif

ptcb1++;

ptcb2++;

}

ptcb1->OSTCBNext=(OS_TCB*)0;

/把最后一個人物控制塊的下個指針清零#ifOS_TASK_NAME_SIZE>1

ptcb1->OSTCBTaskName[0]=‘?’;

/*Unknownname

*/

ptcb1->OSTCBTaskName[1]=OS_ASCII_NUL;

#endif

OSTCBList

=(OS_TCB*)0;

/TCB列表初始化

OSTCBFreeList

=&OSTCBTbl[0];/把第一個任務(wù)控制塊的地址送給空閑任務(wù)控制塊列表

}OS_InitTCBList()初始化任務(wù)控制塊列表stat33建立其它任務(wù)的任務(wù)

TaskStart()

voidTaskStart(void*data){Preventcompilerwarningbyassigning‘data’toitself;DisplaybanneridentifyingthisasEXAMPLE#1;(1)/在屏幕頂端顯示一個標識,說明這是例1。OS_ENTER_CRITICAL();PC_VectSet(0x08,OSTickISR);(2)PC_SetTickRate(200);(3)/關(guān)中斷,以改變中斷向量,讓其指向μC/OS-II的時鐘節(jié)拍處理,然后,改變時鐘節(jié)拍為200HzOS_EXIT_CRITICAL();

建立其它任務(wù)的任務(wù)TaskStart()voidTas34建立其它任務(wù)的任務(wù)

TaskStart()(續(xù))Initializethestatistictaskbycalling‘OSStatInit()’;(4)Create10identicaltasks;/建立10個同樣的任務(wù)

(5)

for(;;){Displaythenumberoftaskscreated;Displaythe%ofCPUused;Displaythenumberoftaskswitchesin1second;DisplayuC/OS-II’sversionnumberIf(keywaspressed){if(keypressedwastheESCAPEkey){PC_DOSReturn();}}Delayfor1Second;}}建立其它任務(wù)的任務(wù)TaskStart()(續(xù))Initia35測試CPU速度voidOSStatInit(void){OSTimeDly(2);/延時兩個時鐘節(jié)拍(1)OS_ENTER_CRITICAL();OSIdleCtr=0L;/32位的計數(shù)器OSIdleCtr被清0,并產(chǎn)生另一個延時,這個延時使OSStatInit()掛起。(2)OS_EXIT_CRITICAL();/uCOS-II執(zhí)行一個無限循環(huán)的空閑任務(wù),不斷的遞增OSIdleCtrOSTimeDly(OS_TICKS_PER_SEC);(3)OS_ENTER_CRITICAL();OSIdleCtrMax=OSIdleCtr;(4)OSStatRdy=TRUE;/μCOS-II將統(tǒng)計CPU的利用率(5)OS_EXIT_CRITICAL();}測試CPU速度voidOSStatInit(void)36在屏幕隨機位置顯示任務(wù)號(0~9)voidTask(void*data){UBYTEx;UBYTEy;UBYTEerr;

for(;;){OSSemPend(RandomSem,0,&err);/獲取信號量RandomSem,同時禁止其他任務(wù)運行這段代碼(1)x=random(80);/獲得一個隨機數(shù)(2)y=random(16);/獲得一個隨機數(shù)OSSemPost(RandomSem);/計算出x和y坐標并釋放信號量(3)PC_DispChar(x,y+5,*(char*)data,DISP_FGND_LIGHT_GRAY); /在計算的坐標處顯示其任務(wù)號(0-9)(4)OSTimeDly(1);/延時一個時鐘節(jié)拍,等待進入下一次循環(huán)(5)}}在屏幕隨機位置顯示任務(wù)號(0~9)voidTask(v37例1的運行結(jié)果例1的運行結(jié)果38例2磁盤文件為\SOFTWARE\uCOS-II\EX2_x86L,它包含9個任務(wù)。加上uCOS-II本身的兩個任務(wù):空閑任務(wù)(idletask)和統(tǒng)計任務(wù),共11個任務(wù)。由main()中的TaskStart()函數(shù)建立任務(wù),功能是建立其他任務(wù)并在屏幕上顯示如下的統(tǒng)計數(shù)據(jù):每秒種任務(wù)切換的次數(shù);CPU利用率的百分比;當前日期和時間;uCOS_II的版本號;使用帶擴展功能的任務(wù)建立函數(shù)OSTaskCreateExt()和uCOS-II的堆棧檢查操作(要使用堆棧檢查操作必須用OSTaskCreateExt()建立任務(wù))。例2磁盤文件為\SOFTWARE\uCOS-II\EX2_x39μC/OS-IIstackchecking

uCOS-II的堆棧檢查功能要求任務(wù)建立時堆棧清零。OSTaskCreateExt()可以執(zhí)行此項操作(設(shè)置選項OS_TASK_OPT_STK_CHK和OS_TASK_OPT_STK_CLR打開此項操作)。OSTaskCreateExt()進行堆棧清零操作是一項很費時的工作,取決于堆棧的大小。執(zhí)行堆棧檢查操作的時候,uCOS-II從棧底向棧頂搜索非0元素(參看上圖),同時用一個計數(shù)器記錄0元素的個數(shù)。μC/OS-IIstackcheckinguCOS-I40main()例2的main()函數(shù)和例1的看起來差不多;有兩點區(qū)別:第一,main()函數(shù)調(diào)用PC_ElapsedInit()來初始化定時器記錄OSTaskStkChk()的執(zhí)行時間。第二,所有的任務(wù)都使用OSTaskCreateExt()函數(shù)來建立(替代了OSTaskCreate()函數(shù)),這使得每一個任務(wù)都可進行堆棧檢查。main()例2的main()函數(shù)和例1的看起來差不多;41例2中的Main()函數(shù)

voidmain(void){PC_DispClrScr(DISP_FGND_WHITE+DISP_BGND_BLACK);OSInit();PC_DOSSaveReturn();PC_VectSet(uCOS,OSCtxSw);PC_ElapsedInit();(1)/對消逝時間的測量進行初始化OSTaskCreateExt(TaskStart,(void*)0,&TaskStartStk[TASK_STK_SIZE-1],

TASK_START_PRIO,TASK_START_ID,&TaskStartStk[0],TASK_STK_SIZE,(void*)0,OS_TASK_OPT_STK_CHK|OS_TASK_OPT_STK_CLR);(2)OSStart();}除了OSTaskCreate()函數(shù)的四個參數(shù)外,OSTaskCreateExt()還需要五個參數(shù):任務(wù)的ID,一個指向任務(wù)堆棧棧底的指針,堆棧的大?。ㄒ远褩卧獮閱挝?,80X86中為字),一個指向用戶定義的TCB擴展數(shù)據(jù)結(jié)構(gòu)的指針,和一個用于指定對任務(wù)操作的變量。

例2中的Main()函數(shù)voidmain(void)除42TaskStart()TaskStart()建立兩個郵箱,分別提供給任務(wù)4和任務(wù)5。接著建立一個專門顯示時間和日期的任務(wù),隨后又建立5個不同的任務(wù)。TaskStart()TaskStart()建立兩個郵箱,分43TaskStart()的偽碼voidTaskStart(void*data){Preventcompilerwarningbyassigning‘data’toitself;Displayabannerandnon-changingtext;InstalluC/OS-II’stickhandler;/關(guān)中斷,PC_VectSet()Changethetickrateto200Hz;/PC_SetTickRate(),開中斷Initializethestatisticstask;/OSStatInit()以上幾項操作和例1中的相同。TaskStart()的偽碼voidTaskStart44TaskStart()的偽碼(續(xù))Create2mailboxeswhichareusedbyTask#4and#5; (1)/調(diào)用TaskStartCreateTasks(void)Createataskthatwilldisplaythedateandtimeonthescreen; (2)Create5applicationtasks;for(;;){Display#tasksrunning;DisplayCPUusagein%;Display#contextswitchesperseconds;Clearthecontextswitchcounter;DisplayuC/OS-II’sversion;If(Keywaspressed){if(KeypressedwastheESCAPEkey){ReturntoDOS;}}Delayfor1second;}}TaskStart()的偽碼(續(xù))Create2mail45創(chuàng)建2個郵箱通過調(diào)用2個OSMboxCreate((void*)0)函數(shù),創(chuàng)建2個郵箱。這2個郵箱在任務(wù)4與任務(wù)5中使用。創(chuàng)建2個郵箱通過調(diào)用2個OSMboxCreate((void46TaskStartCreateTasks(void)staticvoidTaskStartCreateTasks(void){OSTaskCreateExt(TaskClk,(void*)0,&TaskClkStk[TASK_STK_SIZE-1],

TASK_CLK_PRIO,TASK_CLK_ID,&TaskClkStk[0],TASK_STK_SIZE,(void*)0,OS_TASK_OPT_STK_CHK|OS_TASK_OPT_STK_CLR);OSTaskCreateExt(Task1,(void*)0,&Task1Stk[TASK_STK_SIZE-1],

TASK_1_PRIO,TASK_1_ID,&Task1Stk[0],TASK_STK_SIZE,(void*)0,OS_TASK_OPT_STK_CHK|OS_TASK_OPT_STK_CLR);…………OSTaskCreateExt(Task5,……..);}TaskStartCreateTasks(void)stat47時鐘顯示任務(wù)TaskClk()函數(shù)用于顯示當前日期和時間,每秒更新一次。時鐘顯示任務(wù)TaskClk()函數(shù)用于顯示當前日期和時間,每48時鐘顯示任務(wù)程序voidTaskClk(void*data){Structtimenow;Structdatetoday;chars[40];

data=data;for(;;){PC_GetDateTime(s);PC_DispStr(0,24,s,DISP_FGND_BLUE+DISP_BGND_CYAN);OSTimeDly(OS_TICKS_PER_SEC);}}時鐘顯示任務(wù)程序voidTaskClk(void*49任務(wù)1任務(wù)1將檢查其他七個任務(wù)堆棧的大小,同時記錄OSTackStkChk()函數(shù)的執(zhí)行時間,并與堆棧大?。ㄋ卸褩5拇笮《际且宰止?jié)為單位)一起顯示出來。任務(wù)1每秒執(zhí)行10次(間隔100ms)。任務(wù)1任務(wù)1將檢查其他七個任務(wù)堆棧的大小,同時記錄OSTac50任務(wù)1程序voidTask1(void*pdata){INT8Uerr;OS_STK_DATAdata;/任務(wù)堆棧數(shù)據(jù)INT16Utime;/執(zhí)行時間(us)INT8Ui;chars[80];

pdata=pdata;

任務(wù)1程序voidTask1(void*pdata51任務(wù)1程序(續(xù))for(;;){for(i=0;i<7;i++){PC_ElapsedStart(); (1)err=OSTaskStkChk(TASK_START_PRIO+i,&data);time=PC_ElapsedStop();(2)if(err==OS_NO_ERR){sprintf(s,"%3ld%3ld%3ld%5d",data.OSFree+data.OSUsed,data.OSFree,data.OSUsed,time);PC_DispStr(19,12+i,s,DISP_FGND_YELLOW);}}OSTimeDlyHMSM(0,0,0,100);(3)/延時100ms}}任務(wù)1程序(續(xù))for(;;){52任務(wù)2任務(wù)2在屏幕上顯示一個順時針旋轉(zhuǎn)的指針(用橫線,斜線等字符表示),每200ms旋轉(zhuǎn)一格。任務(wù)2任務(wù)2在屏幕上顯示一個順時針旋轉(zhuǎn)的指針(用橫線,斜線53任務(wù)2程序voidTask2(void*data){data=data;for(;;){PC_DispChar(70,15,'|',DISP_FGND_WHITE+DISP_BGND_RED);OSTimeDly(10);PC_DispChar(70,15,'/',DISP_FGND_WHITE+DISP_BGND_RED);任務(wù)2程序voidTask2(void*data)54任務(wù)2程序(續(xù))OSTimeDly(10);PC_DispChar(70,15,'-',DISP_FGND_WHITE+DISP_BGND_RED);OSTimeDly(10);PC_DispChar(70,15,'\\',DISP_FGND_WHITE+DISP_BGND_RED);OSTimeDly(10);}}任務(wù)2程序(續(xù))OSTimeDly(10);55任務(wù)3任務(wù)3也顯示了一個旋轉(zhuǎn)指針,但是與任務(wù)2旋轉(zhuǎn)的方向不同。任務(wù)3在堆棧中分配了一個很大的數(shù)組,將堆棧填充掉,使得OSTaskStkChk()只需花費很少的時間來確定堆棧的利用率,尤其是當堆棧已經(jīng)快滿的時候。任務(wù)3任務(wù)3也顯示了一個旋轉(zhuǎn)指針,但是與任務(wù)2旋轉(zhuǎn)的方向不56任務(wù)3程序voidTask3(void*data){chardummy[500];INT16Ui;data=data;for(I=0;i<499;i++){dummy[i]='?';}任務(wù)3程序voidTask3(void*data)57任務(wù)3程序(續(xù))for(;;){PC_DispChar(70,16,'|',DISP_FGND_WHITE+DISP_BGND_BLUE);OSTimeDly(20);PC_DispChar(70,16,'\\',DISP_FGND_WHITE+DISP_BGND_BLUE);OSTimeDly(20);PC_DispChar(70,16,'-',DISP_FGND_WHITE+DISP_BGND_BLUE);OSTimeDly(20);PC_DispChar(70,16,'/',DISP_FGND_WHITE+DISP_BGND_BLUE);OSTimeDly(20);}}任務(wù)3程序(續(xù))for(;;){PC_DispC58任務(wù)4任務(wù)4向任務(wù)5發(fā)送消息并等待確認。發(fā)送的消息是一個指向字符的指針。每當任務(wù)4從任務(wù)5收到確認,就將傳遞的ASCII碼加1再發(fā)送,結(jié)果是不斷的傳送“ABCDEFG....”。任務(wù)4任務(wù)4向任務(wù)5發(fā)送消息并等待確認。發(fā)送的消息是一個指59任務(wù)4程序voidTask4(void*data){chartxmsg;INT8Uerr;

data=data;txmsg='A';任務(wù)4程序voidTask4(void*data)60任務(wù)4程序(續(xù))for(;;){while(txmsg<='Z'){OSMboxPost(TxMbox,(void*)&txmsg);(1)/向任務(wù)5發(fā)送消息OSMboxPend(AckMbox,0,&err);(2)/等待任務(wù)5的應(yīng)答txmsg++;(3)/發(fā)送下一條消息}txmsg=‘A’;/開始一個新的消息序列}}任務(wù)4程序(續(xù))for(;;){61任務(wù)5當任務(wù)5接收消息后(發(fā)送的字符),就將消息顯示到屏幕上,然后延時1秒,再向任務(wù)4發(fā)送確認信息。任務(wù)5當任務(wù)5接收消息后(發(fā)送的字符),就將消息顯示到屏62任務(wù)5程序voidTask5(void*data){char*rxmsg;INT8Uerr;data=data;任務(wù)5程序voidTask5(void*data)63任務(wù)5程序(續(xù))for(;;){rxmsg=(char*)OSMboxPend(TxMbox,0,&err);(1)/等待任務(wù)4的消息PC_DispChar(70,18,*rxmsg,DISP_FGND_YELLOW+DISP_BGND_RED);(2)OSTimeDlyHMSM(0,0,1,0);(3)/延時等待1sOSMboxPost(AckMbox,(void*)1);(4)/接收到消息的應(yīng)答}}任務(wù)5程序(續(xù))for(;;){64例2的運行結(jié)果例2的運行結(jié)果65例3使用了uCOS-II提供的許多附加功能。使用了OSTaskCreateExt()中TCB的擴展數(shù)據(jù)結(jié)構(gòu),用戶定義的任務(wù)切換對外接口函數(shù)(OSTaskSwHook()),用戶定義的統(tǒng)計任務(wù)(statistictask)的對外接口函數(shù)(OSTaskStatHook())以及消息隊列。例3的磁盤文件位于\SOFTWARE\uCOS-II\EX3_x86L。除了空閑任務(wù)(idletask)和統(tǒng)計任務(wù)(statistictask),還有7個任務(wù),總共9個任務(wù)。例3使用了uCOS-II提供的許多附加功能。66main()main()函數(shù)和例2中的相差不多;不同的是在用戶定義的TCB擴展數(shù)據(jù)結(jié)構(gòu)中可以保存每個任務(wù)的名稱(擴展結(jié)構(gòu)的聲明在INCLUDES.H中定義)。定義了30個字節(jié)來存放任務(wù)名(包括空格)。本例中沒有用到堆棧檢查操作,TaskStart()中禁止該操作。main()main()函數(shù)和例2中的相差不多;67main()函數(shù)

voidmain(void){PC_DispClrScr(DISP_FGND_WHITE+DISP_BGND_BLACK);OSInit();PC_DOSSaveReturn();PC_VectSet(uCOS,OSCtxSw);PC_ElapsedInit();

Strcpy(TaskUserData[TASK_START_ID].TaskName,"StartTask");(1)OSTaskCreateExt(TaskStart,(void*)0,/禁止堆棧檢查&TaskStartStk[TASK_STK_SIZE-1],TASK_START_PRIO,TASK_START_ID,&TaskStartStk[0],TASK_STK_SIZE,&TaskUserData[TASK_START_ID],0);(2)OSStart();}main()函數(shù)voidmain(void)68TCB擴展數(shù)據(jù)結(jié)構(gòu)typedefstruct{charTaskName[30];(1)INT16UTaskCtr;INT16UTaskExecTime;INT32UTaskTotExecTime;}TASK_USER_DATA;定義了30個字節(jié)來存放任務(wù)名(包括空格)TCB擴展數(shù)據(jù)結(jié)構(gòu)typedefstruct定義了3069TaskStart()與例2有3處不同:為任務(wù)1,2,3建立了一個消息隊列;每個任務(wù)都有一個名字,保存在任務(wù)的TCB擴展數(shù)據(jù)結(jié)構(gòu)中;禁止堆棧檢查。TaskStart()與例2有3處不同:70TaskStart()的偽碼voidTaskStart(void*data){Preventcompilerwarningbyassigning‘data’toitself;Displayabannerandnon-changingtext;InstalluC/OS-II’stickhandler;Changethetickrateto200Hz;Initializethestatisticstask;TaskStart()的偽碼voidTaskStart71TaskStart()的偽碼(續(xù))Createamessagequeue;(1)/為任務(wù)1,2,3建立一個消息隊列/調(diào)用TaskStartCreateTasks()創(chuàng)建任務(wù)Createataskthatwilldisplaythedateandtimeonthescreen;Create5applicationtaskswithanamestoredintheTCBext.;(2)/每個任務(wù)的名字都保存在任務(wù)的TCB擴展數(shù)據(jù)結(jié)構(gòu)中for(;;){Display#tasksrunning;DisplayCPUusagein%;Display#contextswitchesperseconds;Clearthecontextswitchcounter;DisplayuC/OS-II’sversion;If(Keywaspressed){if(KeypressedwastheESCAPEkey){ReturntoDOS;}}Delayfor1second;}}TaskStart()的偽碼(續(xù))Createames72為任務(wù)1,2,3建立一個消息隊列MsgQueue=OSQCreate(&MsgQueueTbl[0],MSG_QUEUE_SIZE);為任務(wù)1,2,3建立一個消息隊列MsgQueue=OSQ73TaskStartCreateTasks()voidTaskStartCreateTasks(void){strcpy(TaskUserData[TASK_CLK_ID].TaskName,"ClockTask");OSTaskCreateExt(TaskClk,(void*)0,&TaskClkStk[TASK_STK_SIZE-1],

TASK_CLK_PRIO,TASK_CLK_ID,&TaskClkStk[0],TASK_STK_SIZE,&TaskUserData[TASK_CLK_ID],0);/創(chuàng)建顯示日期與時間的任務(wù)strcpy(TaskUserData[TASK_1_ID].TaskName,"MsgQRxTask");OSTaskCreateExt(Task1,(void*)0,&Task1Stk[TASK_STK_SIZE-1],

TASK_1_PRIO,TASK_1_ID,&Task1Stk[0],TASK_STK_SIZE,&TaskUserData[TASK_1_ID],0);/創(chuàng)建任務(wù)1--------------------------------------strcpy(TaskUserData[TASK_5_ID].TaskName,"TimeDlyTask");OSTaskCreateExt(Task5,(void*)0,&Task5Stk[TASK_STK_SIZE-1],

TASK_5_PRIO,TASK_5_ID,&Task5Stk[0],TASK_STK_SIZE,&TaskUserData[TASK_5_ID],0);/創(chuàng)建任務(wù)5}TaskStartCreateTasks()voidTa74時鐘顯示任務(wù)TaskClk()函數(shù)用于顯示當前日期和時間。與例2類似。時鐘顯示任務(wù)TaskClk()函數(shù)用于顯示當前日期和時間。75任務(wù)1任務(wù)1向消息隊列發(fā)送一個消息,然后延時等待消息發(fā)送完成。這段時間可以讓接收消息的任務(wù)顯示收到的消息。發(fā)送的消息有三種。任務(wù)1任務(wù)1向消息隊列發(fā)送一個消息,然后延時等待消息發(fā)送完76任務(wù)1程序voidTask1(void*data){charone='1';chartwo='2';charthree='3';data=data;for(;;){/向消息隊列發(fā)送一個消息OSQPost(MsgQueue,(void*)&one);(1)/延時等待消息發(fā)送完成OSTimeDlyHMSM(0,0,1,0);(2)OSQPost(MsgQueue,(void*)&two);OSTimeDlyHMSM(0,0,0,500);OSQPost(MsgQueue,(void*)&three);OSTimeDlyHMSM(0,0,1,0);}}任務(wù)1程序voidTask1(void*data)77任務(wù)2任務(wù)2處于等待消息的掛起狀態(tài),且不設(shè)定最大等待時間。任務(wù)2將一直等待直到收到消息。當收到消息后,任務(wù)2顯示消息并且延時500mS,延時的時間可以使任務(wù)3檢查消息隊列。任務(wù)2任務(wù)2處于等待消息的掛起狀態(tài),且不設(shè)定最大等待時間。78任務(wù)2程序voidTask2(void*data){INT8U*msg;INT8Uerr;data=data;for(;;){/處于等待消息的掛起狀態(tài),且不設(shè)定最大等待時間msg=(INT8U*)OSQPend(MsgQueue,0,&err);(1)/收到消息后顯示消息PC_DispChar(70,14,*msg,DISP_FGND_YELLOW+DISP_BGND_BLUE);(2)/延時500mS,同時使任務(wù)3檢查消息隊列OSTimeDlyHMSM(0,0,0,500);(3)}}任務(wù)2程序voidTask2(void*data)79任務(wù)3任務(wù)3同樣處于等待消息的掛起狀態(tài),但是它設(shè)定了等待結(jié)束時間250mS。如果有消息來到,任務(wù)3將顯示消息號,如果超過了等待時間,任務(wù)3就顯示“T”(意為timeout)。任務(wù)3任務(wù)3同樣處于等待消息的掛起狀態(tài),但是它設(shè)定了等待結(jié)80任務(wù)3程序voidTask3(void*data){INT8U*msg;INT8Uerr;data=data;for(;;){msg=(INT8U*)OSQPend(MsgQueue,OS_TICKS_PER_SEC/4,&err); (1)/等待消息的掛起狀態(tài),設(shè)定等待結(jié)束時間250mSIf(err==OS_TIMEOUT){PC_DispChar(70,15,'T',DISP_FGND_YELLOW+DISP_BGND_RED);(2)/如果超過了等待時間,就顯示“T”}else{PC_DispChar(70,15,*msg,DISP_FGND_YELLOW+DISP_BGND_BLUE); (3)/有消息來到,任務(wù)3將顯示消息號}}}任務(wù)3程序voidTask3(void*data)81任務(wù)4任務(wù)4的操作只是從郵箱發(fā)送和接收。用戶可以測量任務(wù)在自己PC上執(zhí)行的時間。任務(wù)4每10mS執(zhí)行一次。任務(wù)4任務(wù)4的操作只是從郵箱發(fā)送和接收。82任務(wù)4程序voidTask4(void*data){OS_EVENT*mbox;INT8Uerr;

data=data;mbox=OSMboxCreate((void*)0);for(;;){OSMboxPost(mbox,(void*)1);(1)/發(fā)送OSMboxPend(mbox,0,&err);(2)/接收OSTimeDlyHMSM(0,0,0,10);(3)/10mS執(zhí)行一次}}任務(wù)4程序voidTask4(void*data)83任務(wù)5任務(wù)5除了延時一個時鐘節(jié)拍以外什么也不做。注意所有的任務(wù)都應(yīng)該調(diào)用uCOS-II的函數(shù),等待延時結(jié)束或者事件的發(fā)生而讓出CPU。如果始終占用CPU,這將使低優(yōu)先級的任務(wù)無法得到CPU。任務(wù)5任務(wù)5除了延時一個時鐘節(jié)拍以外什么也不做。84任務(wù)5程序voidTask5(void*data){data=data;for(;;){OSTimeDly(1);(1)}}任務(wù)5程序voidTask5(void*data)85OSTaskSwHook()函數(shù)通過OSStart()中的OSStartHighRdy()來調(diào)用OSTaskSwHook()函數(shù);該函數(shù)用來測量每個任務(wù)的執(zhí)行時間,可以用來統(tǒng)計每一個任務(wù)的調(diào)度頻率,也可以統(tǒng)計每個任務(wù)運行時間的總和。并將這些信息存儲在每個任務(wù)的TCB擴展數(shù)據(jù)結(jié)構(gòu)中。每次任務(wù)切換的時候OSTaskSwHook()都將被調(diào)用。OSTaskSwHook()函數(shù)通過OSStart()中86用戶定義的OSTaskSwHook()

voidOSTaskSwHook(void){INT16Utime;TASK_USER_DATA*puser;

time=PC_ElapsedStop();(1)/獲取任務(wù)的運行時間,并賦予time變量,然后清零,為下一次計數(shù)做準備。PC_ElapsedStart();(2)/啟動PC的定時器2開始記數(shù)puser=OSTCBCur->OSTCBExtPtr;(3)if(puser!=(void*)0){(4)//如果任務(wù)分配了TCB擴展數(shù)據(jù)結(jié)構(gòu)puser->TaskCtr++;(5)/計數(shù)器TaskCtr進行累加以統(tǒng)計任務(wù)被切換的頻繁程度,或檢查某個任務(wù)是否在運行。puser->TaskExecTime=time;(6)/記錄函數(shù)從切入到切出的運行時間puser->TaskTotExecTime+=time;(7)/記錄任務(wù)總的運行時間}}用戶定義的OSTaskSwHook()voidOSTas87OSTaskStatHo

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論