嵌入式操作系統ucOS-II分析_第1頁
嵌入式操作系統ucOS-II分析_第2頁
嵌入式操作系統ucOS-II分析_第3頁
嵌入式操作系統ucOS-II分析_第4頁
已閱讀5頁,還剩94頁未讀, 繼續免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

1、嵌入式操作系統嵌入式操作系統ucOS-II分析分析ucOS-II應用程序基本結構應用程序基本結構void task ( void* pdata )INT8U err;InitTimer(); / 可選可選For( ; ) / 你的應用程序代碼你的應用程序代碼 . OSTimeDly(1); / 可選可選一些重要的一些重要的ucOS-II API)任務類)任務類)消息類)消息類)同步類)同步類)時間類)時間類)臨界區與事件類)臨界區與事件類任務類和時間類是必須要首先掌握的兩種類型的任務類和時間類是必須要首先掌握的兩種類型的API )OSTaskCreate函數函數 n這個函數應該至少在這個函數應

2、該至少在main函數內調用一函數內調用一次,在次,在OSInit函數調用之后調用,以創函數調用之后調用,以創建一個任務。建一個任務。n系統首先從系統首先從TCB空閑列表內申請一個空空閑列表內申請一個空的的TCB指針,然后根據用戶給出的參數指針,然后根據用戶給出的參數初始化任務堆棧,并在內部的任務就緒初始化任務堆棧,并在內部的任務就緒表內標記該任務為就緒狀態。最后返回,表內標記該任務為就緒狀態。最后返回,這樣一個任務就創建成功了。這樣一個任務就創建成功了。 )OSTaskSuspend函數函數 n將指定的任務掛起。如果掛起的是當前任將指定的任務掛起。如果掛起的是當前任務,會引發系統執行任務切換先

3、導函數務,會引發系統執行任務切換先導函數OSShed來進行一次任務切換。來進行一次任務切換。 n這個函數只有一個優先級參數,在系統內這個函數只有一個優先級參數,在系統內部,優先級除了表示一個任務執行的先后部,優先級除了表示一個任務執行的先后次序外,還起著區分每一個任務的作用,次序外,還起著區分每一個任務的作用,即優先級也是任務的即優先級也是任務的ID。所以。所以uCOS-II不允許出現相同優先級的任務。不允許出現相同優先級的任務。 )OSTaskResume函數函數 n將指定的已經掛起的任務恢復成就緒狀將指定的已經掛起的任務恢復成就緒狀態。如果恢復任務的優先級高于當前任態。如果恢復任務的優先級

4、高于當前任務,那么還會引發一次任務切換。務,那么還會引發一次任務切換。 n參數類似參數類似OSTaskSuspend函數,為指函數,為指定任務的優先級。需要特別說明是,本定任務的優先級。需要特別說明是,本函數并不要求和函數并不要求和OSTaskSuspend函數函數成對使用。成對使用。 )OS_ENTER_CRITICAL宏宏 n分析一下分析一下OS_CPU.H文件,它涉及特定文件,它涉及特定CPU的實現。一般都被替換為一條或者幾的實現。一般都被替換為一條或者幾條嵌入式匯編代碼。其實,它就是條嵌入式匯編代碼。其實,它就是關中斷關中斷。 n只要任務不主動放棄只要任務不主動放棄CPU使用權,別的任

5、使用權,別的任務就沒有占用務就沒有占用CPU的機會,這個任務就是的機會,這個任務就是獨占了。進入臨界區后,這個宏應盡量少獨占了。進入臨界區后,這個宏應盡量少用,它會破壞系統的一些服務,尤其是時用,它會破壞系統的一些服務,尤其是時間服務。并使系統對外界響應性能降低。間服務。并使系統對外界響應性能降低。 )OS_EXIT_CRITICAL宏宏 n與與OS_ENTER_CRITICAL配套使用的配套使用的一個宏,在系統手冊說明里它是退出臨一個宏,在系統手冊說明里它是退出臨界區,其實就是重新界區,其實就是重新開中斷開中斷。n它必須和它必須和OS_ENTER_CRITICAL成對成對出現,否則會帶來意想

6、不到的后果,如出現,否則會帶來意想不到的后果,如系統會崩潰。我們應盡量少用這兩個宏系統會崩潰。我們應盡量少用這兩個宏調用,因為他們的確會破壞系統的多任調用,因為他們的確會破壞系統的多任務性能。務性能。 )OSTimeDly函數函數 n這是調用最多的一個函數,它的功能是這是調用最多的一個函數,它的功能是先掛先掛起當前任務,然后進行任務切換,在指定的起當前任務,然后進行任務切換,在指定的時間到來之后,將當前任務恢復為就緒狀態,時間到來之后,將當前任務恢復為就緒狀態,但是并不一定運行,如果恢復后是優先級最但是并不一定運行,如果恢復后是優先級最高的就緒任務話,那么就運行之。高的就緒任務話,那么就運行之

7、。n可以將任務延時一定時間后再執行它,依靠可以將任務延時一定時間后再執行它,依靠時鐘機制進行任務切換,暫時放棄時鐘機制進行任務切換,暫時放棄CPU的使的使用權,但多任務性能會降低。用權,但多任務性能會降低。ucOS-II范例的源碼分析范例的源碼分析INCLUDES.H nucOS-II中所有的中所有的 *.C 文件都包括了以文件都包括了以下定義:下定義:#include includes.h“n唯一的缺點是唯一的缺點是INCLUDES.H中許多頭文中許多頭文件在一些件在一些*.C文件的編譯中是不需要的。文件的編譯中是不需要的。雖然逐個編譯這些文件要花費額外的時雖然逐個編譯這些文件要花費額外的時

8、間,但代碼的可移植性卻增加了。間,但代碼的可移植性卻增加了。 不依賴于編譯的數據類型不依賴于編譯的數據類型 可移植型數據類型的程序可移植型數據類型的程序Typedef unsigned char BOOLEAN;Typedef unsigned char INT8U;Typedef signed char INT8S;Typedef unsigned int INT16U;Typedef signed int INT16S;Typedef unsigned long INT32U;Typedef signed long INT32S;Typedef float FP32;Typedef dou

9、ble FP64;#define BYTE INT8S -|#define UBYTE INT8U -|#define WORD INT16S -| ucos-ucosII#define UWORD INT16U -|#define LONG INT32S -|#define ULONG INT32U -|全局變量全局變量 n定義全局宏的程序定義全局宏的程序#ifdef xxx_GLOBALS#define xxx_EXT#else#define xxx_EXT extern#endif.H 文件中每個全局變量都加上了文件中每個全局變量都加上了xxx_EXT的前綴。的前綴。xxx代表模塊的名字

10、。該模塊的代表模塊的名字。該模塊的.C文件中有以下定義:文件中有以下定義:#define xxx_GLOBALS#include includes.huCOS_II.H中有以下定義:中有以下定義: n#ifdef OS_GLOBALSn#define OS_EXTn#elsen#define OS_EXT externn#endif nOS_EXT INT32U OSIdleCtr;nOS_EXT INT32U OSIdleCtrRun;nOS_EXT INT32U OSIdleCtrMax;uCOS_II.C中有以下定義:中有以下定義: n#define OS_GLOBALSn#includ

11、e “includes.h” 當編譯器處理當編譯器處理uCOS_II.C時,它使時,它使uCOS_II.H變成如下所示,因為變成如下所示,因為OS_EXT被被設置為空。編譯器就會將這些全局變量分配設置為空。編譯器就會將這些全局變量分配到內存中。到內存中。 nINT32U OSIdleCtr;nINT32U OSIdleCtrRun;nINT32U OSIdleCtrMax; 當編譯器處理其他當編譯器處理其他.C文件時,頭文件變成了文件時,頭文件變成了如下的樣子,因為如下的樣子,因為OS_GLOBAL沒有定義,沒有定義,所以所以OS_EXT被定義為被定義為extern。 nextern INT3

12、2U OSIdleCtr;nextern INT32U OSIdleCtrRun;nextern INT32U OSIdleCtrMax; 在這種情況下,不產生內存分配,而任何在這種情況下,不產生內存分配,而任何 .C文件都可以使用這些變量。這樣就只需在文件都可以使用這些變量。這樣就只需在 .H 文件中定義一次就可以了。文件中定義一次就可以了。OS_ENTER_CRITICAL() 和和 OS_EXIT_CRITICAL()nOS_ENTER_CRITICAL() 關中斷;關中斷;OS_EXIT_CRITICAL()開中斷。開中斷。n是為了保護臨界段代碼,這些代碼與處是為了保護臨界段代碼,這些

