Typedef unsigned char BOOLEAN Typedef unsigned char INT
不依赖于编译的数据类型 可移植型数据类型的程序 Typedef unsigned char BOOLEAN; Typedef unsigned char INT 8 U; Typedef signed char INT 8 S; Typedef unsigned int INT 16 U; Typedef signed int INT 16 S; Typedef unsigned long INT 32 U; Typedef signed long INT 32 S; Typedef float FP 32; Typedef double FP 64; #define BYTE INT 8 S ------| #define UBYTE INT 8 U ------| #define WORD INT 16 S ------| ucos->ucos. II #define UWORD INT 16 U ------| #define LONG INT 32 S ------| #define ULONG INT 32 U ------|
全局变量 定义全局宏的程序 #ifdef xxx_GLOBALS #define xxx_EXT #else #define xxx_EXT extern #endif. H 文件中每个全局变量都加上了xxx_EXT的前缀。xxx 代表模块的名字。该模块的. C文件中有以下定义: #define xxx_GLOBALS #include "includes. h" n
u. COS_II. H中有以下定义: n n n n #ifdef OS_GLOBALS #define OS_EXT #else #define OS_EXT extern #endif OS_EXT INT 32 U OSIdle. Ctr; OS_EXT INT 32 U OSIdle. Ctr. Run; OS_EXT INT 32 U OSIdle. Ctr. Max;
u. COS_II. C中有以下定义: #define OS_GLOBALS n #include “includes. h” 当编译器处理u. COS_II. C时,它使 u. COS_II. H变成如下所示,因为OS_EXT被 设置为空。编译器就会将这些全局变量分配 到内存中。 n INT 32 U OSIdle. Ctr; n INT 32 U OSIdle. Ctr. Run; n INT 32 U OSIdle. Ctr. Max; n
字符显示 n n PC_Disp. Clr. Scr() Clear the screen PC_Disp. Clr. Line() Clear a single row (or line) PC_Disp. Char() Display a single ASCII character anywhere on the screen PC_Disp. Str() Display an ASCII string anywhere on the screen
测量PC_Display. Char()的执 行时间(us) 测量代码执行时间的程序 INT 16 U time; PC_Elapsed. Init(); . . PC_Elapsed. Start(); PC_Disp. Char(40, 24, ‘A’, DISP_FGND_WHITE); time = PC_Elapsed. Stop(); n
IDE中编译选项 Code generation Model: Large Options: Treat enums as ints Assume SS Equals DS: Default for memory model n Advanced code generation Floating point: Emulation Instruction set: 80186 Options: Generate underbars Debug info in OBJs Fast floating point n
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 n
IDE中编译选项 n n n Register variables Automatic Common subexpressions Optimize globally Optimize for Speed
main()程序 n void main (void) { PC_Disp. Clr. Scr(DISP_FGND_WHITE + DISP_BGND_BLACK); (1) OSInit(); (2) PC_DOSSave. Return(); /保存当前DOS环境 (3) PC_Vect. Set(u. COS, OSCtx. Sw); /设置任务切换处理函数 (4) Random. Sem = OSSem. Create(1); /信号量置为 1,在某一时刻只 有一个任务可以调用随机数产生函数 (5) OSTask. Create(Task. Start, (void *)0, /启动多任务 OSStart()之前,用户至少要先建立一个任务如Task. Start() (void*)&Task. Start. Stk[TASK_STK_SIZE-1], 0); (6) OSStart(); /启动多任务 (7)
OSInit()初始化【在OS_CORE. C中定义 】 void OSInit (void) { #if OS_VERSION >= 204 OSInit. Hook. Begin(); /系统初始化开始接口函数 #endif OS_Init. Misc(); /初始化变量 OS_Init. Rdy. List(); /初始化任务就绪列表 OS_Init. TCBList(); /初始化任务控制块列表 OS_Init. Event. List(); /初始化事件控制块列表
OSInit()初始化(续) #if (OS_VERSION >= 251) && (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) OS_Flag. Init(); /事件标志结构初始化 #endif #if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) OS_Mem. Init(); /内存管理初始化 #endif #if (OS_Q_EN > 0) && (OS_MAX_QS > 0) OS_QInit(); /消息队列初始化 #endif OS_Init. Task. Idle(); /创建空闲任务(无条件) #if OS_TASK_STAT_EN > 0 OS_Init. Task. Stat(); /创建统计任务 #endif #if OS_VERSION >= 204 OSInit. Hook. End(); /系统初始化结束接口函数 #endif #if OS_VERSION >= 270 && OS_DEBUG_EN > 0 OSDebug. Init(); #endif }
OS_Init. TCBList()初始化任务控制块列表 n static void OS_Init. TCBList (void) { INT 8 U i; OS_TCB *ptcb 1; OS_TCB *ptcb 2; OS_Mem. Clr((INT 8 U *)&OSTCBTbl[0], sizeof(OSTCBTbl)); / 清除TCB OS_Mem. Clr((INT 8 U *)&OSTCBPrio. Tbl[0], sizeof(OSTCBPrio. Tbl)); / 清除优先级表 ptcb 1 = &OSTCBTbl[0]; /任务控制块列表的第一个任务块地址给变量PTCB 1 ptcb 2 = &OSTCBTbl[1]; /任务控制块列表的第二个任务块地址给变量PTCB 2 for (i = 0; i < (OS_MAX_TASKS + OS_N_SYS_TASKS - 1); i++) { /初始化任务控制块列表 ptcb 1 ->OSTCBNext = ptcb 2; #if OS_TASK_NAME_SIZE > 1 ptcb 1 ->OSTCBTask. Name[0] = '? '; /* Unknown name */ ptcb 1 ->OSTCBTask. Name[1] = OS_ASCII_NUL; /把前一个任务控制块的下一个任务指针指向下 一个任务控制块 #endif ptcb 1++; ptcb 2++; } ptcb 1 ->OSTCBNext = (OS_TCB *)0; /把最后一个任务控制块的下个指针清零 #if OS_TASK_NAME_SIZE > 1 ptcb 1 ->OSTCBTask. Name[0] = ‘? ’; /* Unknown name */ ptcb 1 ->OSTCBTask. Name[1] = OS_ASCII_NUL; #endif OSTCBList = (OS_TCB *)0; /TCB列表初始化 OSTCBFree. List = &OSTCBTbl[0]; /把第一个任务控制块的地址送给空闲任务控制块列 表 }
测试CPU速度 void OSStat. Init (void) { OSTime. Dly(2); /延时两个时钟节拍 OS_ENTER_CRITICAL(); OSIdle. Ctr = 0 L; /32位的计数器OSIdle. Ctr被清0,并产 生另一个延时,这个延时使OSStat. Init()挂起 。 OS_EXIT_CRITICAL(); /u. COS-II执行一个无限循环的空闲任务,不断的递增 OSIdle. Ctr OSTime. Dly(OS_TICKS_PER_SEC); OS_ENTER_CRITICAL(); OSIdle. Ctr. Max = OSIdle. Ctr; OSStat. Rdy = TRUE; /μCOS-II将统计CPU的利用率 OS_EXIT_CRITICAL(); }
例2中的Main()函数 void main (void) { PC_Disp. Clr. Scr(DISP_FGND_WHITE + DISP_BGND_BLACK); OSInit(); PC_DOSSave. Return(); PC_Vect. Set(u. COS, OSCtx. Sw); PC_Elapsed. Init(); /对消逝时间的测量进行初始化 OSTask. Create. Ext(Task. Start, (void *)0, &Task. Start. Stk[TASK_STK_SIZE-1], TASK_START_PRIO, TASK_START_ID, &Task. Start. Stk[0], TASK_STK_SIZE, (void *)0, OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR); (2) OSStart(); } n 除了OSTask. Create()函数的四个参数外,OSTask. Create. Ext()还需要五个参 数:任务的ID,一个指向任务堆栈栈底的指针,堆栈的大小(以堆栈单元为单位 80 X 86中为字),一个指向用户定义的TCB扩展数据结构的指针,和一个用于指 定对任务操作的变量。
Task. Start()的伪码 void Task. Start (void *data) { Prevent compiler warning by assigning ‘data’ to itself; Display a banner and non-changing text; Install u. C/OS-II’s tick handler; /关中断,PC_Vect. Set() Change the tick rate to 200 Hz; /PC_Set. Tick. Rate() ,开中断 Initialize the statistics task; /OSStat. Init() n 以上几项操作和例1中的相同。
Task. Start()的伪码(续) n n n } Create 2 mailboxes which are used by Task #4 and #5; (1) / 调用Task. Start. Create. Tasks(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 u. C/OS-II’s version; If (Key was pressed) { if (Key pressed was the ESCAPE key) {Return to DOS; } } Delay for 1 second; }
Task. Start. Create. Tasks(void) n n n n static void Task. Start. Create. Tasks (void) { OSTask. Create. Ext(Task. Clk, (void *)0, &Task. Clk. Stk[TASK_STK_SIZE - 1], TASK_CLK_PRIO, TASK_CLK_ID, &Task. Clk. Stk[0], TASK_STK_SIZE, (void *)0, OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR); OSTask. Create. Ext(Task 1, (void *)0, &Task 1 Stk[TASK_STK_SIZE - 1], TASK_1_PRIO, TASK_1_ID, &Task 1 Stk[0], TASK_STK_SIZE, (void *)0, OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR); …………………… OSTask. Create. Ext(Task 5, ……. . ); }
时钟显示任务程序 void Task. Clk (void *data) { Struct time now; Struct date today; char s[40]; data = data; for (; ; ) { PC_Get. Date. Time(s); PC_Disp. Str(0, 24, s, DISP_FGND_BLUE + DISP_BGND_CYAN); OSTime. Dly(OS_TICKS_PER_SEC); } } n
任务 1程序 void Task 1 (void *pdata) { INT 8 U err; OS_STK_DATA data; /任务堆栈数据 INT 16 U time; /执行时间 INT 8 U i; char s[80]; pdata = pdata; n
任务 1程序 (续) for (; ; ) { for (i = 0; i < 7; i++) { PC_Elapsed. Start(); / 统计OSTask. Stk. Chk()函数运行时间开始 err = OSTask. Stk. Chk(TASK_START_PRIO+i, &data); time = PC_Elapsed. Stop(); /统计OSTask. Stk. Chk()函数运行时间 结束 if (err == OS_NO_ERR) { sprintf(s, "%3 ld %5 d", data. OSFree + data. OSUsed, data. OSFree, data. OSUsed, time); PC_Disp. Str(19, 12+i, s, DISP_FGND_YELLOW); } /显示统计结果 } OSTime. Dly. HMSM(0, 0, 0, 100); /延时 100 ms } }
任务 2程序 void Task 2 (void *data) { data = data; for (; ; ) { PC_Disp. Char(70, 15, '|', DISP_FGND_WHITE + DISP_BGND_RED); OSTime. Dly(10); PC_Disp. Char(70, 15, '/', DISP_FGND_WHITE + DISP_BGND_RED); n
任务 2程序 (续) OSTime. Dly(10); PC_Disp. Char(70, 15, '-', DISP_FGND_WHITE + DISP_BGND_RED); OSTime. Dly(10); PC_Disp. Char(70, 15, '\', DISP_FGND_WHITE + DISP_BGND_RED); OSTime. Dly(10); } }
任务 3程序 void Task 3 (void *data) { char dummy[500]; INT 16 U i; data = data; for (I = 0; i < 499; i++) { dummy[i] = '? '; } n
任务 3程序 (续) for (; ; ) { PC_Disp. Char(70, 16, '|', DISP_FGND_WHITE + DISP_BGND_BLUE); OSTime. Dly(20); PC_Disp. Char(70, 16, '\', DISP_FGND_WHITE + DISP_BGND_BLUE); OSTime. Dly(20); PC_Disp. Char(70, 16, '-', DISP_FGND_WHITE + DISP_BGND_BLUE); OSTime. Dly(20); PC_Disp. Char(70, 16, '/', DISP_FGND_WHITE + DISP_BGND_BLUE); OSTime. Dly(20); } }
任务 4程序 void Task 4 (void *data) { char txmsg; INT 8 U err; data = data; txmsg = 'A'; n
任务 5程序 void Task 5 (void *data) { char *rxmsg; INT 8 U err; data = data; n
任务 5程序 (续) for (; ; ) { rxmsg = (char *)OSMbox. Pend(Tx. Mbox, 0, &err); /Task 5无限期等待Tx. Mbox邮箱(任务 4发送)的消息 PC_Disp. Char(70, 18, *rxmsg, /显示邮箱的消息 DISP_FGND_YELLOW+DISP_BGND_RED) ; OSTime. Dly. HMSM(0, 0, 1, 0); (3) /延时等待1 s OSMbox. Post(Ack. Mbox, (void *)1); /当接收到消息后,给出应答 }
main()函数 void main (void) { PC_Disp. Clr. Scr(DISP_FGND_WHITE + DISP_BGND_BLACK); OSInit(); PC_DOSSave. Return(); PC_Vect. Set(u. COS, OSCtx. Sw); PC_Elapsed. Init(); Strcpy(Task. User. Data[TASK_START_ID]. Task. Name, "Start. Task"); OSTask. Create. Ext(Task. Start, (void *)0, /禁止堆栈检查 &Task. Start. Stk[TASK_STK_SIZE-1], TASK_START_PRIO, TASK_START_ID, &Task. Start. Stk[0], TASK_STK_SIZE, &Task. User. Data[TASK_START_ID], 0); (2) OSStart(); } n
TCB扩展数据结构 typedef struct { char Task. Name[30]; (1) INT 16 U Task. Ctr; INT 16 U Task. Exec. Time; INT 32 U Task. Tot. Exec. Time; } TASK_USER_DATA; n 定义了30个字节来存放任务名(包括空格)
Task. Start()的伪码 void Task. Start (void *data) { Prevent compiler warning by assigning ‘data’ to itself; Display a banner and non-changing text; Install u. C/OS-II’s tick handler; Change the tick rate to 200 Hz; Initialize the statistics task; n
Task. Start()的伪码 (续) Create a message queue; /为任务 1,2,3建立一个消息队列 /调用Task. Start. Create. Tasks()创建任务 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. ; /每个任务的名字都保存在任务的TCB扩展数据结构中 for (; ; ) { Display #tasks running; Display CPU usage in %; Display #context switches per seconds; Clear the context switch counter; Display u. C/OS-II’s version; If (Key was pressed) { if (Key pressed was the ESCAPE key) {Return to DOS; } } Delay for 1 second; } }
为任务 1,2,3建立一个消息队列 n Msg. Queue = OSQCreate(&Msg. Queue. Tbl[0], MSG_QUEUE_SIZE);
Task. Start. Create. Tasks() void Task. Start. Create. Tasks (void) { strcpy(Task. User. Data[TASK_CLK_ID]. Task. Name, "Clock Task"); OSTask. Create. Ext(Task. Clk, (void *)0, &Task. Clk. Stk[TASK_STK_SIZE - 1], TASK_CLK_PRIO, TASK_CLK_ID, &Task. Clk. Stk[0], TASK_STK_SIZE, &Task. User. Data[TASK_CLK_ID], 0); /创建显示日期与时间的任务 strcpy(Task. User. Data[TASK_1_ID]. Task. Name, "Msg. Q Rx Task"); OSTask. Create. Ext(Task 1, (void *)0, &Task 1 Stk[TASK_STK_SIZE 1], TASK_1_PRIO, TASK_1_ID, &Task 1 Stk[0], TASK_STK_SIZE, &Task. User. Data[TASK_1_ID], 0); /创建任务 1 -------------------strcpy(Task. User. Data[TASK_5_ID]. Task. Name, "Time. Dly. Task"); OSTask. Create. Ext(Task 5, (void *)0, &Task 5 Stk[TASK_STK_SIZE - 1], TASK_5_PRIO, TASK_5_ID, &Task 5 Stk[0], TASK_STK_SIZE, &Task. User. Data[TASK_5_ID], 0); /创建任务 5 n
任务 1程序 void Task 1 (void *data) { char one = '1'; char two = '2'; char three = '3'; data = data; for (; ; ) { /向消息队列发送一个消息 OSQPost(Msg. Queue, (void *)&one); (1) /延时等待消息发送完成 OSTime. Dly. HMSM(0, 0, 1, 0); (2) OSQPost(Msg. Queue, (void *)&two); OSTime. Dly. HMSM(0, 0, 0, 500); OSQPost(Msg. Queue, (void *)&three); OSTime. Dly. HMSM(0, 0, 1, 0); } } n
任务 2程序 void Task 2 (void *data) { INT 8 U *msg; INT 8 U err; data = data; for (; ; ) {/处于等待消息的挂起状态,且不设定最大等待时间 msg = (INT 8 U *)OSQPend(Msg. Queue, 0, &err); (1) /收到消息后显示消息 PC_Disp. Char(70, 14, *msg, DISP_FGND_YELLOW+DISP_BGND_BLUE); (2) /延时 500 m. S,同时使任务 3检查消息队列 OSTime. Dly. HMSM(0, 0, 0, 500); (3) } } n
任务 3程序 void Task 3 (void *data) { INT 8 U *msg; INT 8 U err; data = data; for (; ; ) { msg = (INT 8 U *)OSQPend(Msg. Queue, OS_TICKS_PER_SEC/4, &err); (1) /等待消息的挂起状态,设定等待结束时间 250 m. S If (err == OS_TIMEOUT) {PC_Disp. Char(70, 15, 'T', DISP_FGND_YELLOW+DISP_BGND_RED ); (2) /如果超过了等待时间,就显示“T” } else {PC_Disp. Char(70, 15, *msg, DISP_FGND_YELLOW+DISP_BGND_BLUE); (3) /有消息来到,任务 3将显示消息号 } } } n
任务 4程序 void Task 4 (void *data) { OS_EVENT *mbox; INT 8 U err; data = data; mbox = OSMbox. Create((void *)0); for (; ; ) { OSMbox. Post(mbox, (void *)1); (1) /发送 OSMbox. Pend(mbox, 0, &err); (2)/接收 OSTime. Dly. HMSM(0, 0, 0, 10); (3) /10 m. S执行 一次 } } n
任务 5程序 void Task 5 (void *data) { data = data; for (; ; ) { OSTime. Dly(1); (1) } } n
用户定义的OSTask. Stat. Hook() void OSTask. Stat. Hook (void) { char s[80]; INT 8 U i; INT 32 U total; INT 8 U pct; total = 0 L; for (I = 0; i < 7; i++) {/计算所有任务的运行时间 total += Task. User. Data[i]. Task. Tot. Exec. Time; (1) /将数字显示为ASCII字符 Disp. Task. Stat(i); (2)} n
用户定义的 OSTask. Stat. Hook()(续) if (total > 0) {for (i = 0; i < 7; i++) {pct = 100 * Task. User. Data[i]. Task. Tot. Exec. Time / total; / 计算每个任务运行时间的百分比 sprintf(s, "%3 d %%", pct); PC_Disp. Str(62, i + 11, s, DISP_FGND_YELLOW); /显示出来 } } if (total > 100000 L) {for (i = 0; i < 7; i++) {Task. User. Data[i]. Task. Tot. Exec. Time = 0 L; } } } n
main()函数 void main (void) { PC_Disp. Clr. Scr(DISP_FGND_WHITE + DISP_BGND_BLACK); OSInit(); PC_DOSSave. Return(); PC_Vect. Set(u. COS, OSCtx. Sw); OSTask. Create. Ext(Task. Start, (void *)0, Task. Start. Stk[TASK_STK_SIZE - 1], 0, /任务优先级为 0(最高) 0, &Task. Start. Stk[0], TASK_STK_SIZE, (void *)0, OS_TASK_OPT_SAVE_FP); /支持浮点运算 OSStart(); } n
Task. Start. Create. Tasks()函数 static void Task. Start. Create. Tasks (void) { INT 8 U i; INT 8 U prio; for (i = 0; i < N_TASKS; i++) { /创建N_TASKS =10个相同的任务 prio = i + 1; /每个任务的序号也是优先级的序号 Task. Data[i] = prio; OSTask. Create. Ext(Task, (void *)&Task. Data[i], &Task. Stk[i][TASK_STK_SIZE - 1], prio, 0, &Task. Stk[i][0], TASK_STK_SIZE, (void *)0, OS_TASK_OPT_SAVE_FP); /支持浮点运算 } } n
Task ()函数 void Task (void *pdata) { FP 32 x; FP 32 y; FP 32 angle; FP 32 radians; /设定浮点变量 char s[81]; INT 8 U ypos; ypos = *(INT 8 U *)pdata + 7; angle = (FP 32)(*(INT 8 U *)pdata) * (FP 32)36. 0; /计算角度 for (; ; ) { radians = (FP 32)2. 0 * (FP 32)3. 141592 * angle / (FP 32)360. 0; x = cos(radians); /计算角度的余弦 y = sin(radians); /计算角度的正弦 sprintf(s, " %2 d %8. 3 f", *(INT 8 U *)pdata, angle, x, y); PC_Disp. Str(0, ypos, s, DISP_FGND_BLACK + ISP_BGND_LIGHT_GRAY); if (angle >= (FP 32)360. 0) { angle = (FP 32)0. 0; } else { angle += (FP 32)0. 01; } OSTime. Dly(1); } } n
- Slides: 99