范例三:
在该范例中首先定义了一个用户任务数据结构,在这个结构中有该范例所需要的数据参数,和每个任务相关的,因此定了一个该数据结构类型的变量数组,分配给7个自建的任务
另外使用了消息队列的通讯方式,可以容纳多则消息。建立消息队列需要两个元素即OS_EVENT的数据结构和一串指针。
void main (void)
{
PC_DispClrScr(DISP_BGND_BLACK); /* Clear the screen */
OSInit(); /* Initialize uC/OS-II */
PC_DOSSaveReturn(); /* Save environment to return to DOS */
PC_VectSet(uCOS, OSCtxSw); /* Install uC/OS-II's context switch vector */
PC_ElapsedInit(); /* Initialized elapsed time measurement */
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],/*在UCOS中,每个任务的TCB控制块都可以保存一个用户定义的数据结构的指针*/
0);
OSStart(); /* Start multitasking */
}
void TaskStart (void *pdata)
{
#if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr;
#endif
INT16S key;
pdata = pdata; /* Prevent compiler warning */
TaskStartDispInit(); /* Setup the display */
OS_ENTER_CRITICAL(); /* Install uC/OS-II's clock tick ISR */
PC_VectSet(0x08, OSTickISR);
PC_SetTickRate(OS_TICKS_PER_SEC); /* Reprogram tick rate */
OS_EXIT_CRITICAL();
OSStatInit(); /* Initialize uC/OS-II's statistics */
MsgQueue = OSQCreate(&MsgQueueTbl[0], MSG_QUEUE_SIZE); /* Create a message queue 建立了一个消息队列*/
TaskStartCreateTasks();
for (;;) {
TaskStartDisp(); /* Update the display */
if (PC_GetKey(&key)) { /* See if key has been pressed */
if (key == 0x1B) { /* Yes, see if it's the ESCAPE key */
PC_DOSReturn(); /* Yes, return to DOS */
}
}
OSCtxSwCtr = 0; /* Clear the context switch counter */
OSTimeDly(OS_TICKS_PER_SEC); /* Wait one second */
}
}
void TaskStartCreateTasks (void)
{
strcpy(TaskUserData[TASK_CLK_ID].TaskName, "Clock Task");
OSTaskCreateExt(TaskClk,
(void *)0,
&TaskClkStk[TASK_STK_SIZE - 1],
TASK_CLK_PRIO,
TASK_CLK_ID,
&TaskClkStk[0],
TASK_STK_SIZE,
&TaskUserData[TASK_CLK_ID],
0);
strcpy(TaskUserData[TASK_1_ID].TaskName, "MsgQ Rx Task");
OSTaskCreateExt(Task1,
(void *)0,
&Task1Stk[TASK_STK_SIZE - 1],
TASK_1_PRIO,
TASK_1_ID,
&Task1Stk[0],
TASK_STK_SIZE,
&TaskUserData[TASK_1_ID],
0);
strcpy(TaskUserData[TASK_2_ID].TaskName, "MsgQ Tx Task #2");
OSTaskCreateExt(Task2,
(void *)0,
&Task2Stk[TASK_STK_SIZE - 1],
TASK_2_PRIO,
TASK_2_ID,
&Task2Stk[0],
TASK_STK_SIZE,
&TaskUserData[TASK_2_ID],
0);
strcpy(TaskUserData[TASK_3_ID].TaskName, "MsgQ Tx Task #3");
OSTaskCreateExt(Task3,
(void *)0,
&Task3Stk[TASK_STK_SIZE - 1],
TASK_3_PRIO,
TASK_3_ID,
&Task3Stk[0],
TASK_STK_SIZE,
&TaskUserData[TASK_3_ID],
0);
strcpy(TaskUserData[TASK_4_ID].TaskName, "MsgQ Tx Task #4");
OSTaskCreateExt(Task4,
(void *)0,
&Task4Stk[TASK_STK_SIZE - 1],
TASK_4_PRIO,
TASK_4_ID,
&Task4Stk[0],
TASK_STK_SIZE,
&TaskUserData[TASK_4_ID],
0);
strcpy(TaskUserData[TASK_5_ID].TaskName, "TimeDlyTask");
OSTaskCreateExt(Task5,
(void *)0,
&Task5Stk[TASK_STK_SIZE - 1],
TASK_5_PRIO,
TASK_5_ID,
&Task5Stk[0],
TASK_STK_SIZE,
&TaskUserData[TASK_5_ID],
0);
}
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);
}
}
Task3和4都是发送字符串,间隔半秒
void Task5 (void *pdata)
{
pdata = pdata;
for (;;) {
OSTimeDlyHMSM(0, 0, 0, 100);
}
}
void TaskClk (void *pdata)
{
char s[40];
pdata = pdata;
for (;;) {
PC_GetDateTime(s);
PC_DispStr(60, 23, s, DISP_FGND_YELLOW + DISP_BGND_BLUE);
OSTimeDlyHMSM(0, 0, 0, 500);
}
}
关于定义的接口函数的修改
OSTaskSwHook函数是在一个低优先级的任务切换到一个高优先级的任务时被调用
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 这个函数被调用的时候高优先级的任务还没有执行,因此OSTCBCur指向当前任务的任务控制块,而OSTCBHighRdy指向即将被调用运行的任务的任务控制块, OSTCBCur->OSTCBExtPtr是当前任务在建立时指定的数据结构的指针!!!*/
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 执行时间总和 */
}
}
当允许使用统计任务时即OS_TASK_STAT_EN配置常数设为1,统计任务将首先调用定义的OSTaskStatHook接口函数
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;
}
}
}