uCOSii_任务栈检测和任务栈清除

1、任务栈检测和任务栈清除

在创建任务时,也需要设置OSTaskCreateExt()传入opt参数。

opt= (INT16U)(OS_TASK_OPT_STK_CLR | OS_TASK_OPT_STK_CHK),可以使用OSTaskStkChk()检查的任务栈的剩余空间,也可以使用OS_TaskStkClr()清除任务栈。

2、创建任务举例

#define LED0_TASK_PRIORITY   5     //设置LED0_TASK任务优先级为5

#define LED0_TASK_STACK_SIZE             88

//设置LED0_TASK任务堆栈大小为88, 8的倍数

//如果任务中使用printf来打印浮点数据的话一点要8字节对齐

OS_STK LED0_TASK_STACK[LED0_TASK_STACK_SIZE];//LED0_TASK任务栈

//LED0_TASK任务

void LED0_TASK(void *pdata)

{

         (void)pdata;

         while(1)

         {

                   OSTimeDlyHMSM(0,0,0,500);//延时500ms

         }

}

OSTaskCreateExt(

LED0_TASK,/*任务函数指针*/

(void *)0,/*建立任务时,传递的参数*/                                                                                   

(OS_STK*)&LED0_TASK_STACK[LED0_TASK_STACK_SIZE-1],/*指向任务栈顶的指针*/

LED0_TASK_PRIORITY, /*任务优先级*/

LED0_TASK_PRIORITY,/*任务ID用优先级代替,2.52版本,无实际作用,保留作为扩展用*/

(OS_STK*)&LED0_TASK_STACK[0],/*指向栈底部的指针,用于OSTaskStkChk()函数*/

LED0_TASK_STACK_SIZE, /*指定任务堆栈的大小,OS_STK类型决定*/

(void *)0, /*定义数据结构的指针,作为TCB的扩展*/

(INT16U)(OS_TASK_OPT_STK_CLR | OS_TASK_OPT_STK_CHK)/*允许任务栈检查*/

);

3OSTaskStkChk()函数

1)、在使用OSTaskStkChk()之前,要先声明OS_STK_DATA结构变量,如下:

OS_STK_DATA  TaskStackData;

2)、OSTaskStkChk()应用举例

OSTaskStkChk( LED0_TASK_PRIORITY, &TaskStackData);

3)、分析解析OSTaskStkChk()函数

函数功能:结构指针p_stk_data返回的数据就是该任务栈的使用情况

//prio表示任务优先级

INT8U  OSTaskStkChk (INT8U prio, OS_STK_DATA  *p_stk_data)

