程序清单 L 1.8建立其它任务的任务。
|
void TaskStart (void *data)
|
{
|
Prevent compiler warning by assigning ‘data’ to itself;
|
Display banner identifying this as EXAMPLE #1; (1)
|
|
OS_ENTER_CRITICAL();
|
PC_VectSet(0x08, OSTickISR); (2)
|
PC_SetTickRate(200); (3)
|
OS_EXIT_CRITICAL();
|
|
Initialize the statistic task by calling ‘OSStatInit()’; (4)
|
|
Create 10 identical tasks; (5)
|
|
for (;;) {
|
Display the number of tasks created;
|
Display the % of CPU used;
|
Display the number of task switches in 1 second;
|
Display uC/OS-II’s version number
|
If (key was pressed) {
|
if (key pressed was the ESCAPE key) {
|
PC_DOSReturn();
|
}
|
}
|
Delay for 1 Second;
|
}
|
}
|
在建立其他任务之前,必须调用OSStatInit()[L1.8(4)]来确定用户的PC有多快,如程序清单L1.9所示。在一开始,OSStatInit()就将自身延时了两个时钟节拍,这样它就可以与时钟节拍中断同步[L1.9(1)]。因此,OSStatInit()必须在时钟节拍启动之后调用;否则,用户的应用程序就会崩溃。当uC/OS-II调用OSStatInit()时,一个32位的计数器OSIdleCtr被清为0 [L1.9(2)],并产生另一个延时,这个延时使OSStatInit()挂起。此时,uCOS-II没有别的任务可以执行,它只能执行空闲任务(uC/OS-II的内部任务)。空闲任务是一个无线的循环,它不断的递增OSIdleCtr[L1.9(3)]。1秒以后,uCOS-II重新开始OSStatInit(),并且将OSIdleCtr保存在OSIdleMax中[L1.9(4)。所以OSIdleMax是OSIdleCtr所能达到的最大值。而当用户再增加其他应用代码时,空闲任务就不会占用那样多的CPU时间。OSIdleCtr不可能达到那样多的记数,(如果拥护程序每秒复位一次OSIdleCtr)CPU利用率的计算由uC/OS-II 中的OSStatTask()函数来完成,这个任务每秒执行一次。而当OSStatRdy置为TRUE[L1.9(5)],表示uC/OS-II将统计CPU的利用率。程序清单 L 1.12TaskStart()的伪码。.
|
void TaskStart (void *data)
|
{
|
Prevent compiler warning by assigning ‘data’ to itself;
|
Display a banner and non-changing text;
|
Install uC/OS-II’s tick handler;
|
Change the tick rate to 200 Hz;
|
Initialize the statistics task;
|
Create 2 mailboxes which are used by Task #4 and #5; (1)
|
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 uC/OS-II’s version;
|
If (Key was pressed) {
|
if (Key pressed was the ESCAPE key) {
|
Return to DOS;
|
}
|
}
|
Delay for 1 second;
|
}
|
}
|
程序清单 L 1.13例2, 任务1
|
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(); (1)
|
err = OSTaskStkChk(TASK_START_PRIO+i, &data)
|
time = PC_ElapsedStop(); (2)
|
if (err == OS_NO_ERR) {
|
sprintf(s, "%3ld %3ld %3ld %5d",
|
data.OSFree + data.OSUsed,
|
data.OSFree,
|
data.OSUsed,
|
time);
|
PC_DispStr(19, 12+i, s, DISP_FGND_YELLOW);
|
}
|
}
|
OSTimeDlyHMSM(0, 0, 0, 100); (3)
|
}
|
}
|
程序清单L1.14所示的任务2在屏幕上显示一个顺时针旋转的指针(用横线,斜线等字符表示—译者注),每200ms旋转一格。程序清单 L 1.14任务2
|
void Task2 (void *data)
|
{
|
data = data;
|
for (;;) {
|
PC_DispChar(70, 15, '|', DISP_FGND_WHITE + DISP_BGND_RED);
|
OSTimeDly(10);
|
PC_DispChar(70, 15, '/', DISP_FGND_WHITE + DISP_BGND_RED);
|
OSTimeDly(10);
|
PC_DispChar(70, 15, '-', DISP_FGND_WHITE + DISP_BGND_RED);
|
OSTimeDly(10);
|
PC_DispChar(70, 15, '\\', DISP_FGND_WHITE + DISP_BGND_RED);
|
OSTimeDly(10);
|
}
|
}
|
任务3(程序清单 L1.15)也显示了与任务2相同的一个旋转指针,但是旋转的方向不同。任务3在堆栈中分配了一个很大的数组,将堆栈填充掉,使得OSTaskStkChk()只需花费很少的时间来确定堆栈的利用率,尤其是当堆栈已经快满的时候。程序清单 L 1.15任务3
|
void Task3 (void *data)
|
{
|
char dummy[500];
|
INT16U i;
|
data = data;
|
for (I = 0; i < 499; i++) {
|
dummy = '?';
|
}
|
for (;;) {
|
PC_DispChar(70, 16, '|', DISP_FGND_WHITE + DISP_BGND_BLUE);
|
OSTimeDly(20);
|
PC_DispChar(70, 16, '\\', DISP_FGND_WHITE + DISP_BGND_BLUE);
|
OSTimeDly(20);
|
PC_DispChar(70, 16, '-', DISP_FGND_WHITE + DISP_BGND_BLUE);
|
OSTimeDly(20);
|
PC_DispChar(70, 16, '/', DISP_FGND_WHITE + DISP_BGND_BLUE);
|
OSTimeDly(20);
|
}
|
}
|
任务4(程序清单L1.16)向任务5发送消息并等待确认[程序清单L1.16(1)]。发送的消息是一个指向字符的指针。每当任务4从任务5收到确认[程序清单L1.16(2)],就将传递的ASCII码加1再发送[程序清单L1.16(3)],结果是不断的传送“ABCDEFG....”。程序清单 L 1.28用户定义的OSTaskStatHook().
|
void OSTaskStatHook (void)
|
{
|
char s[80];
|
INT8U i;
|
INT32U total;
|
INT8U pct;
|
|
|
total = 0L;
|
for (I = 0; i < 7; i++) {
|
total += TaskUserData.TaskTotExecTime; (1)
|
DispTaskStat(i); (2)
|
}
|
if (total > 0) {
|
for (i = 0; i < 7; i++) {
|
pct = 100 * TaskUserData.TaskTotExecTime / total; (3)
|
sprintf(s, "%3d %%", pct);
|
PC_DispStr(62, i + 11, s, DISP_FGND_YELLOW); (4)
|
}
|
}
|
if (total > 1000000000L) {
|
for (i = 0; i < 7; i++) {
|
TaskUserData.TaskTotExecTime = 0L;
|
}
|
}
|
}
|