13、代碼與處理器有關。宏的定義在理器有關。宏的定義在OS_CPU.H中。中。n關中斷會影響中斷延遲,所以要特別小關中斷會影響中斷延遲,所以要特別小心。用戶還可以用信號量來保護臨界段心。用戶還可以用信號量來保護臨界段代碼。代碼。 基于基于PC的服務的服務 nPC.C 文件和文件和 PC.H 文件是范例中使文件是范例中使用到的一些基于用到的一些基于PC的服務程序。的服務程序。 nPC.C包括字符顯示,時間度量和其包括字符顯示,時間度量和其他各種服務。所有的函數都以他各種服務。所有的函數都以PC_為為前綴。前綴。 字符顯示字符顯示 nPC_DispClrScr()Clear the screennPC_

14、DispClrLine()Clear a single row (or line)nPC_DispChar()Display a single ASCII character anywhere on the screennPC_DispStr()Display an ASCII string anywhere on the screen時間度量時間度量 n用用PC的的82C54定時器定時器2測試一個函數的運行花測試一個函數的運行花了多少時間。被測的程序代碼放在函數了多少時間。被測的程序代碼放在函數PC_ElapsedStart()和和PC_ElapsedStop()之之間來測量。在用這兩個函數

15、之前,應該調用間來測量。在用這兩個函數之前,應該調用PC_ElapsedInit()來初始化,它主要是計算運來初始化,它主要是計算運行這兩個函數本身所附加的的時間。這樣,行這兩個函數本身所附加的的時間。這樣,PC_ElapsedStop()函數中返回的數值就是準函數中返回的數值就是準確的測量結果了。這兩個函數都不具備可重入確的測量結果了。這兩個函數都不具備可重入性,不要有多個任務同時調用這兩個函數。性,不要有多個任務同時調用這兩個函數。 測量測量PC_DisplayChar()的執的執行時間(行時間(us)n測量代碼執行時間的程序測量代碼執行時間的程序INT16U time; PC_Elaps

16、edInit();.PC_ElapsedStart();PC_DispChar(40, 24, A, DISP_FGND_WHITE);time = PC_ElapsedStop();應用應用 C/OS-II 的范例的范例 n用用BC IDE (Integrated Development Environment)編譯通編譯通過,在過,在WindowsXP 的的DOS窗口下編窗口下編譯運行??蓤绦写a在每個范例的譯運行。可執行代碼在每個范例的OBJ子目錄中。子目錄中。 IDE中編譯選項中編譯選項nCode generation Model: LargeOptions: Treat enums

17、as intsAssume SS Equals DS: Default for memory modelnAdvanced code generation Floating point: EmulationInstruction set: 80186Options: Generate underbars Debug info in OBJs Fast floating pointIDE中編譯選項中編譯選項nOptimizationsGlobal register allocation Invariant code motion Induction variables Loop optimiza

18、tion Suppress redundant loads Copy propagation Dead code elimination Jump optimization In-line intrinsic functionsIDE中編譯選項中編譯選項nRegister variables AutomaticnCommon subexpressions Optimize globallynOptimize for Speed例例1n有有13個任務個任務(包括包括 C/OS-II 的空閑任務和一個計的空閑任務和一個計算算CPU利用率的任務)。利用率的任務)。TaskStart()在函數在函數m

19、ain()中建立,功能是建立其它任務并且在屏幕上顯示如中建立,功能是建立其它任務并且在屏幕上顯示如下統計信息:下統計信息:n每秒鐘任務切換次數;每秒鐘任務切換次數;CPU利用百分率;寄存器切利用百分率;寄存器切換次數;目前日期和時間;換次數;目前日期和時間;C/OS-II的版本號;的版本號;n TaskStart()還檢查是否按下還檢查是否按下ESC鍵,以決定是否鍵,以決定是否返回到返回到DOS。n其余其余10個任務基于相同的代碼個任務基于相同的代碼Task();每個任;每個任務在屏幕上隨機的位置顯示一個務在屏幕上隨機的位置顯示一個0到到9的數字。的數字。main() nmain()程序從清整

20、個屏幕開始,為的是保程序從清整個屏幕開始,為的是保證屏幕上不留有以前的證屏幕上不留有以前的DOS下的顯示。下的顯示。n用戶在使用任何服務之前先調用用戶在使用任何服務之前先調用OSInit() 。建立兩個任務:空閑任務和統計任務,前者建立兩個任務:空閑任務和統計任務,前者在沒有其它任務處于就緒態時運行;后者計在沒有其它任務處于就緒態時運行;后者計算算CPU的利用率。的利用率。main()程序程序nvoid main (void) PC_DispClrScr(DISP_FGND_WHITE + DISP_BGND_BLACK); (1) OSInit(); (2) PC_DOSSaveReturn

