ucOS-II范例分析_01汇总课件

上传人:58****5 文档编号:243142576 上传时间:2024-09-16 格式:PPT 页数:98 大小:989KB
返回 下载 相关 举报
ucOS-II范例分析_01汇总课件_第1页
第1页 / 共98页
ucOS-II范例分析_01汇总课件_第2页
第2页 / 共98页
ucOS-II范例分析_01汇总课件_第3页
第3页 / 共98页
点击查看更多>>
资源描述
,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,*,*,嵌入式操作系统,ucOS,-II,分析,ucOS,-II,应用程序基本结构,void task ( void*,pdata,),INT8Uerr;,InitTimer,(); /,可选,For( ; ),/,你的应用程序代码,.,OSTimeDly(1); /,可选,一些重要的,ucOS,-II API,)任务类,)消息类,)同步类,)时间类,)临界区与事件类,任务类和时间类是必须要首先掌握的两种类型的,API,),OSTaskCreate,函数,这个函数应该至少在,main,函数内调用一次,在,OSInit,函数调用之后调用,以创建一个任务。,系统首先从,TCB,空闲列表内申请一个空的,TCB,指针,然后根据用户给出的参数初始化任务堆栈,并在内部的任务就绪表内标记该任务为就绪状态。最后返回,这样一个任务就创建成功了。,),OSTaskSuspend,函数,将指定的任务挂起。如果挂起的是当前任务,会引发系统执行任务切换先导函数,OSShed,来进行一次任务切换。,这个函数只有一个优先级参数,在系统内部,优先级除了表示一个任务执行的先后次序外,还起着区分每一个任务的作用,即优先级也是任务的,ID,。所以,uCOS,-II,不允许出现相同优先级的任务。,),OSTaskResume,函数,将指定的已经挂起的任务恢复成就绪状态。如果恢复任务的优先级高于当前任务,那么还会引发一次任务切换。,参数类似,OSTaskSuspend,函数,为指定任务的优先级。需要特别说明是,本函数并不要求和,OSTaskSuspend,函数成对使用。,),OS_ENTER_CRITICAL,宏,分析一下,OS_CPU.H,文件,它涉及特定,CPU,的实现。一般都被替换为一条或者几条嵌入式汇编代码。其实,它就是关中断。,只要任务不主动放弃,CPU,使用权,别的任务就没有占用,CPU,的机会,这个任务就是独占了。进入临界区后,这个应宏尽量少用,它会破坏系统的一些服务,尤其是时间服务。并使系统对外界响应性能降低。,),OS_EXIT_CRITICAL,宏,与,OS_ENTER_CRITICAL,配套使用的一个宏,在系统手册说明里它是退出临界区,其实就是重新开中断。,它必须和,OS_ENTER_CRITICAL,成对出现,否则会带来意想不到的后果,如系统会崩溃。我们应尽量少用这两个宏调用,因为他们的确会破坏系统的多任务性能。,),OSTimeDly,函数,这是调用最多的一个函数,它的功能是先挂起当前任务,然后进行任务切换,在指定的时间到来之后,将当前任务恢复为就绪状态,但是并不一定运行,如果恢复后是优先级最高的就绪任务话,那么就运行之。,可以将任务延时一定时间后再执行它,依靠时钟机制进行任务切换,暂时放弃,CPU,的使用权,但多任务性能会降低。,ucOS,-II,范例的源码分析,INCLUDES.H,ucOS,-II,中所有的 *,.C,文件都包括了以下定义:,#include ,includes.h,“,唯一的缺点是,INCLUDES.H,中许多头文件在一些*,.C,文件的编译中是不需要的。虽然逐个编译这些文件要花费额外的时间,但代码的可移植性却增加了。,不依赖于编译的数据类型,可移植型数据类型的程序,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,double FP64;,#define BYTE INT8S -|,#define UBYTE INT8U -|,#define WORD INT16S -|,ucos,-,ucosII,#define UWORD INT16U -|,#define LONG INT32S -|,#define ULONG INT32U -|,全局变量,定义全局宏的程序,#,ifdef,xxx_GLOBALS,#define,xxx_EXT,#else,#define,xxx_EXT,extern,#,endif,.H,文件中每个全局变量都加上了,xxx_EXT,的前缀。,xxx,代表模块的名字。该模块的,.C,文件中有以下定义:,#define,xxx_GLOBALS,#include ,includes.h,uCOS_II.H,中有以下定义:,#,ifdef,OS_GLOBALS,#define OS_EXT,#else,#define OS_EXT extern,#,endif,OS_EXT INT32U,OSIdleCtr,;,OS_EXT INT32U,OSIdleCtrRun,;,OS_EXT INT32U,OSIdleCtrMax,;,uCOS_II.C,中有以下定义:,#define OS_GLOBALS,#include “,includes.h,”,当编译器处理,uCOS_II.C,时,它使,uCOS_II.H,变成如下所示,因为,OS_EXT,被设置为空。编译器就会将这些全局变量分配到内存中。,INT32U,OSIdleCtr,;,INT32U,OSIdleCtrRun,;,INT32U,OSIdleCtrMax,;,当编译器处理其他,.C,文件时,头文件变成了如下的样子,因为,OS_GLOBAL,没有定义,所以,OS_EXT,被定义为,extern,。,extern INT32U,OSIdleCtr,;,extern INT32U,OSIdleCtrRun,;,extern INT32U,OSIdleCtrMax,;,在这种情况下,不产生内存分配,而任何,.C,文件都可以使用这些变量。这样的就只需在,.H,文件中定义一次就可以了。,OS_ENTER_CRITICAL(),和,OS_EXIT_CRITICAL(),OS_ENTER_CRITICAL(),关中断;,OS_EXIT_CRITICAL(),开中断。,是为了保护临界段代码,这些代码与处理器有关。宏的定义在,OS_CPU.H,中。,关中断会影响中断延迟,所以要特别小心。用户还可以用信号量来保护临界段代码。,基于,PC,的服务,PC.C,文件和,PC.H,文件是范例中使用到的一些基于,PC,的服务程序。,PC.C,包括字符显示,时间度量和其他各种服务。所有的函数都以,PC_,为前缀。,字符显示,PC_DispClrScr,()Clear the screen,PC_DispClrLine,()Clear a single row (or line),PC_DispChar,()Display a single ASCII character anywhere on the screen,PC_DispStr,()Display an ASCII string anywhere on the screen,时间度量,用,PC,的,82C54,定时器,2,测试一个函数的运行花了多少时间。被测的程序代码放在函数,PC_ElapsedStart,(),和,PC_ElapsedStop,(),之间来测量。在用这两个函数之前,应该调用,PC_ElapsedInit,(),来初始化,它主要是计算运行这两个函数本身所附加的的时间。这样,,PC_ElapsedStop,(),函数中返回的数值就是准确的测量结果了。这两个函数都不具备可重入性,不要有多个任务同时调用这两个函数。,测量,PC_DisplayChar,(),的执行时间(,us,),测量代码执行时间的程序,INT16U time;,PC_ElapsedInit,();,.,PC_ElapsedStart,();,PC_DispChar(40, 24, A, DISP_FGND_WHITE);,time =,PC_ElapsedStop,();,应用,C,/OS-II,的范例,用,BC IDE (Integrated Development Environment),编译通过,在,WindowsXP,的,DOS,窗口下编译运行。可执行代码在每个范例的,OBJ,子目录中。,IDE,中编译选项,Code generation,Model: Large,Options: Treat,enums,as,ints,Assume SS Equals DS: Default for memory model,Advanced code generation,Floating point: Emulation,Instruction set: 80186,Options: Generate underbars,Debug info in,OBJs,Fast floating point,IDE,中编译选项,Optimizations,Global register allocation,Invariant code motion,Induction variables,Loop optimization,Suppress redundant loads,Copy propagation,Dead code elimination,Jump optimization,In-line intrinsic functions,IDE,中编译选项,Register variables,Automatic,Common,subexpressions,Optimize globally,Optimize for,Speed,例,1,有,13,个任务,(,包括,C,/OS-II,的空闲任务和一个计算,CPU,利用率的任务)。,TaskStart,(),在函数,main(),中建立,功能是建立其它任务并且在屏幕上显示如下统计信息:,每秒钟任务切换次数;,CPU,利用百分率;寄存器切换次数;目前日期和时间;,C,/OS-II,的版本号;,TaskStart,(),还检查是否按下,ESC,键,以决定是否返回到,DOS,。,其余,10,个任务基于相同的代码,Task(),;每个任务在屏幕上随机的位置显示一个,0,到,9,的数字。,main(),main(),程序从清整个屏幕开始,为的是保证屏幕上不留有以前的,DOS,下的显示。,用户在使用任何服务之前先调用,OSInit,(),。建立两个任务:空闲任务和统计任务,前者在没有其它任务处于就绪态时运行;后者计算,CPU,的利用率。,main(),程序,void main (void),PC_DispClrScr(DISP_FGND_WHITE,+ DISP_BGND_BLACK); (1),OSInit,(); (2),PC_DOSSaveReturn,(); /,保存,当前,DOS,环境,(3),PC_VectSet(uCOS,OSCtxSw,); /,设置,CPU,寄存器切换,(4),RandomSem,= OSSemCreate(1); /,信号量置为,1,,在某一时刻只有一个任务可以调用随机数产生函数,(5),OSTaskCreate(TaskStart, (void *)0, /,启动多任务,OSStart,(),之前,用户至少要先建立一个任务如,TaskStart,(),(void*) (6),OSStart,(); /,启动多任务,(7),OSInit,(),初始化,【,在,OS_CORE.C,中定义,】,void,OSInit,(void)#if OS_VERSION = 204,OSInitHookBegin,();/,系统初始化开始接口函数,#,endif,OS_InitMisc,(); /,初始化变量,OS_InitRdyList,(); /,初始化任务就绪列表,OS_InitTCBList,(); /,初始化任务控制块列表,OS_InitEventList,(); /,初始化事件控制块列表,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_InitTaskIdle,(); /,创建空闲任务,(,无条件,),#if OS_TASK_STAT_EN 0,OS_InitTaskStat,(); /,创建统计任务,#,endif,#if OS_VERSION = 204,OSInitHookEnd,(); /,系统初始化结束接口函数,#,endif,#if OS_VERSION = 270 & OS_DEBUG_EN 0,OSDebugInit,();,#,endif,OS_InitMisc,(),初始化变量,OSIntNesting,= 0; /,清除中断嵌套计数器,OSLockNesting,= 0;/,清除调度锁定计数器,OSTaskCtr,= 0; /,任务数清零,OSRunning,= FALSE; /,系统多任务没有执行,OSIdleCtr,= 0L; /,清除空闲任务计数器,OSCtxSwCtr,= 0;/,清除程序切换计数器,OS_InitRdyList,(),初始化任务就绪列表,static void,OS_InitRdyList,(void) INT8U i; INT8U *,prdytbl,;,OSRdyGrp,= 0x00; /,清除任务就绪表,prdytbl,= /,将,OSRdyTbl,数组全部初始化,0,for (i = 0; i OS_RDY_TBL_SIZE; i+) *,prdytbl,+ = 0x00; /,把任务就绪表里面所有的项目全部清零,OSPrioCur,= 0; /,当前运行任务的优先级寄存器清零,OSPrioHighRdy,= 0; /,将处于就绪状态的最高优先级的任务寄存器清零,OSTCBHighRdy,= (OS_TCB *)0;/,将处于就绪态的最高优先级的任务控制块指针寄存器清零,OSTCBCur,= (OS_TCB *)0; /,将当前运行任务的任务控制块指针寄存器清零,OSTCBList,= (OS_TCB *)0; /,任务控制块列表清零,for (i = 0; i (OS_LOWEST_PRIO + 1); i+) ,OSTCBPrioTbli, = (OS_TCB *)0; /,清除优先级列表,这个列表存储各个优先级对应的任务控制块的地址,系统用它来寻找下一个要运行的任务地址,OS_InitTCBList,(),初始化任务控制块列表,static 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 = /,任务控制块列表的第一个任务块地址给变量,PTCB1,ptcb2 = /,任务控制块列表的第二个任务块地址给变量,PTCB2,for (i = 0; i ,OSTCBNext,= ptcb2;#if OS_TASK_NAME_SIZE 1 ptcb1-OSTCBTaskName0 = ?; /* Unknown name */ ptcb1-OSTCBTaskName1 = OS_ASCII_NUL;/,把前一个任务控制块的下一个任务指针指向下一个任务控制块,#,endif,ptcb1+; ptcb2+; 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,= /,把第一个任务控制块的地址送给空闲任务控制块列表,建立其它任务的任务,TaskStart,(),void,TaskStart,(void *data),Prevent compiler warning by assigning data to itself;,Display banner identifying this as EXAMPLE #1; (1),/,在屏幕顶端显示一个标识,说明这是例,1,。,OS_ENTER_CRITICAL();,PC_VectSet(0x08,OSTickISR,); (2),PC_SetTickRate(200); (3),/,关中断,以改变中断向量,让其指向,C,/OS-II,的时钟节拍处理,然后,改变时钟节拍为,200Hz,OS_EXIT_CRITICAL();,建立其它任务的任务,TaskStart,(),(续),Initialize the statistic task by calling ,OSStatInit,(); (4),Create 10 identical tasks; /,建立,10,个同样的任务,(5),for (;) ,Display the number of tasks created;,Display the % of CPU used;,Display the number of task switches in 1 second;,Display,uC/OS-IIs,version number,If (key was pressed) ,if (key pressed was the ESCAPE key) ,PC_DOSReturn,(); ,Delay for 1 Second;,测试,CPU,速度,void,OSStatInit,(void), OSTimeDly(2); /,延时两个时钟节拍,(1),OS_ENTER_CRITICAL();,OSIdleCtr,= 0L; /32,位的计数器,OSIdleCtr,被清,0,,并产生另一个延时,这个延时使,OSStatInit,(),挂起 。,(2) OS_EXIT_CRITICAL();,/,uCOS,-II,执行,一个无,限,循环,的空闲任务,,不断的递增OSIdleCtr,OSTimeDly(OS_TICKS_PER_SEC,); (3) OS_ENTER_CRITICAL();,OSIdleCtrMax,=,OSIdleCtr,; (4),OSStatRdy,= TRUE; /,COS,-II,将统计,CPU,的利用率,(5),OS_EXIT_CRITICAL(); ,在屏幕随机位置显示任务号(,0,9,),void Task (void *data), UBYTE x;,UBYTE y;,UBYTE err;,for (;) ,OSSemPend(RandomSem, 0, /,获取信号量,RandomSem,,同时禁止其他任务运行这段代码,(1),x = random(80); /,获得一个随机数,(2),y = random(16); /,获得一个随机数,OSSemPost(RandomSem,); /,计算出,x,和,y,坐标并,释放信号量,(3),PC_DispChar(x, y + 5, *(char *)data, DISP_FGND_LIGHT_GRAY);,/,在计算的坐标处显示其任务号(,0-9,),(4),OSTimeDly(1); /,延时一个时钟节拍,,等待进入下一次循环,(5),例,1,的运行结果,例,2,磁盘文件为,SOFTWAREuCOS-IIEX2_x86L,,它包含,9,个任务。加上,uCOS,-II,本身的两个任务:空闲任务(,idle task,)和统计任务,共,11,个任务。,由,main,()中的,TaskStart,()函数建立任务,功能是建立其他任务并在屏幕上显示如下的统计数据:,每秒种任务切换的次数;,CPU,利用率的百分比;,当前日期和时间;,uCOS_II,的版本号;,使用带扩展功能的任务建立函数,OSTaskCreateExt,()和,uCOS,-II,的堆栈检查操作(要使用堆栈检查操作必须用,OSTaskCreateExt,()建立任务)。,C,/OS-II stack checking,uCOS,-II,的堆栈检查功能要求任务建立时堆栈清零。,OSTaskCreateExt,(),可以执行此项操作(设置选项,OS_TASK_OPT_STK_CHK,和,OS_TASK_OPT_STK_CLR,打开此项操作)。,OSTaskCreateExt,(),进行堆栈清零操作是一项很费时的工作,取决于堆栈的大小。执行堆栈检查操作的时候,,uCOS,-II,从栈底向栈顶搜索非,0,元素,(,参看上图,),,同时用一个计数器记录,0,元素的个数。,main(),例,2,的,main(),函数和例,1,的看起来差不多;,有两点区别:第一,,main(),函数调用,PC_ElapsedInit,(),来初始化定时器记录,OSTaskStkChk,(),的执行时间。第二,所有的任务都使用,OSTaskCreateExt,(),函数来建立(替代了,OSTaskCreate,()函数),这使得每一个任务都可进行堆栈检查。,例,2,中的,Main,()函数,void main (void),PC_DispClrScr(DISP_FGND_WHITE,+ DISP_BGND_BLACK);,OSInit,();,PC_DOSSaveReturn,();,PC_VectSet(uCOS,OSCtxSw,);,PC_ElapsedInit,(); (1) /,对消逝时间的测量进行初始化,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,(),还需要五个参数:任务的,ID,,一个指向任务堆栈栈底的指针,堆栈的大小(以堆栈单元为单位,,80X86,中为字),一个指向用户定义的,TCB,扩展数据结构的指针,和一个用于指定对任务操作的变量。,TaskStart,(),TaskStart,()建立两个邮箱,分别提供给任务,4,和任务,5,。,接着建立一个专门显示时间和日期的任务,随后又建立,5,个不同的任务。,TaskStart,(),的伪码,void,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,(),以上几项操作和例,1,中的相同。,TaskStart,(),的伪码(续),Create 2 mailboxes which are used by Task #4 and #5; (1),/,调用,TaskStartCreateTasks(void,),Create a task that will display the date and time on the screen;(2),Create 5 application tasks;,for (;) ,Display #tasks running;,Display CPU usage in %;,Display #context 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,个邮箱,通过调用,2,个,OSMboxCreate(void,*)0),函数,创建,2,个邮箱。,这,2,个邮箱在任务,4,与任务,5,中使用。,TaskStartCreateTasks,(,void,),static void,TaskStartCreateTasks,(void),OSTaskCreateExt(,TaskClk, (void *)0,&,TaskClkStk,TASK_STK_SIZE,- 1,TASK_CLK_PRIO,TASK_CLK_ID,&TaskClkStk0,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,&Task1Stk0,TASK_STK_SIZE, (void *)0,OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR);,OSTaskCreateExt(,Task5, .);,时钟显示任务,TaskClk,(),函数用于显示当前日期和时间,每秒更新一次。,时钟显示任务程序,void,TaskClk,(void *data),Struct,time now;,Struct,date today;,char s40;,data =,data,;,for (;) ,PC_GetDateTime(s,);,PC_DispStr(0, 24, s,DISP_FGND_BLUE + DISP_BGND_CYAN);,OSTimeDly(OS_TICKS_PER_SEC,);,任务,1,任务,1,将检查其他七个任务堆栈的大小,同时记录,OSTackStkChk,(),函数的执行时间,并与堆栈大小(所有堆栈的大小都是以字节为单位)一起显示出来。任务,1,每秒执行,10,次(间隔,100ms,)。,任务,1,程序,void Task1 (void *,pdata,), INT8U err;,OS_STK_DATA data; /,任务堆栈数据,INT16U time; /,执行时间(,us,),INT8U i;,char s80;,pdata,=,pdata,;,任务,1,程序 (续),for (;) ,for (i = 0; i 7; i+) ,PC_ElapsedStart,(); (1),err =,OSTaskStkChk(TASK_START_PRIO+i, ,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,任务,2,任务,2,在屏幕上显示一个顺时针旋转的指针(用横线,斜线等字符表示),每,200ms,旋转一格。,任务,2,程序,void 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_FGND_WHITE + DISP_BGND_RED);,OSTimeDly(10);,PC_DispChar(70, 15, ,DISP_FGND_WHITE + DISP_BGND_RED);,OSTimeDly(10); ,任务,3,任务,3,也显示了一个旋转指针,但是与任务,2,旋转的方向不同。任务,3,在堆栈中分配了一个很大的数组,将堆栈填充掉,使得,OSTaskStkChk,(),只需花费很少的时间来确定堆栈的利用率,尤其是当堆栈已经快满的时候。,任务,3,程序,void 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(70, 16, -,DISP_FGND_WHITE + DISP_BGND_BLUE);,OSTimeDly(20);,PC_DispChar(70, 16, /,DISP_FGND_WHITE + DISP_BGND_BLUE);,OSTimeDly(20); ,任务,4,任务,4,向任务,5,发送消息并等待确认。发送的消息是一个指向字符的指针。每当任务,4,从任务,5,收到确认,就将传递的,ASCII,码加,1,再发送,结果是不断的传送“,ABCDEFG.”,。,任务,4,程序,void Task4 (void *data), char,txmsg,;,INT8U err;,data =,data,;,txmsg,= A;,任务,4,程序 (续),for (;) ,while (,txmsg,= Z),OSMboxPost(TxMbox, (void *)&,txmsg,); (1),/,向任务,5,发送消息,OSMboxPend(AckMbox, 0, (2),/,等待任务,5,的应答,txmsg,+; (3) /,发送下一条消息,txmsg,= A; /,开始一个新的消息序列,任务,5,当任务,5,接收消息后(发送的字符),就将消息显示到屏幕上,然后延时,1,秒,再向任务,4,发送确认信息。,任务,5,程序,void Task5 (void *data), char *,rxmsg,;,INT8U err;,data =,data,;,任务,5,程序 (续),for (;) ,rxmsg,= (char *),OSMboxPend(TxMbox, 0, (1),/,等待任务,4,的消息,PC_DispChar(70, 18, *,rxmsg,DISP_FGND_YELLOW+DISP_BGND_RED); (2),OSTimeDlyHMSM(0, 0, 1, 0); (3) /,延时等待,1s,OSMboxPost(AckMbox, (void *)1); (4),/,接收到消息的应答,例,2,的运行结果,例,3,使用了,uCOS,-II,提供的许多附加功能。,使用了,OSTaskCreateExt,(),中,TCB,的扩展数据结构,用户定义的任务切换对外接口函数(,OSTaskSwHook,(),),用户定义的统计任务(,statistic task,)的对外接口函数(,OSTaskStatHook,(),)以及消息队列。,例,3,的磁盘文件位于,SOFTWAREuCOS-IIEX3_x86L,。除了空闲任务(,idle task,)和统计任务(,statistic task,),还有,7,个任务,总共,9,个任务。,main(),main(),函数和例,2,中的相差不多;,不同的是在用户定义的,TCB,扩展数据结构中可以保存每个任务的名称(扩展结构的声明在,INCLUDES.H,中定义)。,定义了,30,个字节来存放任务名(包括空格)。本例中没有用到堆栈检查操作,,TaskStart,(),中禁止该操作。,main(),函数,void main (void),PC_DispClrScr(DISP_FGND_WHITE,+ DISP_BGND_BLACK);,OSInit,();,PC_DOSSaveReturn,();,PC_VectSet(uCOS,OSCtxSw,);,PC_ElapsedInit,();,Strcpy(TaskUserDataTASK_START_ID.TaskName, ,StartTask,); (1),OSTaskCreateExt(TaskStart, (void *)0, /,禁止堆栈检查,&TaskStartStkTASK_STK_SIZE-1, TASK_START_PRIO,TASK_START_ID, &TaskStartStk0, TASK_STK_SIZE,&,TaskUserDataTASK_START_ID, 0); (2),OSStart,();,TCB,扩展数据结构,typedef,struct, char TaskName30; (1),INT16U,TaskCtr,;,INT16U,TaskExecTime,;,INT32U,TaskTotExecTime,;, TASK_USER_DATA;,定义了,30,个字节来存放任务名(包括空格),TaskStart,(),与例,2,有,3,处不同:,为任务,1,,,2,,,3,建立了一个消息队列;,每个任务都有一个名字,保存在任务的,TCB,扩展数据结构中;,禁止堆栈检查。,TaskStart,(),的伪码,void,TaskStart,(void *data), Prevent compiler warning by assigning data to itself;,Display a banner and non-changing text;,Install,uC/OS-IIs,tick handler;,Change the tick rate to 200 Hz;,Initialize the statistics task;,TaskStart,(),的伪码 (续),Create a message queue; (1) /,为任务,1,,,2,,,3,建立一个消息队列,/,调用,TaskStartCreateTasks,(),创建任务,Create a task that will display the date and time on the screen;,Create 5 application tasks with a name stored in the TCB ext.; (2),/,每个任务的名字都保存在任务的,TCB,扩展数据结构中,for (;) Display #tasks running;,Display CPU usage in %;,Display #context 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; ,为任务,1,,,2,,,3,建立一个消息队列,MsgQueue,= OSQCreate(,TaskStartCreateTasks,(),void,TaskStartCreateTasks,(void),strcpy(TaskUserData,TASK_CLK,_ID.TaskName, Clock Task);,OSTaskCreateExt(,TaskClk, (void *)0, &,TaskClk,StkTASK_STK_SIZE,- 1,TASK_CLK,_PRIO,TASK_CLK,_ID, &,TaskClk,Stk0, TASK_STK_SIZE,&TaskUserData,TASK_CLK,_ID,0); /,创建显示日期与时间的任务,strcpy(TaskUserData,TASK_1,_ID.TaskName, ,MsgQ,Rx Task);,OSTaskCreateExt(,Task1,(void *)0, &,Task1,StkTASK_STK_SIZE - 1,TASK_1,_PRIO,TASK_1,_ID, &,Task1,Stk0,TASK_STK_SIZE,&TaskUserData,TASK_1,_ID,0); /,创建任务,1,-,strcpy(TaskUserData,TASK_5,_ID.TaskName, ,TimeDlyTask,);,OSTaskCreateExt(,Task5,(void *)0,&,Task5,StkTASK_STK_SIZE - 1,TASK_5,_PRIO,TASK_5,_ID,&,Task5,Stk0,TASK_STK_SIZE,&TaskUserData,TASK_5,_ID,0); /,创建任务,5,时钟显示任务,TaskClk,(),函数用于显示当前日期和时间。,与例,2,类似。,任务,1,任务,1,向消息队列发送一个消息,然后延时等待消息发送完成。这段时间可以让接收消息的任务显示收到的消息。,发送的消息有三种。,任务,1,程序,void Task1 (void *data), char one = 1; char two = 2; char three = 3;,data =,data,;,for (;) /,向消息队列发送一个消息,OSQPost(MsgQueue, (void *) (1),/,延时等待消息发送完成,OSTimeDlyHMSM(0, 0, 1, 0); (2),OSQPost(MsgQueue, (void *),OSTimeDlyHMSM(0, 0, 0, 500);,OSQPost(MsgQueue, (void *),OSTimeDlyHMSM(0, 0, 1, 0); ,任务,2,任务,2,处于等待消息的挂起状态,且不设定最大等待时间。,任务,2,将一直等待直到收到消息。,当收到消息后,任务,2,显示消息并且延时,500mS,,延时的时间可以使任务,3,检查消息队列。,任务,2,程序,void Task2 (void *data), INT8U *,msg,; INT8U err; data =,data,;,for (;) /,处于,等待消息的挂起状态,,且不设定最大等待时间,msg,= (INT8U *),OSQPend(MsgQueue, 0, (1),/,收到消息后显示消息,PC_DispChar(70, 14, *,msg,DISP_FGND_YELLOW+DISP_BGND_BLUE); (2),/,延时,500mS,,同时使任务,3,检查消息队列,OSTimeDlyHMSM(0, 0, 0, 500); (3) ,任务,3,任务,3,同样处于等待消息的挂起状态,但是它设定了等待结束时间,250mS,。,如果有消息来到,任务,3,将显示消息号,如果超过了等待时间,任务,3,就显示“,T”,(意为,timeout,)。,任务,3,程序,void Task3 (void *data), INT8U *,msg,; INT8U err; data =,data,;,for (;) ,msg,= (INT8U *),OSQPend(MsgQueue,OS_TICKS_PER_SEC/4, (1),/,等待消息的挂起状态,设定等待结束时间,250mS,If (err = OS_TIMEOUT),PC_DispChar(70,15,T,DISP_FGND_YELLOW+DISP_BGND_RED); (2),/,如果超
展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 办公文档 > 教学培训


copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!