} } }
任务4的操作只是从邮箱发送[程序清单L1.25(1)]和接收[程序清单L1.25(2)],这使得用户可以测量任务在自己PC上执行的时间。任务4每10mS执行一次[程序清单L1.25(3)]。
程序清单 L 1.25 任务4。 void Task4 (void *data) {
OS_EVENT *mbox; INT8U err;
data = data;
mbox = OSMboxCreate((void *)0); for (;;) {
OSMboxPost(mbox, (void *)1); (1) OSMboxPend(mbox, 0, &err); (2) OSTimeDlyHMSM(0, 0, 0, 10); (3) } }
任务5除了延时一个时钟节拍以外什么也不做[程序清单L1.26(1)]。注意所有的任务都应该调用uCOS-II的函数,等待延时结束或者事件的发生而让出CPU。如果始终占用CPU,这将使低优先级的任务无法得到CPU。
程序清单 L 1.26 任务5。 void Task5 (void *data) {
data = data; for (;;) {
OSTimeDly(1); (1) } }
同样, TaskClk()函数[程序清单L1.18]显示当前日期和时间。 1.09.03注意
有些程序的细节只有请您仔细读一读EX3L.C才能理解。EX3L.C中有OSTaskSwHook()函数的代码,该函数用来测量每个任务的执行时间,可以用来统计每一个任务的调度频率,也可以统计每个任务运行时间的总和。这些信息将存储在每个任务的TCB扩展数据结构中。每次任务切换的时候OSTaskSwHook()都将被调用。
每次任务切换发生的时候,OSTaskSwHook()先调用PC_ElapsedStop()函数[程序清单L1.27(1)] 来获取任务的运行时间[程序清单L1.27(1)],PC_ElapsedStop()要和PC_ElapsedStart()一起使用,上述两个函数用到了PC的定时器2(timer 2)。其中PC_ElapsedStart()功能为启动定时器开始记数;而PC_ElapsedStop()功能为获取定时器的值,然后清零,为下一次计数做准备。从定时器取得的计数将拷贝到time变量[程序清单L1.27(1)]。然后OSTaskSwHook()调用PC_ElapsedStart()重新启动定时器做下一次计数[程序清单L1.27(2)]。需要注意的是,系统启动后,第一次调用PC_ElapsedStart()是在初始化代码中,所以第一次任务切换调用PC_ElapsedStop()所得到的计数值没有实际意义,但这没有什么影响。如果任务分配了TCB扩展数据结构[程序清单L1.27(4)],其中的计数器TaskCtr进行累加[程序清单L1.27(5)]。TaskCtr可以统计任务被切换的频繁程度,也可以检查某个任务是否在
运行。TaskExecTime [程序清单L1.27(6)]用来记录函数从切入到切出的运行时间,
TaskTotExecTime[程序清单L1.27(7)]记录任务总的运行时间。统计每个任务的上述两个变量,可以计算出一段时间内各个任务占用CPU的百分比。OSTaskStatHook()函数会显示这些统计信息。
程序清单 L 1.27 用户定义的OSTaskSwHook() void OSTaskSwHook (void) {
INT16U time; TASK_USER_DATA *puser;
time = PC_ElapsedStop(); (1) PC_ElapsedStart(); (2) puser = OSTCBCur->OSTCBExtPtr; (3) if (puser != (void *)0) { (4) puser->TaskCtr++; (5) puser->TaskExecTime = time; (6) puser->TaskTotExecTime += time; (7) } }
本例中的统计任务(statistic task)将调用对外接口函数OSTaskStatHook()(设置OS_CFG.H文件中的OS_TASK_STAT_EN为1允许对外接口函数)。统计任务每秒运行一次,本例中OSTaskStatHook()用来计算并显示各任务占用CPU的情况。
OSTaskStatHook()函数中首先计算所有任务的运行时间[程序清单L1.28(1)],DispTaskStat()用来将数字显示为ASCII字符[程序清单L1.28(2)]。然后是计算每个任务运行时间的百分比[程序清单L1.28(3)],显示在合适的位置上 [程序清单L1.28(4)]。 程序清单 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, \
PC_DispStr(62, i + 11, s, DISP_FGND_YELLOW); (4) } }
if (total > 1000000000L) { for (i = 0; i < 7; i++) {
TaskUserData.TaskTotExecTime = 0L; } } }