uCOS-II 学习笔记之事件管理--------信号量管理的学习

  今天将卢有亮老师基于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机运行那样,细看打印结果,基本上都是根据设计来的。

原文地址:https://www.cnblogs.com/xiaofeng6636/p/3511371.html