今天将卢有亮老师基于VC的信号量管理的代码移植到STM32中,并通过串口打印在串口终端。
假设有共享资源R,允许2个任务分时访问R,那么信号量应该设置为2,系统中有三个任务(A、B、C)分别访问资源R,任务的优先级分别为7、6、5. 3个任务在操作系统的初始化和启动多任务之前被创建。任务A运行后创建信号量,并访问R,访问完成后任务将自己阻塞1000个时钟周期。任务B先阻塞自己300个时钟周期,任何操作步骤同任务A。任务C先阻塞400个时钟周期,然后操作步骤同任务A。
1 //========================================================================================= 2 //uCOS-II 学习例子 3 //========================================================================================= 4 //信号量管理的例子 5 void UserTaskSemA(void *pParam) 6 { 7 /*任务SemA创建信号量,然后周期性访问资源R*/ 8 /*创建信号量*/ 9 INT8U *perr; 10 INT8U err; 11 //INT8U i; 12 OS_SEM_DATA mySemData; 13 err=0; 14 perr=&err; 15 MyEventSem=OSSemCreate(2); 16 if (MyEventSem==(OS_EVENT *)0) 17 { 18 printf("任务A创建信号量失败! "); 19 OSTaskDel(OS_PRIO_SELF); 20 return; 21 } 22 OSSemQuery(MyEventSem,&mySemData); 23 printf("时间:%d, 任务A创建信号量。当前信号量值=%d ",OSTimeGet(),mySemData.OSCnt); 24 while(1) 25 { 26 OSSemQuery(MyEventSem,&mySemData); 27 printf("时间:%d,任务A开始请求信号量!当前信号量值=%d ",OSTimeGet(),mySemData.OSCnt); 28 OSSemPend(MyEventSem,0,perr); 29 if (err!=OS_ERR_NONE) 30 { 31 printf("任务A请求信号量失败 "); 32 printf("错误号%d ",err); 33 continue; 34 } 35 OSSemQuery(MyEventSem,&mySemData); 36 printf("时间:%d,任务A获得信号量。当前信号量值=%d,任务A开始对R操作 ",OSTimeGet(),mySemData.OSCnt); 37 OSTimeDly(1000); /*模拟操作资源,需要10秒,1000个时钟嘀嗒*/ 38 printf("时间:%d,任务A结束资源操作,提交信号量! ",OSTimeGet()); 39 OSSemPost(MyEventSem); 40 OSSemQuery(MyEventSem,&mySemData); 41 printf("时间:%d,任务A提交信号量完成,当前信号量值=%d,任务A将延时阻塞1000嘀嗒 ",OSTimeGet(),mySemData.OSCnt); 42 OSTimeDly(1000); 43 } 44 } 45 void UserTaskSemB(void *pParam) 46 { 47 /*任务SemA创建信号量,然后周期性访问资源R*/ 48 INT8U *perr; 49 INT8U err; 50 OS_SEM_DATA mySemData; 51 err=0; 52 perr=&err; 53 printf("时间:%d,任务B开始延时300个时钟嘀嗒",OSTimeGet()); 54 OSTimeDly(300);/*任务B先延时3秒*/ 55 if (MyEventSem==(OS_EVENT *)0) 56 { 57 printf("任务A创建信号量失败! "); 58 OSTaskDel(OS_PRIO_SELF); 59 return; 60 } 61 while(1) 62 { 63 OSSemQuery(MyEventSem,&mySemData); 64 printf("时间:%d,任务B开始请求信号量!当前信号量值=%d ",OSTimeGet(),mySemData.OSCnt); 65 OSSemPend(MyEventSem,0,perr); 66 if (err!=OS_ERR_NONE) 67 { 68 printf("任务B请求信号量失败 "); 69 printf("错误号%d ",err); 70 continue; 71 } 72 OSSemQuery(MyEventSem,&mySemData); 73 printf("时间:%d,任务B获得信号量。当前信号量值=%d,任务B开始对R操作,需1000个时钟嘀嗒 ",OSTimeGet(),mySemData.OSCnt); 74 OSTimeDly(1000); /*模拟操作资源,需要10秒,1000个时钟嘀嗒*/ 75 printf("时间:%d,任务B结束资源操作,提交信号量! ",OSTimeGet()); 76 OSSemPost(MyEventSem); 77 OSSemQuery(MyEventSem,&mySemData); 78 printf("时间:%d,任务B提交信号量完成,当前信号量值=%d,任务B将延时阻塞1000嘀嗒 ",OSTimeGet(),mySemData.OSCnt); 79 OSTimeDly(1000); 80 } 81 } 82 83 84 void UserTaskSemC(void *pParam) 85 { 86 /*任务SemA创建信号量,然后周期性访问资源R*/ 87 INT8U *perr; 88 INT8U err; 89 //INT8U i; 90 OS_SEM_DATA mySemData; 91 err=0; 92 perr=&err; 93 printf("时间:%d,任务C开始延时400个时钟嘀嗒",OSTimeGet()); 94 OSTimeDly(400);/*任务C先延时4秒*/ 95 if (MyEventSem==(OS_EVENT *)0) 96 { 97 printf("任务A创建信号量失败! "); 98 OSTaskDel(OS_PRIO_SELF); 99 return; 100 } 101 while(1) 102 { 103 OSSemQuery(MyEventSem,&mySemData); 104 printf("时间:%d,任务C开始请求信号量!当前信号量值=%d ",OSTimeGet(),mySemData.OSCnt); 105 OSSemPend(MyEventSem,0,perr); 106 if (err!=OS_ERR_NONE) 107 { 108 printf("任务C请求信号量失败 "); 109 printf("错误号%d ",err); 110 continue; 111 } 112 OSSemQuery(MyEventSem,&mySemData); 113 printf("时间:%d,任务C获得信号量。当前信号量值=%d,任务C开始对R操作,需1000个时钟嘀嗒 ",OSTimeGet(),mySemData.OSCnt); 114 OSTimeDly(1000); /*模拟操作资源,需要10秒,1000个时钟嘀嗒*/ 115 printf("时间:%d,任务C结束资源操作,提交信号量! ",OSTimeGet()); 116 OSSemPost(MyEventSem); 117 OSSemQuery(MyEventSem,&mySemData); 118 printf("时间:%d,任务C提交信号量完成,当前信号量值=%d,任务C将延时阻塞1000嘀嗒 ",OSTimeGet(),mySemData.OSCnt); 119 OSTimeDly(1000); 120 } 121 }
运行结果如下所示:
1 时间:0,任务C开始延时400个时钟嘀嗒时间:0,任务B开始延时300个时钟嘀嗒时间:0, 任务A创建信号量。当前信号量值=2 2 时间:1,任务A开始请求信号量!当前信号量值=2 3 时间:1,任务A获得信号量。当前信号量值=1,任务A开始对R操作 4 时间:300,任务B开始请求信号量!当前信号量值=1 5 时间:300,任务B获得信号量。当前信号量值=0,任务B开始对R操作,需1000个时钟嘀嗒 6 时间:400,任务C开始请求信号量!当前信号量值=0 7 时间:1002,任务A结束资源操作,提交信号量! 8 时间:1002,任务C获得信号量。当前信号量值=0,任务C开始对R操作,需1000个时钟嘀嗒 9 时间:1003,任务A提交信号量完成,当前信号量值=0,任务A将延时阻塞1000嘀嗒 10 时间:1301,任务B结束资源操作,提交信号量! 11 时间:1301,任务B提交信号量完成,当前信号量值=1,任务B将延时阻塞1000嘀嗒 12 时间:2003,任务C结束资源操作,提交信号量! 13 时间:2003,任务C提交信号量完成,当前信号量值=2,任务C将延时阻塞1000嘀嗒 14 时间:2004,任务A开始请求信号量!当前信号量值=2 15 时间:2004,任务A获得信号量。当前信号量值=1,任务A开始对R操作 16 时间:2302,任务B开始请求信号量!当前信号量值=1 17 时间:2302,任务B获得信号量。当前信号量值=0,任务B开始对R操作,需1000个时钟嘀嗒 18 时间:3004,任务C开始请求信号量!当前信号量值=0 19 时间:3005,任务A结束资源操作,提交信号量! 20 时间:3005,任务C获得信号量。当前信号量值=0,任务C开始对R操作,需1000个时钟嘀嗒 21 时间:3006,任务A提交信号量完成,当前信号量值=0,任务A将延时阻塞1000嘀嗒 22 时间:3303,任务B结束资源操作,提交信号量! 23 时间:3303,任务B提交信号量完成,当前信号量值=1,任务B将延时阻塞1000嘀嗒 24 时间:4006,任务C结束资源操作,提交信号量! 25 时间:4006,任务C提交信号量完成,当前信号量值=2,任务C将延时阻塞1000嘀嗒 26 时间:4007,任务A开始请求信号量!当前信号量值=2 27 时间:4007,任务A获得信号量。当前信号量值=1,任务A开始对R操作 28 时间:4304,任务B开始请求信号量!当前信号量值=1 29 时间:4304,任务B获得信号量。当前信号量值=0,任务B开始对R操作,需1000个时钟嘀嗒 30 时间:5007,任务C开始请求信号量!当前信号量值=0 31 时间:5008,任务A结束资源操作,提交信号量! 32 时间:5008,任务C获得信号量。当前信号量值=0,任务C开始对R操作,需1000个时钟嘀嗒 33 时间:5009,任务A提交信号量完成,当前信号量值=0,任务A将延时阻塞1000嘀嗒 34 时间:5305,任务B结束资源操作,提交信号量! 35 时间:5305,任务B提交信号量完成,当前信号量值=1,任务B将延时阻塞1000嘀嗒 36 时间:6009,任务C结束资源操作,提交信号量! 37 时间:6009,任务C提交信号量完成,当前信号量值=2,任务C将延时阻塞1000嘀嗒 38 时间:6010,任务A开始请求信号量!当前信号量值=2 39 时间:6010,任务A获得信号量。当前信号量值=1,任务A开始对R操作 40 时间:6306,任务B开始请求信号量!当前信号量值=1 41 时间:6306,任务B获得信号量。当前信号量值=0,任务B开始对R操作,需1000个时钟嘀嗒 42 时间:7010,任务C开始请求信号量!当前信号量值=0 43 时间:7011,任务A结束资源操作,提交信号量! 44 时间:7011,任务C获得信号量。当前信号量值=0,任务C开始对R操作,需1000个时钟嘀嗒 45 时间:7012,任务A提交信号量完成,当前信号量值=0,任务A将延时阻塞1000嘀嗒 46 时间:7307,任务B结束资源操作,提交信号量! 47 时间:7307,任务B提交信号量完成,当前信号量值=1,任务B将延时阻塞1000嘀嗒 48 时间:8012,任务C结束资源操作,提交信号量! 49 时间:8012,任务C提交信号量完成,当前信号量值=2,任务C将延时阻塞1000嘀嗒 50 时间:8013,任务A开始请求信号量!当前信号量值=2 51 时间:8013,任务A获得信号量。当前信号量值=1,任务A开始对R操作 52 时间:8308,任务B开始请求信号量!当前信号量值=1 53 时间:8308,任务B获得信号量。当前信号量值=0,任务B开始对R操作,需1000个时钟嘀嗒 54 时间:9013,任务C开始请求信号量!当前信号量值=0 55 时间:9014,任务A结束资源操作,提交信号量! 56 时间:9014,任务C获得信号量。当前信号量值=0,任务C开始对R操作,需1000个时钟嘀嗒 57 时间:9015,任务A提交信号量完成,当前信号量值=0,任务A将延时阻塞1000嘀嗒 58 时间:9309,任务B结束资源操作,提交信号量! 59 时间:9309,任务B提交信号量完成,当前信号量值=1,任务B将延时阻塞1000嘀嗒
由于串口打印函数需要一定的时间,显示结果未能像PC机运行那样,细看打印结果,基本上都是根据设计来的。