21、(); /保存保存當前當前DOS環境環境 (3) PC_VectSet(uCOS, OSCtxSw); /設置任務切換處理函數設置任務切換處理函數 (4) RandomSem = OSSemCreate(1); /信號量置為信號量置為1,在某一時刻只,在某一時刻只有一個任務可以調用隨機數產生函數有一個任務可以調用隨機數產生函數 (5) OSTaskCreate(TaskStart, (void *)0, /啟動多任務啟動多任務OSStart()之前,用戶至少要先建立一個任務如之前,用戶至少要先建立一個任務如TaskStart()(void*)&TaskStartStkTASK_STK_

22、SIZE-1, 0); (6) OSStart(); /啟動多任務啟動多任務 (7)OSInit()初始化初始化【在在OS_CORE.C中定義中定義】 void OSInit (void)#if OS_VERSION = 204 OSInitHookBegin(); /系統初始化開始接口函數系統初始化開始接口函數#endif OS_InitMisc(); /初始化變量初始化變量 OS_InitRdyList(); /初始化任務就緒列表初始化任務就緒列表 OS_InitTCBList(); /初始化任務控制塊列表初始化任務控制塊列表 OS_InitEventList(); /初始化事件控制塊列表

23、初始化事件控制塊列表 OSInit()初始化(續)初始化(續)#if (OS_VERSION = 251) & (OS_FLAG_EN 0) & (OS_MAX_FLAGS 0) OS_FlagInit(); /事件標志結構初始化事件標志結構初始化 #endif#if (OS_MEM_EN 0) & (OS_MAX_MEM_PART 0) OS_MemInit(); /內存管理初始化內存管理初始化 #endif#if (OS_Q_EN 0) & (OS_MAX_QS 0) OS_QInit(); /消息隊列初始化消息隊列初始化 #endif OS_InitTas

24、kIdle(); /創建空閑任務創建空閑任務(無條件無條件) #if OS_TASK_STAT_EN 0 OS_InitTaskStat(); /創建統計任務創建統計任務 #endif#if OS_VERSION = 204 OSInitHookEnd(); /系統初始化結束接口函數系統初始化結束接口函數#endif#if OS_VERSION = 270 & OS_DEBUG_EN 0 OSDebugInit();#endifOS_InitMisc()初始化變量初始化變量 nOSIntNesting = 0; /清除中斷嵌套計數器清除中斷嵌套計數器 nOSLockNesting =

25、0; /清除調度鎖定計數器清除調度鎖定計數器 nOSTaskCtr = 0; /任務數清零任務數清零nOSRunning = FALSE; /系統多任務沒有執系統多任務沒有執行行 nOSIdleCtr = 0L; /清除空閑任務計數器清除空閑任務計數器nOSCtxSwCtr = 0; /清除程序切換計數器清除程序切換計數器 OS_InitRdyList()初始化任務就緒列表初始化任務就緒列表 nstatic void OS_InitRdyList (void) INT8U i; INT8U *prdytbl; OSRdyGrp = 0 x00; /清除任務就緒表清除任務就緒表 prdytbl

26、= &OSRdyTbl0; /將將OSRdyTbl數組全部初始化數組全部初始化0 for (i = 0; i OS_RDY_TBL_SIZE; i+) *prdytbl+ = 0 x00; /把任務就緒表里面所有的項目全部清零把任務就緒表里面所有的項目全部清零 OSPrioCur = 0; /當前運行任務的優先級寄存器清零當前運行任務的優先級寄存器清零 OSPrioHighRdy = 0; /將處于就緒狀態的最高優先級的任務寄存器清零將處于就緒狀態的最高優先級的任務寄存器清零 OSTCBHighRdy = (OS_TCB *)0; /將處于就緒態的最高優先級的任務控制塊指針寄將處于就緒

