您的位置:首页 > 其它

UCOSII上任务堆栈检测OSTaskStkChk实例

2014-03-29 11:56 357 查看
网上讲解ucos 任务堆栈检测函数的人很多,而且对函数每一行都能说得清清楚楚,但给出实例的还是比较少。

像下面这位解释:

OSTaskStkChk(INT8U prio,OS_STK_DATA *pdata) /*检查优先级为prio的任务的堆栈使用情况,并把结果存入OS_STK_DATA类型的单元中*/

INT8U OSTaskStkChk(INT8U prio,OS_STK_DATA *pdata)

{

OS_TCB *ptcb; /*用于执行所要堆栈检测任务的TCB*/

OS_STK *pchk; /*用于指向所要堆栈检测的任务的堆栈*/

INT32U free; /*存放未使用的堆栈容量*/

INT32U size; /*存放堆栈总容量*/

pdata->OSFree=0; /*将用于存放堆栈检测结果的单元进行清零*/

pdata->OSUsed=0;

if(prio>OS_LOWEST_PRIO &&prio != OS_PRIO_SELF)/*查看优先级是否在有效范围内*/

{

return(OS_PRIO_INVALID);

}

OS_ENTER_CRITICAL();/*在对任务的TCB内容读取的过程中需要关中断,即TCB是临界资源,不可多个进程同时访问*/

if (prio==OS_PRIO_SELF) /*如果prio的值为OS_PRIO_SELF 即prio==0xFF,系统规定优先级为当前正在执行的任务*/

{

prio=OSTCBCur->OSTCBPrio;/*需要将prio的值更改为当前正在执行任务的优先级*/

}

ptcb=OSTCBPrioTbl[prio];/*根据任务的优先级和TCB优先级表,找到所要进程堆栈检测任务的TCB*/

if(ptcb==(OS_TCB *)0) /*判断任务是否存在,这个是针对,如果所要检查的任务并不是正在执行的任务*/

{

OS_EXIT_CRITICAL(); /*任务不存在的话,要先开中断,然后再返回*/

return (OS_TASK_NOT_EXIST);

}

if((ptcb->OSTCBopt&OS_TASK_OPT_STK_CHK)==0) /*在任务存在的前提下,再查看该任务是否允许堆栈检测*/

{ /*OSTCBopt中的内容为0的话OS_TACK_OPT_STK_CHK一定为零*/

OS_EXIT_CRITICAL(); /*而OS_TACK_OPT_STK_CHK为零的话,OSTCBopt不一定为零*/

return (OS_TASK_OPT_ERR);

} /*通过上面的操作顺利找到了TCB,下面的操作就是读取TCB中相关的信息*/

free = 0; /*将需要存放空闲堆栈大小的单元清零*/

size = ptcb->OSTCBStkSize; /*读取任务的堆栈的大小*/

pchk = ptcb->OSTCBStkBottom; /*读取栈底堆栈的值*/

OS_EXIT_CRITICAL(); /*TCB中需要的信息已经读取完毕了,此时不需要再霸占TCB了,所以开中断*/

#if OS_STK_GROWTH == 1 /*根据系统硬件的情况,进行空闲堆栈的计算*/

while(*pchk++ == 0)

{

free++;

}

#else

while(*pchk-- == 0)

{

free++;

}

#endif /*堆栈使用情况计算完毕,填写到所要存储的单元中,并返回堆栈查询没有出错*/

pdata->OSFree = free *sizeof(OS_STK); pdata->OSUsed = (size-free) * sizeof(OS_STK);

return (OS_NO_ERR);

}

原理在UCOSII.pdf也清楚说了。

实例:

首先必须是能任务堆栈检测:

os_cfg.h

#define OS_TASK_CREATE_EXT_EN 1

在创建任务时有些变化

OSTaskCreateExt(TaskInit,

(void *)0,

&TaskStartStkInit[0],

0, /* Task priority = 0 */

0,

&TaskStartStkInit[TASK_INIT_STK_SIZE-1],

TASK_INIT_STK_SIZE,

(void *)0,

OS_TASK_OPT_STK_CHK);

刚开始在网上看别人怎么用,结果都不行,到最后还是发现了问题,OSTaskCreateExt的opt参数也需改变下,在OSTaskStkChk有对参数进行检查。

当然像优先级也有规定要小于OS_LOWEST_PRIO.

在任务中:

#define TASK_INIT_STK_SIZE 128

OS_STK_DATA stkdata;

void TaskInit(void *nouse) reentrant

{

xdata unsigned char str[30]="";

unsigned int i;

nouse = nouse;

InitHardware();

for(i=0;i<65535;i++);//just for wait ...

for(;;)

{

for(i=0;i<30;i++)

{

str[i] = 0;

}

i = OSTaskStkChk(OS_PRIO_SELF,&stkdata);

sprintf(str,"free:%ld,used:%ld,errno:%d \r\n",stkdata.OSFree,stkdata.OSUsed,i);

SendStr(str, sizeof(str));

OSTimeDly(OS_TICKS_PER_SEC);

}

}

上面也是经过一些测试,最初系统总是出现问题,串口有时会多出乱码,最后不断调试,再根据OSTaskStkChk的实现和返回值重要确定了原因,溢出了。

还有OS_STK_DATA结构体成员的变量也需注意,是unsigned long的。

结果:

free:30,used:98,errno:0

但是,可能由于我对ucos或单片机堆栈认识不够吧,我不管怎么改变程序,发现结果还是一样,当然有可能代码是之前的工程师做了相应的改变吧。

free:30,used:98,errno:0

使用的字节数不变也不变少,这正是我纠结的地方。

但在ucos虽然移植成功了,但是还有很多问题不清楚的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: