1、嵌入式操作系统ucOS-II分析ucOS-II应用程序基本结构void task(void*pdata)INT8U err;InitTimer();/可选For(;)/你的应用程序代码 .OSTimeDly(1);/可选一些重要的ucOS-II API)任务类)消息类)同步类)时间类)临界区与事件类任务类和时间类是必须要首先掌握的两种类型的API)OSTaskCreate函数函数 n这个函数应该至少在main函数内调用一次,在OSInit函数调用之后调用,以创建一个任务。n系统首先从TCB空闲列表内申请一个空的TCB指针,然后根据用户给出的参数初始化任务堆栈,并在内部的任务就绪表内标记该任务为
2、就绪状态。最后返回,这样一个任务就创建成功了。)OSTaskSuspend函数函数 n将指定的任务挂起。如果挂起的是当前任务,会引发系统执行任务切换先导函数OSShed来进行一次任务切换。n这个函数只有一个优先级参数,在系统内部,优先级除了表示一个任务执行的先后次序外,还起着区分每一个任务的作用,即优先级也是任务的ID。所以uCOS-II不允许出现相同优先级的任务。)OSTaskResume函数函数 n将指定的已经挂起的任务恢复成就绪状态。如果恢复任务的优先级高于当前任务,那么还会引发一次任务切换。n参数类似OSTaskSuspend函数,为指定任务的优先级。需要特别说明是,本函数并不要求和O
3、STaskSuspend函数成对使用。)OS_ENTER_CRITICAL宏宏 n分析一下OS_CPU.H文件,它涉及特定CPU的实现。一般都被替换为一条或者几条嵌入式汇编代码。其实,它就是关中断。n只要任务不主动放弃CPU使用权,别的任务就没有占用CPU的机会,这个任务就是独占了。进入临界区后,这个应宏尽量少用,它会破坏系统的一些服务,尤其是时间服务。并使系统对外界响应性能降低。)OS_EXIT_CRITICAL宏宏 n与OS_ENTER_CRITICAL配套使用的一个宏,在系统手册说明里它是退出临界区,其实就是重新开中断。n它必须和OS_ENTER_CRITICAL成对出现,否则会带来意想
4、不到的后果,如系统会崩溃。我们应尽量少用这两个宏调用,因为他们的确会破坏系统的多任务性能。)OSTimeDly函数函数 n这是调用最多的一个函数,它的功能是先挂起当前任务,然后进行任务切换,在指定的时间到来之后,将当前任务恢复为就绪状态,但是并不一定运行,如果恢复后是优先级最高的就绪任务话,那么就运行之。n可以将任务延时一定时间后再执行它,依靠时钟机制进行任务切换,暂时放弃CPU的使用权,但多任务性能会降低。ucOS-II范例的源码分析INCLUDES.H nucOS-II中所有的*.C 文件都包括了以下定义:#include includes.h“n唯一的缺点是INCLUDES.H中许多头文
5、件在一些*.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;Ty
6、pedef double 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代表模块的名字。该模块的.C文件中有以下
7、定义:#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#include“includes.h”当编译器处理uCOS_II.C时,它使uCOS_II.H变成如下所示,因为
8、OS_EXT被设置为空。编译器就会将这些全局变量分配到内存中。nINT32U OSIdleCtr;nINT32U OSIdleCtrRun;nINT32U OSIdleCtrMax;当编译器处理其他.C文件时,头文件变成了如下的样子,因为OS_GLOBAL没有定义,所以OS_EXT被定义为extern。nextern INT32U OSIdleCtr;nextern INT32U OSIdleCtrRun;nextern INT32U OSIdleCtrMax;在这种情况下,不产生内存分配,而任何.C文件都可以使用这些变量。这样的就只需在.H 文件中定义一次就可以了。OS_ENTER_CRIT
9、ICAL()和和 OS_EXIT_CRITICAL()nOS_ENTER_CRITICAL()关中断;OS_EXIT_CRITICAL()开中断。n是为了保护临界段代码,这些代码与处理器有关。宏的定义在OS_CPU.H中。n关中断会影响中断延迟,所以要特别小心。用户还可以用信号量来保护临界段代码。基于PC的服务 nPC.C 文件和 PC.H 文件是范例中使用到的一些基于PC的服务程序。nPC.C包括字符显示,时间度量和其他各种服务。所有的函数都以PC_为前缀。字符显示 nPC_DispClrScr()Clear the screennPC_DispClrLine()Clear a single
10、 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()之间来测量。在用这两个函数之前,应该调用PC_ElapsedInit()来初始化,它主要是计算运行这两个函数本身所附加的的时间。这样,PC_ElapsedSt
11、op()函数中返回的数值就是准确的测量结果了。这两个函数都不具备可重入性,不要有多个任务同时调用这两个函数。测量PC_DisplayChar()的执行时间(us)n测量代码执行时间的程序测量代码执行时间的程序INT16U time;PC_ElapsedInit();.PC_ElapsedStart();PC_DispChar(40,24,A,DISP_FGND_WHITE);time=PC_ElapsedStop();应用应用 C/OS-II 的范例的范例 n用BC IDE(Integrated Development Environment)编译通过,在WindowsXP 的DOS窗口下编译
12、运行。可执行代码在每个范例的OBJ子目录中。IDE中编译选项中编译选项nCode generation Model:LargeOptions:Treat enums 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中编译选项中编译选项nOptimizationsGlo
13、bal register allocation Invariant code motion Induction variables Loop optimization Suppress redundant loads Copy propagation Dead code elimination Jump optimization In-line intrinsic functionsIDE中编译选项中编译选项nRegister variables AutomaticnCommon subexpressions Optimize globallynOptimize for Speed例例1n有1
14、3个任务(包括 C/OS-II 的空闲任务和一个计算CPU利用率的任务)。TaskStart()在函数main()中建立,功能是建立其它任务并且在屏幕上显示如下统计信息:n每秒钟任务切换次数;CPU利用百分率;寄存器切换次数;目前日期和时间;C/OS-II的版本号;n TaskStart()还检查是否按下ESC键,以决定是否返回到DOS。n其余10个任务基于相同的代码Task();每个任务在屏幕上随机的位置显示一个0到9的数字。main()nmain()程序从清整个屏幕开始,为的是保证屏幕上不留有以前的DOS下的显示。n用户在使用任何服务之前先调用OSInit()。建立两个任务:空闲任务和统计
15、任务,前者在没有其它任务处于就绪态时运行;后者计算CPU的利用率。main()程序程序nvoid 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(
16、)之前,用户至少要先建立一个任务如TaskStart()(void*)&TaskStartStkTASK_STK_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();/初始化事件控制块列表 OS
17、Init()初始化(续)#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();/消息队列初始化#endifOS_InitTaskIdle();/创建空闲任务(无条件)#if OS_TASK_STAT_EN 0 OS_InitTaskStat();/创建统计任务#endif#if OS_V
18、ERSION=204 OSInitHookEnd();/系统初始化结束接口函数#endif#if OS_VERSION=270&OS_DEBUG_EN 0 OSDebugInit();#endifOS_InitMisc()初始化变量 nOSIntNesting =0;/清除中断嵌套计数器 nOSLockNesting=0;/清除调度锁定计数器 nOSTaskCtr =0;/任务数清零nOSRunning =FALSE;/系统多任务没有执行 nOSIdleCtr =0L;/清除空闲任务计数器nOSCtxSwCtr =0;/清除程序切换计数器 OS_InitRdyList()初始化任务就绪列表 n
19、static void OS_InitRdyList(void)INT8U i;INT8U *prdytbl;OSRdyGrp =0 x00;/清除任务就绪表 prdytbl =&OSRdyTbl0;/将OSRdyTbl数组全部初始化0 for(i=0;i OS_RDY_TBL_SIZE;i+)*prdytbl+=0 x00;/把任务就绪表里面所有的项目全部清零 OSPrioCur =0;/当前运行任务的优先级寄存器清零 OSPrioHighRdy=0;/将处于就绪状态的最高优先级的任务寄存器清零 OSTCBHighRdy =(OS_TCB*)0;/将处于就绪态的最高优先级的任务控制块指针寄存
20、器清零 OSTCBCur =(OS_TCB*)0;/将当前运行任务的任务控制块指针寄存器清零 OSTCBList =(OS_TCB*)0;/任务控制块列表清零 for(i=0;i (OS_LOWEST_PRIO+1);i+)OSTCBPrioTbli=(OS_TCB*)0;/清除优先级列表,这个列表存储各个优先级对应的任务控制块的地址,系统用它来寻找下一个要运行的任务地址OS_InitTCBList()初始化任务控制块列表nstatic void OS_InitTCBList(void)INT8U i;OS_TCB *ptcb1;OS_TCB *ptcb2;OS_MemClr(INT8U*)&
21、OSTCBTbl0,sizeof(OSTCBTbl);/清除TCB OS_MemClr(INT8U*)&OSTCBPrioTbl0,sizeof(OSTCBPrioTbl);/清除优先级表 ptcb1=&OSTCBTbl0;/任务控制块列表的第一个任务块地址给变量PTCB1 ptcb2=&OSTCBTbl1;/任务控制块列表的第二个任务块地址给变量PTCB2 for(i=0;i OSTCBNext=ptcb2;#if OS_TASK_NAME_SIZE 1 ptcb1-OSTCBTaskName0=?;/*Unknown name */ptcb1-OSTCBTaskName1=OS_ASCII
22、_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 =&OSTCBTbl0;/把第一个任务控制块的地址送给空闲任务控制块列表 建立其它任务的任务建立其它
23、任务的任务 TaskStart()nvoid 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(0 x08,OSTickISR);(2)PC_SetTickRate(200);(3)/关中断,以改变中断向量,让其指向C/OS-II的时钟节拍处理,然后,改变时钟节拍为 200Hz OS_EXIT_CRITI
24、CAL();建立其它任务的任务建立其它任务的任务 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 pr
25、essed)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);
26、(3)OS_ENTER_CRITICAL();OSIdleCtrMax=OSIdleCtr;(4)OSStatRdy =TRUE;/COS-II将统计CPU的利用率 (5)OS_EXIT_CRITICAL();在屏幕随机位置显示任务号(09)void Task(void*data)UBYTE x;UBYTE y;UBYTE err;for(;)OSSemPend(RandomSem,0,&err);/获取信号量RandomSem,同时禁止其他任务运行这段代码 (1)x=random(80);/获得一个随机数 (2)y=random(16);/获得一个随机数 OSSemPost(RandomSe
27、m);/计算出x和y坐标并释放信号量 (3)PC_DispChar(x,y+5,*(char*)data,DISP_FGND_LIGHT_GRAY);/在计算的坐标处显示其任务号(0-9)(4)OSTimeDly(1);/延时一个时钟节拍,等待进入下一次循环 (5)例1的运行结果例例2n磁盘文件为SOFTWAREuCOS-IIEX2_x86L,它包含9个任务。加上uCOS-II本身的两个任务:空闲任务(idle task)和统计任务,共11个任务。n由main()中的TaskStart()函数建立任务,功能是建立其他任务并在屏幕上显示如下的统计数据:每秒种任务切换的次数;CPU利用率的百分比;
28、当前日期和时间;uCOS_II的版本号;n使用带扩展功能的任务建立函数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从栈底向栈顶搜索
29、非0元素(参看上图),同时用一个计数器记录0元素的个数。main()n例2的main()函数和例1的看起来差不多;n有两点区别:第一,main()函数调用PC_ElapsedInit()来初始化定时器记录OSTaskStkChk()的执行时间。第二,所有的任务都使用OSTaskCreateExt()函数来建立(替代了OSTaskCreate()函数),这使得每一个任务都可进行堆栈检查。例例2中的中的Main()函数()函数 nvoid main(void)PC_DispClrScr(DISP_FGND_WHITE+DISP_BGND_BLACK);OSInit();PC_DOSSaveRetu
30、rn();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()还需要五个参数
31、:任务的ID,一个指向任务堆栈栈底的指针,堆栈的大小(以堆栈单元为单位,80X86中为字),一个指向用户定义的TCB扩展数据结构的指针,和一个用于指定对任务操作的变量。TaskStart()nTaskStart()建立两个邮箱,分别提供给任务4和任务5。n接着建立一个专门显示时间和日期的任务,随后又建立5个不同的任务。TaskStart()的伪码 nvoid TaskStart(void*data)Prevent compiler warning by assigning data to itself;Display a banner and non-changing text;Install
32、 uC/OS-IIs tick handler;/关中断,PC_VectSet()Change the tick rate to 200 Hz;/PC_SetTickRate(),开中断 Initialize the statistics task;/OSStatInit()以上几项操作和例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 t
33、ime on the screen;(2)nCreate 5 application tasks;nfor(;)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个邮箱n通过调用2个OSMbo
34、xCreate(void*)0)函数,创建2个邮箱。n这2个邮箱在任务4与任务5中使用。TaskStartCreateTasks(void)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(
35、Task1,(void*)0,n&Task1StkTASK_STK_SIZE-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;data=data;for(
36、;)PC_GetDateTime(s);PC_DispStr(0,24,s,DISP_FGND_BLUE+DISP_BGND_CYAN);OSTimeDly(OS_TICKS_PER_SEC);任务1n任务1将检查其他七个任务堆栈的大小,同时记录OSTackStkChk()函数的执行时间,并与堆栈大小(所有堆栈的大小都是以字节为单位)一起显示出来。任务1每秒执行10次(间隔100ms)。任务1程序 nvoid Task1(void*pdata)INT8U err;OS_STK_DATA data;/任务堆栈数据 INT16U time;/执行时间(us)INT8U i;char s80;pda
37、ta=pdata;任务1程序(续)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
38、任务2 n任务2在屏幕上显示一个顺时针旋转的指针(用横线,斜线等字符表示),每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_FGND_WHITE+DISP_BGND_RED);OSTimeDly(10);PC_Di
39、spChar(70,15,DISP_FGND_WHITE+DISP_BGND_RED);OSTimeDly(10);任务3 n任务3也显示了一个旋转指针,但是与任务2旋转的方向不同。任务3在堆栈中分配了一个很大的数组,将堆栈填充掉,使得OSTaskStkChk()只需花费很少的时间来确定堆栈的利用率,尤其是当堆栈已经快满的时候。任务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
40、+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 n任务4向任务5发送消息并等待确认。发送的消息是一个指向字符的指针。每当任务4从任务5收到确认,就将传递的ASCII码加1再发送,结果是不
41、断的传送“ABCDEFG.”。任务4程序nvoid Task4(void*data)char txmsg;INT8U err;data =data;txmsg=A;任务4程序(续)for(;)while(txmsg OSTCBExtPtr;(3)if(puser!=(void*)0)(4)/如果任务分配了TCB扩展数据结构 puser-TaskCtr+;(5)/计数器TaskCtr进行累加以统计任务被切换的频繁程度,或检查某个任务是否在运行。puser-TaskExecTime=time;(6)/记录函数从切入到切出的运行时间 puser-TaskTotExecTime+=time;(7)/记
42、录任务总的运行时间 OSTaskStatHook()函数 n本例的统计任务(statistic task)通过OS_TaskStat()调用对外接口函数OSTaskStatHook()(设置OS_CFG.H文件中的OS_TASK_STAT_EN为1,允许对外接口函数),统计任务每秒运行一次。n对OSTaskSwHook()中每个任务的TaskExecTime与TaskTotExecTime两个变量进行统计,可以计算出一段时间内各个任务所占用CPU的百分比。nOSTaskStatHook()函数会显示这些统计信息。用户定义的OSTaskStatHook()nvoid OSTaskStatHook
43、(void)char s80;INT8U i;INT32U total;INT8U pct;total=0L;for(I=0;i 0)for(i=0;i 1000000000L)for(i=0;i 7;i+)TaskUserDatai.TaskTotExecTime=0L;例3的运行结果例例4n与例4相关的磁盘文件位于SOFTWAREuCOS-IIIx86L-FP和SOFTWAREuCOS-IIEX4_x86L.FP中。除了空闲任务(idle task)和统计任务(statistic task),还有10个相同的任务,总共13个任务。TaskStart()在函数main()中建立,功能是建立其
44、它任务并且在屏幕上显示如下统计信息:任务总数;每秒钟任务切换次数;CPU利用率;C/OS-II的版本号;n其余10个任务基于同一代码Task();每个任务按任务序号110(优先级顺序)显示相应的角度、角度的余弦和角度的正弦。main()nmain()函数和前3例中的相差不多;n不同的是创建了10个相同的任务,并且对于每个任务,均设定为OS_TASK_OPT_SAVE_FP(支持统计任务的浮点运算)。main()函数函数 nvoid main(void)PC_DispClrScr(DISP_FGND_WHITE+DISP_BGND_BLACK);OSInit();PC_DOSSaveReturn
45、();PC_VectSet(uCOS,OSCtxSw);OSTaskCreateExt(TaskStart,(void*)0,TaskStartStkTASK_STK_SIZE-1,0,/任务优先级为0(最高)0,&TaskStartStk0,TASK_STK_SIZE,(void*)0,OS_TASK_OPT_SAVE_FP);/支持浮点运算 OSStart();TaskStart()函数n与前例1差不多,主要功能是显示相关的统计信息,并且调用TaskStartCreateTasks()创建10个相同的任务。TaskStartCreateTasks()函数nstatic void TaskStartCreateTasks(void)INT8U i;INT8U prio;for(i=0;i=(FP32)360.0)angle =(FP32)0.0;else angle+=(FP32)0.01;OSTimeDly(1);例4的运行结果
侵权处理QQ:3464097650--上传资料QQ:3464097650
【声明】本站为“文档C2C交易模式”,即用户上传的文档直接卖给(下载)用户,本站只是网络空间服务平台,本站所有原创文档下载所得归上传人所有,如您发现上传作品侵犯了您的版权,请立刻联系我们并提供证据,我们将在3个工作日内予以改正。