27、態的最高優先級的任務控制塊指針寄存器清零存器清零 OSTCBCur = (OS_TCB *)0; /將當前運行任務的任務控制塊指針寄存器清零將當前運行任務的任務控制塊指針寄存器清零 OSTCBList = (OS_TCB *)0; /任務控制塊列表清零任務控制塊列表清零 for (i = 0; i (OS_LOWEST_PRIO + 1); i+) OSTCBPrioTbli = (OS_TCB *)0; / 清除優先級列表,這個列表存儲各個優先級對應的任務控制塊的地址,系清除優先級列表,這個列表存儲各個優先級對應的任務控制塊的地址,系統用它來尋找下一個要運行的任務地址統用它來尋找下一個要運行

28、的任務地址OS_InitTCBList()初始化任務控制塊列表初始化任務控制塊列表nstatic void OS_InitTCBList (void) INT8U i; OS_TCB *ptcb1; OS_TCB *ptcb2; OS_MemClr(INT8U *)&OSTCBTbl0, sizeof(OSTCBTbl); / 清除清除TCB OS_MemClr(INT8U *)&OSTCBPrioTbl0, sizeof(OSTCBPrioTbl); / 清除優先級表清除優先級表 ptcb1 = &OSTCBTbl0; /任務控制塊列表的第一個任務塊地址給變量任務控制

