分析µC/OS-II操作系统信号量机制

任务说明

了解µC/OS-II的信号量的定义及作用,并能够使用信号量保证进程间的同步。

要求

应用程序中有一个函数Fun(),试编写程序使得任务MyTask需在6秒后经过任务YouTask同意才能调用这个函数一次。

示例结果如下图所示。

操作系统2

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
/************************Test*************************************/
#include "includes.h"
#define TASK_STK_SIZE 512 //任务堆栈长度
char *s1="你的学号";
char *s2="你的姓名";

OS_STK StartTaskStk[TASK_STK_SIZE]; //定义任务堆栈区
OS_STK MyTaskStk[TASK_STK_SIZE]; //定义任务堆栈区
OS_STK YouTaskStk[TASK_STK_SIZE]; //定义任务堆栈区
INT16S key; //用于退出的键

INT8U err;
INT8U y=0; //字符显示位置

OS_EVENT *a;
INT8U count = 0;

void Fun(INT8U x,INT8U y);
void StartTask(void *data); //声明起始任务
void MyTask(void *data); //声明任务
void YouTask(void *data); //声明任务

// OS_EVENT *OSSemCreate(
// INT16U cnt //信号量计数器初始值
// );

// void OSSemPend(
// OS_EVENT *pevent,//信号量的指针
// INT16U timeout, //等待时限
// INT8U *err //错误信息
// );

// INT16U OSSemAccept(
// OS_EVENT *pevent,//信号量的指针
// );

// INT8U OSSemPost(
// OS_EVENT *pevent,//信号量的指针
// );

// OS_EVENT *OSSemDel(
// OS_EVENT *pevent,//信号量的指针
// INT8U opt , //删除条件选项
// INT8U *err //错误信息
// );

// INT8U OSSemQuery(
// OS_EVENT *pevent,//信号量的指针
// OS_SEM_DATA *pdata //存储信号量状态的结构
// );

/************************主函数*********************************/
void main (void)
{
OSInit( ); //初始化µC/OS-II_II
PC_DOSSaveReturn( ); //保存Dos环境
PC_VectSet(uCOS, OSCtxSw); //安装µC/OS-II_II中断
a = OSSemCreate(0);
OSTaskCreate(StartTask, //创建任务StartTask
(void*)0, //给任务传递参数
&StartTaskStk[TASK_STK_SIZE - 1], //设置任务堆栈栈顶
0); //使任务的优先级别为0
OSStart( ); //启动多任务管理

}
/***********************任务StartTask*******************************/
void StartTask (void *pdata)
{
#if OS_CRITICAL_METHOD == 3
OS_CPU_SR cpu_sr;
#endif
pdata = pdata;
OS_ENTER_CRITICAL( );
PC_VectSet(0x08, OSTickISR); //安装时钟中断向量
PC_SetTickRate(OS_TICKS_PER_SEC); //设置µC/OS-II_II时钟频率
OS_EXIT_CRITICAL( );

OSStatInit( ); //初始化统计任务
OSTaskCreate(MyTask, //创建任务MyTask
(void*)0, //给任务传递参数
&MyTaskStk[TASK_STK_SIZE - 1], //设置任务堆栈栈顶
1); //使任务的优先级别为1
OSTaskCreate(YouTask, //创建任务YouTask
(void*)0, //给任务传递参数
&YouTaskStk[TASK_STK_SIZE - 1], //设置任务堆栈栈顶
2); //使任务的优先级别为2

for (;;)
{
//如果按下Esc键则退出µC/OS-II_II
if (PC_GetKey(&key) == TRUE)
{
if (key == 0x1B)
{
PC_DOSReturn();
}
}
OSTimeDlyHMSM(0, 0, 3, 0); //等待3秒
}
}
/************************任务MyTask*******************************/
void MyTask (void *pdata)
{
#if OS_CRITICAL_METHOD == 3
OS_CPU_SR cpu_sr;
#endif
pdata = pdata;
for (;;)
{
OSSemPend(a,0,&err);
PC_DispStr(0,++y,
s1,
DISP_BGND_BLACK+DISP_FGND_WHITE );
Fun(12,y); //调用函数fun
OSTimeDlyHMSM(0, 0, 1, 0); //等待1秒

}
}
/************************任务YouTask******************************/
void YouTask (void *pdata)
{
#if OS_CRITICAL_METHOD == 3
OS_CPU_SR cpu_sr;
#endif
pdata = pdata;

for (;;)
{
PC_DispStr(0,++y,
s2,
DISP_BGND_BLACK+DISP_FGND_YELLOW );
OSTimeDlyHMSM(0, 0, 1, 0); //等待1秒
++count;
if(count == 6)
{
OSSemPost(a);
count = 0;
}
}
}
void Fun(INT8U x,INT8U y)
{
PC_DispStr(x,y,"invoked Fun()!",
DISP_BGND_BLACK+DISP_FGND_BLUE );
}
/************************End**************************************/