{

    OS_TCB    *ptcb; //任务控制块的指针

    OS_STK    *pchk;//任务栈的指针

    INT32U     nfree;//该任务栈的剩余空间大小,单位为OS_STK

INT32U     size;//该任务栈的总空间大小,单位为OS_STK

//unsigned int重命名为OS_STK

#if OS_CRITICAL_METHOD == 3u

    OS_CPU_SR  cpu_sr = 0u;

#endif

参数检查开始//

#if OS_ARG_CHK_EN > 0u

if (prio > OS_LOWEST_PRIO)

{/*若任务优先级prio比最低优先级(空闲任务优先级),则表示任务优先级错误*/

        if (prio != OS_PRIO_SELF)

        {//自身优先级OS_PRIO_SELF255

            return (OS_ERR_PRIO_INVALID);//优先级无效

        }

    }

if (p_stk_data == (OS_STK_DATA *)0)

{/*p_stk_data结构指针为0*/

        return (OS_ERR_PDATA_NULL);

    }

#endif

    p_stk_data->OSFree = 0u; /*假定任务栈的可用空间0*/

    p_stk_data->OSUsed = 0u; /*假定任务栈的已用空间0*/

    OS_ENTER_CRITICAL();//进入临界区(无法被中断打断),需要定义cpu_sr变量

if (prio == OS_PRIO_SELF)

{/*若任务优先级prio为自身优先级,需要读取当前任务的优先级*/

        prio = OSTCBCur->OSTCBPrio;

        //读取当前任务的优先级

        // OSTCBCur指向“当前任务控制块”的指针

}

ptcb = OSTCBPrioTbl[prio];

//根据所给的任务优先级prio,读取任务控制块的指针

//*OSTCBPrioTbl[]为所有的任务控制块的指针

//OSTCBTbl[]任务控制块数组,所有的任务控制块都保存在这个数组中

if (ptcb == (OS_TCB *)0)

{/*任务控制块的指针ptcb0 */

        OS_EXIT_CRITICAL();//退出临界区(可以被中断打断)

        return (OS_ERR_TASK_NOT_EXIST);

}

if (ptcb == OS_TCB_RESERVED)

{/*任务控制块的指针ptcbOS_TCB_RESERVED,OS_TCB_RESERVED =1 */

        OS_EXIT_CRITICAL();//退出临界区(可以被中断打断)

        return (OS_ERR_TASK_NOT_EXIST);

}

if ((ptcb->OSTCBOpt & OS_TASK_OPT_STK_CHK) == 0u)

{

 //调用OSTaskCreateExt()时会传入opt

 //opt= (INT16U)(OS_TASK_OPT_STK_CLR | OS_TASK_OPT_STK_CHK)

 //OS_TASK_OPT_STK_CHK允许任务栈检查

        OS_EXIT_CRITICAL();//退出临界区(可以被中断打断)

        return (OS_ERR_TASK_OPT);

}

参数检查结束//

    nfree = 0u; //假定该任务栈的剩余空间大小为0,单位为OS_STK

size  = ptcb->OSTCBStkSize;//读取该任务栈的总空间大小,单位为OS_STK

    pchk  = ptcb->OSTCBStkBottom;//读取该任务栈的栈底指针

    OS_EXIT_CRITICAL();//退出临界区(可以被中断打断)

#if OS_STK_GROWTH == 1u

// OS_STK_GROWTH为栈的增长方向,1表示栈是向下增长

//CM3,栈是由高地址向低地址增长的,所以OS_STK_GROWTH设置为1

while (*pchk++ == (OS_STK)0)

{

        nfree++;

        //计算任务栈的剩余空间大小”,单位为OS_STK

        //栈是由高地址向低地址增长的,所以栈底的地址较小,使用pchk++

    }

#else

while (*pchk-- == (OS_STK)0)

{

        nfree++;

        //计算任务栈的剩余空间大小”,单位为OS_STK

        //栈是由低地址向高地址增长的,所以栈底的地址较大,使用pchk--

    }

#endif

p_stk_data->OSFree = nfree * sizeof(OS_STK);

/* unsigned int重命名为OS_STK,计算该任务栈的可用空间大小,单位为字节数*/

p_stk_data->OSUsed = (size - nfree) * sizeof(OS_STK);

/*Compute number of bytes used on the stack*/

    return (OS_ERR_NONE);

}

4OS_TaskStkClr()函数

1)、警慎调用OS_TaskStkClr()函数,否则可能会导致系统崩溃。

注意:这个函数是给OSTaskCreateExt()调用的,在创建任务时,需要将任务栈初始化为0。在任务中不要随便调用

2)、分析解析OS_TaskStkClr()函数

函数功能:清除任务栈

//pbos为指向栈底部的指针

//size为任务堆栈的大小

//opt= (INT16U)(OS_TASK_OPT_STK_CLR | OS_TASK_OPT_STK_CHK),该函数才会执行

void OS_TaskStkClr (OS_STK *pbos, INT32U size, INT16U opt)

{

if ((opt & OS_TASK_OPT_STK_CHK) != 0x0000u)

{ //调用OSTaskCreateExt()时会传入opt

 //opt= (INT16U)(OS_TASK_OPT_STK_CLR | OS_TASK_OPT_STK_CHK)

 //OS_TASK_OPT_STK_CHK允许任务栈检查

        if ((opt & OS_TASK_OPT_STK_CLR) != 0x0000u)

        {/*See if stack needs to be cleared*/

#if OS_STK_GROWTH == 1u

// OS_STK_GROWTH为栈的增长方向,1表示栈是向下增长

//CM3,栈是由高地址向低地址增长的,所以OS_STK_GROWTH设置为1

            while (size > 0u) //循环将任务栈清除

            {/*Stack grows from HIGH to LOW memory*/

                size--;

                *pbos++ = (OS_STK)0;

                //从栈底向上清除

                //栈是由高地址向低地址增长的,所以栈底的地址较小,使用pchk++

            }

#else

            while (size > 0u)

            {/*Stack grows from LOW to HIGH memory*/

                size--;

                *pbos-- = (OS_STK)0; /*Clear from bottom of stack and down*/

                //从栈底向下清除

                //栈是由低地址向高地址增长的,所以栈底的地址较大,使用pchk--

            }

#endif

        }

    }

}