29、塊列表的第一個任務塊地址給變量PTCB1 ptcb2 = &OSTCBTbl1; /任務控制塊列表的第二個任務塊地址給變量任務控制塊列表的第二個任務塊地址給變量PTCB2 for (i = 0; i OSTCBNext = ptcb2;#if OS_TASK_NAME_SIZE 1 ptcb1-OSTCBTaskName0 = ?; /* Unknown name */ ptcb1-OSTCBTaskName1 = OS_ASCII_NUL;/把前一個任務控制塊的下一個任務指針指向下把前一個任務控制塊的下一個任務指針指向下一個任務控制塊一個任務控制塊 #endif ptcb1+; pt

30、cb2+; ptcb1-OSTCBNext = (OS_TCB *)0; /把最后一個任務控制塊的下個指針清零把最后一個任務控制塊的下個指針清零 #if OS_TASK_NAME_SIZE 1 ptcb1-OSTCBTaskName0 = ?; /* Unknown name */ ptcb1-OSTCBTaskName1 = OS_ASCII_NUL;#endif OSTCBList = (OS_TCB *)0; /TCB列表初始化列表初始化 OSTCBFreeList = &OSTCBTbl0; /把第一個任務控制塊的地址送給空閑任務控制塊列把第一個任務控制塊的地址送給空閑任務控制

31、塊列表表 建立其它任務的任務建立其它任務的任務 TaskStart() nvoid TaskStart (void *data)TaskStart()將()將data的值賦給自己,以免某些編譯的值賦給自己,以免某些編譯器的警告器的警告 TaskStartDispInit();(); (1) /在屏幕頂端顯示一個標在屏幕頂端顯示一個標識,說明這是例識,說明這是例1 。 OS_ENTER_CRITICAL(); PC_VectSet(0 x08, OSTickISR); (2) PC_SetTickRate(200); (3) /關中斷,以改變中斷向量,讓其指向關中斷,以改變中斷向量,讓其指向C/

32、OS-II的時鐘的時鐘節拍處理,然后,改變時鐘節拍為節拍處理,然后,改變時鐘節拍為 200Hz OS_EXIT_CRITICAL(); 建立其它任務的任務建立其它任務的任務 TaskStart()(續)(續)OSStatInit(); /測試處理器的速度(運行任務時的測試處理器的速度(運行任務時的CPU使用率)使用率) (4)TaskStartCreateTasks(); /建立建立10個同樣的任務個同樣的任務 (5) for (;) /每個任務都是一個無限循環每個任務都是一個無限循環 TaskStartDisp();/在在Dos窗口底部,顯示相關信息(任務個數、窗口底部,顯示相關信息(任務個

33、數、CPU利用利用率、任務切換次數、率、任務切換次數、ucOS-II版本號和處理器是否包含浮點處理單元版本號和處理器是否包含浮點處理單元FPU) If (PC_GetKey(&key)=TRUE) /檢查是否有鍵按下檢查是否有鍵按下 if (key=0 x1B) /是否按下是否按下Esc鍵鍵 PC_DOSReturn(); OSCtxSWCtr=0; /如果沒有按下如果沒有按下Esc鍵,則記錄任務切換次數的全局變量清鍵,則記錄任務切換次數的全局變量清零零 OSTimeDlyHMSM(0,0,1,0);/TaskStart()任務將自身掛起()任務將自身掛起1秒,秒,ucOS-II開始調

34、度,找下一個最高優先級(開始調度,找下一個最高優先級(=1)的就緒任務)的就緒任務 測試測試CPU速度速度 void OSStatInit (void) OSTimeDly(2); /延時兩個時鐘節拍延時兩個時鐘節拍 OS_ENTER_CRITICAL(); OSIdleCtr = 0L; /32位的計數器位的計數器OSIdleCtr被清被清0,并產,并產生另一個延時,這個延時使生另一個延時,這個延時使OSStatInit()掛起掛起 。 OS_EXIT_CRITICAL();/uCOS-II執行執行一個無一個無限限循環循環的空閑任務的空閑任務,不斷的遞增,不斷的遞增OSIdleCtr OST

35、imeDly(OS_TICKS_PER_SEC); OS_ENTER_CRITICAL(); OSIdleCtrMax = OSIdleCtr; OSStatRdy = TRUE; /COS-II將統計將統計CPU的利用率的利用率 OS_EXIT_CRITICAL(); 建立建立10個同樣的任務個同樣的任務Static void TaskStartCreateTasks(void)INT8U i; for(i=0;iN_TASKS;i+) TaskDatai=0+i;/初始化字符數組,包含初始化字符數組,包含09 OSTaskCreate(Task, /循環建立循環建立N_TASKS個相同的任

36、個相同的任務,每個任務顯示不同的字符務,每個任務顯示不同的字符(void *)&TaskDatai, /每個任務接受一個指向字符數組中每個任務接受一個指向字符數組中元素的指針元素的指針&TaskStkiTASK_STK_SIZE-1, /每個任務各自的堆??彰總€任務各自的堆棧空間間i+1); /每個任務各自的優先級每個任務各自的優先級110在屏幕隨機位置顯示任務號(在屏幕隨機位置顯示任務號(09) void Task (void *data) UBYTE x; UBYTE y; UBYTE err; for (;) OSSemPend(RandomSem, 0, &er

37、r); /獲取信號量獲取信號量RandomSem ,同時禁止其他任務運行這段代碼同時禁止其他任務運行這段代碼 x = random(80); /獲得一個隨機數獲得一個隨機數 y = random(16); /獲得一個隨機數獲得一個隨機數 OSSemPost(RandomSem); /計算出計算出x和和y坐標并坐標并釋放信號量釋放信號量 PC_DispChar(x, y + 5, *(char *)data, DISP_FGND_LIGHT_GRAY);/在計算的坐標處顯示其任務號(在計算的坐標處顯示其任務號(0-9) OSTimeDly(1); /延時一個時鐘節拍延時一個時鐘節拍,等待進入下一

38、次循環,等待進入下一次循環 例例1的運行結果的運行結果例例2n磁盤文件為磁盤文件為SOFTWAREuCOS-IIEX2_x86L,它,它包含包含9個任務。加上個任務。加上uCOS-II本身的兩個任務:空閑本身的兩個任務:空閑任務(任務(idle task)和統計任務,共)和統計任務,共11個任務。個任務。 n由由main()中的()中的TaskStart()函數建立任務,功能()函數建立任務,功能是建立其他任務并在屏幕上顯示如下的統計數據:是建立其他任務并在屏幕上顯示如下的統計數據: 每秒種任務切換的次數;每秒種任務切換的次數; CPU利用率的百分比;利用率的百分比; 當前日期和時間;當前日期

39、和時間; uCOS_II的版本號;的版本號;n使用帶擴展功能的任務建立函數使用帶擴展功能的任務建立函數OSTaskCreateExt()()和和uCOS-II的堆棧檢查操作(要使用堆棧檢查操作必的堆棧檢查操作(要使用堆棧檢查操作必須用須用OSTaskCreateExt()建立任務)。()建立任務)。C/OS-II stack checking uCOS-II的堆棧檢查功能要求任務建立時堆棧清零。的堆棧檢查功能要求任務建立時堆棧清零。OSTaskCreateExt()可以執行此可以執行此項操作(設置選項項操作(設置選項OS_TASK_OPT_STK_CHK和和OS_TASK_OPT_STK_CL

40、R打開此項打開此項操作)。操作)。OSTaskCreateExt()進行堆棧清零操作是一項很費時的工作,取決于堆棧的大進行堆棧清零操作是一項很費時的工作,取決于堆棧的大小。執行堆棧檢查操作的時候,小。執行堆棧檢查操作的時候,uCOS-II從棧底向棧頂搜索非從棧底向棧頂搜索非0元素元素(參看上圖參看上圖),同時用,同時用一個計數器記錄一個計數器記錄0元素的個數。元素的個數。main() n例例2的的main()函數和例函數和例1的看起來差不多;的看起來差不多;n有兩點區別:第一,有兩點區別:第一,main()函數調用函數調用PC_ElapsedInit()來初始化定時器記錄來初始化定時器記錄OS

41、TaskStkChk()的執行時間。第二,所的執行時間。第二,所有的任務都使用有的任務都使用OSTaskCreateExt()函數函數來建立(替代了來建立(替代了OSTaskCreate()函數),()函數),這使得每一個任務都可進行堆棧檢查。這使得每一個任務都可進行堆棧檢查。 例例2中的中的Main()函數()函數 nvoid main (void) PC_DispClrScr(DISP_FGND_WHITE + DISP_BGND_BLACK); OSInit(); PC_DOSSaveReturn(); PC_VectSet(uCOS, OSCtxSw); PC_ElapsedInit(

42、); /對消逝時間的測量進行初始化對消逝時間的測量進行初始化 OSTaskCreateExt(TaskStart, (void *)0, &TaskStartStkTASK_STK_SIZE-1, TASK_START_PRIO, TASK_START_ID, &TaskStartStk0, TASK_STK_SIZE, (void *)0, OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR); (2) OSStart();除了除了OSTaskCreate()函數的四個參數外,函數的四個參數外,OSTaskCreateExt()還需要五個參還需

43、要五個參數:任務的數:任務的ID,一個指向任務堆棧棧底的指針,堆棧的大小(以堆棧單元為單,一個指向任務堆棧棧底的指針,堆棧的大?。ㄒ远褩卧獮閱挝唬唬?0X86中為字),一個指向用戶定義的中為字),一個指向用戶定義的TCB擴展數據結構的指針,和一個擴展數據結構的指針,和一個用于指定對任務操作的變量。用于指定對任務操作的變量。 TaskStart()()nTaskStart()建立兩個郵箱,()建立兩個郵箱,分別提供給任務分別提供給任務4和任務和任務5。n接著建立一個專門顯示時間和日接著建立一個專門顯示時間和日期的任務,隨后又建立期的任務,隨后又建立5個不同的個不同的任務。任務。TaskSta

44、rt()的偽碼的偽碼 nvoid TaskStart (void *data) Prevent compiler warning by assigning data to itself; Display a banner and non-changing text; Install uC/OS-IIs tick handler; /關中斷,關中斷,PC_VectSet() Change the tick rate to 200 Hz; /PC_SetTickRate() ,開中斷,開中斷 Initialize the statistics task;/OSStatInit()()以上幾項操作和

45、例以上幾項操作和例1中的相同。中的相同。 TaskStart()的偽碼(續)的偽碼(續)nCreate 2 mailboxes which are used by Task #4 and #5; (1) n/ 調用調用TaskStartCreateTasks(void)nCreate a task that will display the date and time on the screen;(2) nCreate 5 application tasks; nfor (;) Display #tasks running; Display CPU usage in %; Display #c

46、ontext switches per seconds; Clear the context switch counter; Display uC/OS-IIs version; If (Key was pressed) if (Key pressed was the ESCAPE key) Return to DOS; Delay for 1 second; 創建創建2個郵箱個郵箱n通過調用通過調用2個個OSMboxCreate(void *)0)函數,創建函數,創建2個郵箱。個郵箱。n這這2個郵箱在任務個郵箱在任務4與任務與任務5中使用。中使用。TaskStartCreateTasks(v

47、oid)nstatic void TaskStartCreateTasks (void)nn OSTaskCreateExt(TaskClk, (void *)0,n &TaskClkStkTASK_STK_SIZE - 1,n TASK_CLK_PRIO, TASK_CLK_ID, &TaskClkStk0,n TASK_STK_SIZE, (void *)0,n OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR);n OSTaskCreateExt(Task1, (void *)0, n &Task1StkTASK_STK_SIZE

48、 - 1,n TASK_1_PRIO, TASK_1_ID,&Task1Stk0,n TASK_STK_SIZE, (void *)0,n OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR);nn OSTaskCreateExt(Task5, .);n時鐘顯示任務時鐘顯示任務nTaskClk()函數用于顯示當前函數用于顯示當前日期和時間,每秒更新一次。日期和時間,每秒更新一次。 時鐘顯示任務程序時鐘顯示任務程序 nvoid TaskClk (void *data) Struct time now; Struct date today; char s40

49、; data = data; for (;) PC_GetDateTime(s); PC_DispStr(0, 24, s, DISP_FGND_BLUE + DISP_BGND_CYAN); OSTimeDly(OS_TICKS_PER_SEC); 任務任務1n任務任務1將檢查其他七個任務堆棧的將檢查其他七個任務堆棧的大小,同時記錄大小,同時記錄OSTaskStkChk()函數的執行時間,并與堆棧大小函數的執行時間,并與堆棧大?。ㄋ卸褩5拇笮《际且宰止潪椋ㄋ卸褩5拇笮《际且宰止潪閱挝唬┮黄痫@示出來。任務單位)一起顯示出來。任務1每秒每秒執行執行10次(間隔次(間隔100ms)。)。任務任

50、務1程序程序 nvoid Task1 (void *pdata) INT8U err; OS_STK_DATA data; /任務堆棧數據任務堆棧數據 INT16U time; /執行時間執行時間 INT8U i; char s80; pdata = pdata; 任務任務1程序程序 (續)(續)for (;) for (i = 0; i 7; i+) PC_ElapsedStart();/ 統計統計OSTaskStkChk()函數運行時間開始()函數運行時間開始 err = OSTaskStkChk(TASK_START_PRIO+i, &data); time = PC_Elaps

51、edStop(); /統計統計OSTaskStkChk()函數運行時間()函數運行時間結束結束 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); /延時延時100ms 任務任務2 n任務任務2在屏幕上顯示一個順時在屏幕上顯示一個順時針旋轉的指針(用橫線針

52、旋轉的指針(用橫線_,豎線豎線|,斜線,斜線/、,等字符表,等字符表示),每示),每200ms旋轉一格。旋轉一格。 任務任務2程序程序nvoid Task2 (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);任務任務2程序程序 (續)(續)OSTimeDly(10); PC_DispChar(70, 15, -, DISP_

53、FGND_WHITE + DISP_BGND_RED); OSTimeDly(10); PC_DispChar(70, 15, , DISP_FGND_WHITE + DISP_BGND_RED); OSTimeDly(10); 任務任務3 n任務任務3也顯示了一個旋轉指針,但是與任務也顯示了一個旋轉指針,但是與任務2旋轉的方向不同。任務旋轉的方向不同。任務3在堆棧中分配了在堆棧中分配了一個一個500B的數組,占用了的數組,占用了Task3的堆棧,的堆棧,程序運行后可看出,程序運行后可看出,Task3的空閑堆棧比的空閑堆棧比Task2少了少了502B(500B的數組和一個的數組和一個2B的整型

54、變量)。的整型變量)。任務任務3程序程序nvoid Task3 (void *data) char dummy500; INT16U i; data = data; for (I = 0; i 499; i+) dummyi = ?; 任務任務3程序程序 (續)(續)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(7

55、0, 16, -, DISP_FGND_WHITE + DISP_BGND_BLUE); OSTimeDly(20); PC_DispChar(70, 16, /, DISP_FGND_WHITE + DISP_BGND_BLUE); OSTimeDly(20); 任務任務4 n任務任務4向任務向任務5發送消息并等待確發送消息并等待確認。發送的消息是一個指向字符認。發送的消息是一個指向字符的指針。每當任務的指針。每當任務4從任務從任務5收到收到確認,就將傳遞的確認,就將傳遞的ASCII碼加碼加1再再發送,結果是不斷的傳送發送,結果是不斷的傳送“ABCDEFG.”。任務任務4程序程序nvoid Task4 (void *data) char txmsg; INT8U err; data = data; txmsg = A;任務任務4程序程序 (續)(續)for (;) while (txmsg OSTCBExtPtr; if (puser != (void *)0) /如果任務分配了如果任務分配了TCB擴展數據結構擴展數據結構 puser-TaskCtr+; /計數器計數器TaskCtr進行累加以統計進行累加以統計任務被切換的頻繁程度,或檢查某個任務是否在運行。任務被切換的頻繁程度,或檢查某個任務是否在運行。 puser-TaskE

溫馨提示

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

評論

0/150

提交評論