在真正开始分析源代码前,先来看使用
uC/OS-II
的
三个例子
1)使用信号量
#define
TASK_STK_SIZE 512 /* 每个任务堆栈的大小(以字计算)*/
#define
N_TASKS 10 /* 任务数*/
OS_STK TaskStk[N_TASKS][TASK_STK_SIZE];
/*
任务堆栈
*/
OS_STK TaskStartStk[TASK_STK_SIZE];
//
开始任务的堆栈
char
TaskData[N_TASKS];
/*
传给每个任务的数据
*/
OS_EVENT
*
RandomSem;
//
互斥型信号量
void
main (
void
)
{
PC_DispClrScr(DISP_FGND_WHITE
+
DISP_BGND_BLACK);
/*
清空屏幕
*/
OSInit();
/*
初始化uC/OS-II
*/
PC_DOSSaveReturn();
/*
保存环境以便稍后可以返回DOS环境
*/
PC_VectSet(uCOS, OSCtxSw);
/*
设置uC/OS-II的切换处理函数
*/
RandomSem
=
OSSemCreate(
1
);
/*
建立一个信号量
*/
OSTaskCreate(TaskStart, (
void
*
)
0
,
&
TaskStartStk[TASK_STK_SIZE
-
1
],
0
);
//
创建第一个任务,优先级设置为最大值
OSStart();
/*
开始多任务
*/
}
void
TaskStart (
void
*
pdata)
{
#if
OS_CRITICAL_METHOD == 3 /* 为CPU的状态寄存器分配内存*/
OS_CPU_SR cpu_sr;
#endif
char
s[
100
];
INT16S key;
pdata
=
pdata;
/*
这步是为了防止编译错误
*/
TaskStartDispInit();
/*
初始化显示屏
*/
OS_ENTER_CRITICAL();
PC_VectSet(
0x08
, OSTickISR);
/*
替换机器的时钟中断函数为uC/OS-II所需要的中断函数
*/
PC_SetTickRate(OS_TICKS_PER_SEC);
/*
调整时钟频率
*/
OS_EXIT_CRITICAL();
OSStatInit();
/*
初始化统计任务
*/
TaskStartCreateTasks();
/*
创建其他任务
*/
for
(;;) {
TaskStartDisp();
if
(PC_GetKey(
&
key)
==
TRUE) {
/*
是否按键
*/
if
(key
==
0x1B
) {
/*
ESCAPE按下了
*/
PC_DOSReturn();
/*
返回DOS
*/
}
}
OSCtxSwCtr
=
0
;
/*
切换次数计数器清零
*/
OSTimeDlyHMSM(
0
,
0
,
1
,
0
);
/*
挂起秒,让给其他任务运行
*/
}
}
static
void
TaskStartCreateTasks (
void
)
{
INT8U i;
for
(i
=
0
; i
<
N_TASKS; i
++
) {
/*
创建N_TASKS个任务
*/
TaskData[i]
=
'
0
'
+
i;
/*
每个任务显示其数据
*/
OSTaskCreate(Task, (
void
*
)
&
TaskData[i],
&
TaskStk[i][TASK_STK_SIZE
-
1
], i
+
1
);
}
}
void
Task (
void
*
pdata)
{
INT8U x;
INT8U y;
INT8U err;
for
(;;) {
OSSemPend(RandomSem,
0
,
&
err);
/*
获取信号量
*/
x
=
random(
80
);
/*
计算X坐标
*/
y
=
random(
16
);
/*
计算Y坐标
*/
OSSemPost(RandomSem);
/*
释放信号量
*/
/*
Display the task number on the screen
*/
PC_DispChar(x, y
+
5
,
*
(
char
*
)pdata, DISP_FGND_BLACK
+
DISP_BGND_LIGHT_GRAY);
OSTimeDly(
1
);
/*
挂起秒,让给其他任务运行
*/
}
}
2)使用消息邮箱
#define
TASK_STK_SIZE 512
#define
TASK_START_ID 0 /* 任务ID*/
#define
TASK_CLK_ID 1
#define
TASK_1_ID 2
#define
TASK_2_ID 3
#define
TASK_3_ID 4
#define
TASK_4_ID 5
#define
TASK_5_ID 6
#define
TASK_START_PRIO 10 /* 任务优先级*/
#define
TASK_CLK_PRIO 11
#define
TASK_1_PRIO 12
#define
TASK_2_PRIO 13
#define
TASK_3_PRIO 14
#define
TASK_4_PRIO 15
#define
TASK_5_PRIO 16
OS_STK TaskStartStk[TASK_STK_SIZE];
OS_STK TaskClkStk[TASK_STK_SIZE];
OS_STK Task1Stk[TASK_STK_SIZE];
OS_STK Task2Stk[TASK_STK_SIZE];
OS_STK Task3Stk[TASK_STK_SIZE];
OS_STK Task4Stk[TASK_STK_SIZE];
OS_STK Task5Stk[TASK_STK_SIZE];
OS_EVENT
*
AckMbox;
/*
任务和使用的消息邮箱
*/
OS_EVENT
*
TxMbox;
void
main (
void
)
{
OS_STK
*
ptos;
OS_STK
*
pbos;
INT32U size;
PC_DispClrScr(DISP_FGND_WHITE);
OSInit();
PC_DOSSaveReturn();
PC_VectSet(uCOS, OSCtxSw);
PC_ElapsedInit();
ptos
=
&
TaskStartStk[TASK_STK_SIZE
-
1
];
pbos
=
&
TaskStartStk[
0
];
size
=
TASK_STK_SIZE;
OSTaskStkInit_FPE_x86(
&
ptos,
&
pbos,
&
size);
OSTaskCreateExt(TaskStart,
(
void
*
)
0
,
ptos,
TASK_START_PRIO,
TASK_START_ID,
pbos,
size,
(
void
*
)
0
,
OS_TASK_OPT_STK_CHK
|
OS_TASK_OPT_STK_CLR);
OSStart();
}
void
TaskStart (
void
*
pdata)
{
#if
OS_CRITICAL_METHOD == 3
OS_CPU_SR cpu_sr;
#endif
INT16S key;
pdata
=
pdata;
TaskStartDispInit();
OS_ENTER_CRITICAL();
PC_VectSet(
0x08
, OSTickISR);
PC_SetTickRate(OS_TICKS_PER_SEC);
OS_EXIT_CRITICAL();
OSStatInit();
AckMbox
=
OSMboxCreate((
void
*
)
0
);
/*
创建两个消息邮箱
*/
TxMbox
=
OSMboxCreate((
void
*
)
0
);
TaskStartCreateTasks();
for
(;;) {
TaskStartDisp();
if
(PC_GetKey(
&
key)) {
if
(key
==
0x1B
) {
PC_DOSReturn();
}
}
OSCtxSwCtr
=
0
;
OSTimeDly(OS_TICKS_PER_SEC);
}
}
void
Task1 (
void
*
pdata)
{
INT8U err;
OS_STK_DATA data;
/*
任务堆栈数据
*/
INT16U time;
INT8U i;
char
s[
80
];
pdata
=
pdata;
for
(;;) {
for
(i
=
0
; i
<
7
; i
++
) {
PC_ElapsedStart();
err
=
OSTaskStkChk(TASK_START_PRIO
+
i,
&
data);
//
执行堆栈检查
time
=
PC_ElapsedStop();
if
(err
==
OS_NO_ERR) {
sprintf(s,
"
%4ld %4ld %4ld %6d
"
,
data.OSFree
+
data.OSUsed,
data.OSFree,
data.OSUsed,
time);
PC_DispStr(
19
,
12
+
i, s, DISP_FGND_BLACK
+
DISP_BGND_LIGHT_GRAY);
}
}
OSTimeDlyHMSM(
0
,
0
,
0
,
100
);
/*
挂起mS
*/
}
}
void
Task4 (
void
*
data)
{
char
txmsg;
INT8U err;
data
=
data;
txmsg
=
'
A
'
;
for
(;;) {
OSMboxPost(TxMbox, (
void
*
)
&
txmsg);
/*
发消息给Task #5
*/
OSMboxPend(AckMbox,
0
,
&
err);
/*
等待Task #5的应答消息
*/
txmsg
++
;
/*
下一个要发的消息数据
*/
if
(txmsg
==
'
Z
'
) {
txmsg
=
'
A
'
;
/*
循环发送A-Z
*/
}
}
}
void
Task5 (
void
*
data)
{
char
*
rxmsg;
INT8U err;
data
=
data;
for
(;;) {
rxmsg
=
(
char
*
)OSMboxPend(TxMbox,
0
,
&
err);
/*
等待来自Task #4的数据
*/
PC_DispChar(
70
,
18
,
*
rxmsg, DISP_FGND_YELLOW
+
DISP_BGND_BLUE);
OSTimeDlyHMSM(
0
,
0
,
1
,
0
);
/*
挂起秒,让给其他任务运行
*/
OSMboxPost(AckMbox, (
void
*
)
1
);
/*
发送接收到数据的应答消息
*/
}
}
运行结果:
3)使用消息队列
#define
TASK_STK_SIZE 512
#define
TASK_START_ID 0
#define
TASK_CLK_ID 1
#define
TASK_1_ID 2
#define
TASK_2_ID 3
#define
TASK_3_ID 4
#define
TASK_4_ID 5
#define
TASK_5_ID 6
#define
TASK_START_PRIO 10
#define
TASK_CLK_PRIO 11
#define
TASK_1_PRIO 12
#define
TASK_2_PRIO 13
#define
TASK_3_PRIO 14
#define
TASK_4_PRIO 15
#define
TASK_5_PRIO 16
#define
MSG_QUEUE_SIZE 20 /* 消息队列大小*/
typedef
struct
{
char
TaskName[
30
];
INT16U TaskCtr;
INT16U TaskExecTime;
INT32U TaskTotExecTime;
} TASK_USER_DATA;
OS_STK TaskStartStk[TASK_STK_SIZE];
OS_STK TaskClkStk[TASK_STK_SIZE];
OS_STK Task1Stk[TASK_STK_SIZE];
OS_STK Task2Stk[TASK_STK_SIZE];
OS_STK Task3Stk[TASK_STK_SIZE];
OS_STK Task4Stk[TASK_STK_SIZE];
OS_STK Task5Stk[TASK_STK_SIZE];
TASK_USER_DATA TaskUserData[
7
];
OS_EVENT
*
MsgQueue;
/*
消息队列指针
*/
void
*
MsgQueueTbl[
20
];
/*
消息存储
*/
void
main (
void
)
{
PC_DispClrScr(DISP_BGND_BLACK);
OSInit();
PC_DOSSaveReturn();
PC_VectSet(uCOS, OSCtxSw);
PC_ElapsedInit();
strcpy(TaskUserData[TASK_START_ID].TaskName,
"
StartTask
"
);
OSTaskCreateExt(TaskStart,
(
void
*
)
0
,
&
TaskStartStk[TASK_STK_SIZE
-
1
],
TASK_START_PRIO,
TASK_START_ID,
&
TaskStartStk[
0
],
TASK_STK_SIZE,
&
TaskUserData[TASK_START_ID],
0
);
OSStart();
}
void
TaskStart (
void
*
pdata)
{
#if
OS_CRITICAL_METHOD == 3
OS_CPU_SR cpu_sr;
#endif
INT16S key;
pdata
=
pdata;
TaskStartDispInit();
OS_ENTER_CRITICAL();
PC_VectSet(
0x08
, OSTickISR);
PC_SetTickRate(OS_TICKS_PER_SEC);
OS_EXIT_CRITICAL();
OSStatInit();
MsgQueue
=
OSQCreate(
&
MsgQueueTbl[
0
], MSG_QUEUE_SIZE);
/*
创建消息队列,大小为
*/
TaskStartCreateTasks();
for
(;;) {
TaskStartDisp();
if
(PC_GetKey(
&
key)) {
if
(key
==
0x1B
) {
PC_DOSReturn();
}
}
OSCtxSwCtr
=
0
;
OSTimeDly(OS_TICKS_PER_SEC);
}
}
void
Task1 (
void
*
pdata)
{
char
*
msg;
INT8U err;
pdata
=
pdata;
for
(;;) {
msg
=
(
char
*
)OSQPend(MsgQueue,
0
,
&
err);
//
从消息队列中取消息
PC_DispStr(
70
,
13
, msg, DISP_FGND_YELLOW
+
DISP_BGND_BLUE);
OSTimeDlyHMSM(
0
,
0
,
0
,
100
);
}
}
void
Task2 (
void
*
pdata)
{
char
msg[
20
];
pdata
=
pdata;
strcpy(
&
msg[
0
],
"
Task 2
"
);
for
(;;) {
OSQPost(MsgQueue, (
void
*
)
&
msg[
0
]);
//
发送消息到队列中
OSTimeDlyHMSM(
0
,
0
,
0
,
500
);
}
}
void
Task3 (
void
*
pdata)
{
char
msg[
20
];
pdata
=
pdata;
strcpy(
&
msg[
0
],
"
Task 3
"
);
for
(;;) {
OSQPost(MsgQueue, (
void
*
)
&
msg[
0
]);
//
发送消息到队列中
OSTimeDlyHMSM(
0
,
0
,
0
,
500
);
}
}
void
Task4 (
void
*
pdata)
{
char
msg[
20
];
pdata
=
pdata;
strcpy(
&
msg[
0
],
"
Task 4
"
);
for
(;;) {
OSQPost(MsgQueue, (
void
*
)
&
msg[
0
]);
//
发送消息到队列中
OSTimeDlyHMSM(
0
,
0
,
0
,
500
);
}
}
void
OSTaskStatHook (
void
)
{
char
s[
80
];
INT8U i;
INT32U total;
INT8U pct;
total
=
0L
;
/*
Totalize TOT. EXEC. TIME for each task
for (i = 0; i < 7; i++) {
total += TaskUserData[i].TaskTotExecTime;
DispTaskStat(i); /* Display task data
}
if (total > 0) {
for (i = 0; i < 7; i++) { /* Derive percentage of each task
*/
pct
=
100
*
TaskUserData[i].TaskTotExecTime
/
total;
sprintf(s,
"
%3d %%
"
, pct);
PC_DispStr(
62
, i
+
11
, s, DISP_FGND_BLACK
+
DISP_BGND_LIGHT_GRAY);
}
}
if
(total
>
1000000000L
) {
/*
Reset total time counters at 1 billion
for (i = 0; i < 7; i++) {
TaskUserData[i].TaskTotExecTime = 0L;
}
}
}
void OSTaskSwHook (void)
{
INT16U time;
TASK_USER_DATA *puser;
time = PC_ElapsedStop(); /* This task is done
PC_ElapsedStart(); /* Start for next task
puser = OSTCBCur->OSTCBExtPtr; /* Point to used data
if (puser != (TASK_USER_DATA *)0) {
puser->TaskCtr++; /* Increment task counter
puser->TaskExecTime = time; /* Update the task's execution time
puser->TaskTotExecTime += time; /* Update the task's total execution time
}
}
运行结果: