嵌入式操作系统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窗口下编窗口下编译运行。可执行代码在每个范例的译运行。可执行代码在每个范例的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,一个指向任务堆栈栈底的指针,堆栈的大小(以堆栈单元为单,一个指向任务堆栈栈底的指针,堆栈的大小(以堆栈单元为单位,位,80X86中为字),一个指向用户定义的中为字),一个指向用户定义的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()函数的执行时间,并与堆栈大小函数的执行时间,并与堆栈大小(所有堆栈的大小都是以字节为(所有堆栈的大小都是以字节为单位)一起显示出来。任务单位)一起显示出来。任务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

提交评论