3)、OS_TaskStkClr()应用举例

这是给好奇心很强的人看的。再次强调,不要随便调用

OS_TaskStkClr(

(OS_STK*)&LED0_TASK_STACK[0],/*指向栈底部的指针,用于OSTaskStkChk()函数*/

LED0_TASK_STACK_SIZE, /*指定任务堆栈的大小,OS_STK类型决定*/

(INT16U)(OS_TASK_OPT_STK_CLR | OS_TASK_OPT_STK_CHK)/*允许任务栈清除*/

);

5、实际应用

const char CHECK_TASK_rn_REG[]="\r\n";

const char CHECK_TASK_Initialise_REG[]="CHECK_TASK Initialise";

const char LED0_TASK_used_Or_free_REG[]="LED0_TASK used/free:";

const char LED1_TASK_used_Or_free_REG[]="LED1_TASK used/free:";

const char KEY_TASK_used_Or_free_REG[]="KEY_TASK used/free:";

const char CHECK_TASK_used_Or_free_REG[]="CHECK_TASK used/free:";

const char Used_REG[]="  used%";

const char Err_REG[]="  err:";

void CHECK_TASK(void *pdata)

{

         OS_STK_DATA  pTaskStackData;

         u8 err1 =0;//1079062528

         (void)pdata;

         printf("%s",CHECK_TASK_rn_REG);

         printf("%s",CHECK_TASK_Initialise_REG);

         while(1)

         {

                   err1 = OSTaskStkChk( LED0_TASK_PRIORITY, &pTaskStackData);

                   printf("%s",CHECK_TASK_rn_REG);

                   printf("%s",LED0_TASK_used_Or_free_REG);

        printf("%d/",pTaskStackData.OSUsed);

        printf("%d",pTaskStackData.OSFree);

                   printf("%s",Used_REG);

printf( "%0.2f",(float)(pTaskStackData.OSUsed*100)/(float)(pTaskStackData.OSUsed+pTaskStackData.OSFree) );

                   printf("%s",Err_REG);printf("%d",err1);

                   printf("%s",CHECK_TASK_rn_REG);

                   err1 = OSTaskStkChk( LED1_TASK_PRIORITY, &pTaskStackData);

                   printf("%s",LED1_TASK_used_Or_free_REG);

        printf("%d/",pTaskStackData.OSUsed);

        printf("%d",pTaskStackData.OSFree);

                   printf("%s",Used_REG);

printf( "%0.2f",(float)(pTaskStackData.OSUsed*100)/(float)(pTaskStackData.OSUsed+pTaskStackData.OSFree) );

                   printf("%s",Err_REG);printf("%d",err1);

                   printf("%s",CHECK_TASK_rn_REG);

                   err1 = OSTaskStkChk( KEY_TASK_PRIORITY, &pTaskStackData);

                   printf("%s",KEY_TASK_used_Or_free_REG);

        printf("%d/",pTaskStackData.OSUsed);

        printf("%d",pTaskStackData.OSFree);

                   printf("%s",Used_REG);

printf( "%0.2f",(float)(pTaskStackData.OSUsed*100)/(float)(pTaskStackData.OSUsed+pTaskStackData.OSFree) );

                   printf("%s",Err_REG);printf("%d",err1);

                   printf("%s",CHECK_TASK_rn_REG);

                   err1 = OSTaskStkChk( CHECK_TASK_PRIORITY, &pTaskStackData);

             printf("%s",CHECK_TASK_used_Or_free_REG);

        printf("%d/",pTaskStackData.OSUsed);

        printf("%d",pTaskStackData.OSFree);

                   printf("%s",Used_REG);

printf( "%0.2f",(float)(pTaskStackData.OSUsed*100)/(float)(pTaskStackData.OSUsed+pTaskStackData.OSFree) );

                   printf("%s",Err_REG);printf("%d",err1);

                   printf("%s",CHECK_TASK_rn_REG);

                   OSTimeDlyHMSM(0,0,5,0);//延时5s

         }

}

输出结果:

LED0_TASK used/free:184/168  used%52.27  err:0

LED1_TASK used/free:212/172  used%55.21  err:0

KEY_TASK used/free:184/168  used%52.27  err:0

CHECK_TASK used/free:444/68  used%86.72  err:0

uCOSii_任务栈检测和任务栈清除_第1张图片 

 

你可能感兴趣的:(产品研发,uCOSii,实时操作系统,RTOS,任务栈,单片机)