主要统计任务优先级、任务堆栈使用大小、任务堆栈剩余大小、任务堆栈使用率、以及任务名称。(任务堆栈使用率 不同于 CPU使用率)该任务统计的是实时的栈使用情况,不是最大的。
一、统计任务堆栈使用情况
想要实现任务堆栈的统计必须使用OSTaskCreateExt()创建任务,且OS_TASK_CREATE_EXT_EN置1。
#define OS_TASK_CREATE_EXT_EN 1u /* Include code for OSTaskCreateExt() */
#if OS_TASK_CREATE_EXT_EN > 0u
INT8U OSTaskCreateExt (void (*task)(void *p_arg),
void *p_arg,
OS_STK *ptos,
INT8U prio,
INT16U id,
OS_STK *pbos,
INT32U stk_size,
void *pext,
INT16U opt);
#endif
OSTaskCreateExt()函数的使用:
OSTaskCreateExt()建立任务_*fzfw的博客-CSDN博客
任务堆栈的统计最终使用OSTaskStkChk()函数来实现。要想使得OSTaskStkChk()有效,必须将宏OS_TASK_STAT_STK_CHK_EN、OS_TASK_CREATE_EXT_EN都置1,堆栈检测任务OSTaskStkChk()才有效。
#define OS_TASK_STAT_STK_CHK_EN 1u // 从统计任务中检查任务堆栈使能
#define OS_TASK_CREATE_EXT_EN 1u // OSTaskCreateExt()使能
#if (OS_TASK_STAT_STK_CHK_EN > 0u) && (OS_TASK_CREATE_EXT_EN > 0u)
OS_TaskStatStkChk(); //配置允许时,进行堆栈检测
#endif
二、任务名相关说明
设置任务名称需要将宏OS_TASK_NAME_EN置1
#define OS_TASK_NAME_EN 1u /* Enable task names */
设置任务名称的函数为OSTaskNameSet() ,在创建任务时调用该函数定义任务名。
// prio : 任务优先级
// pname : 任务名字
// perr : 错误代码
void OSTaskNameSet (INT8U prio, INT8U *pname, INT8U *perr)
设置任务名源码
/**********************************************************************************************************
* ASSIGN A NAME TO A TASK
*
* Description: This function is used to set the name of a task.
*
* Arguments : prio is the priority of the task that you want the assign a name to.
*
* pname is a pointer to an ASCII string that contains the name of the task.
*
* perr is a pointer to an error code that can contain one of the following values:
*
* OS_ERR_NONE if the requested task is resumed
* OS_ERR_TASK_NOT_EXIST if the task has not been created or is assigned to a Mutex
* OS_ERR_PNAME_NULL You passed a NULL pointer for 'pname'
* OS_ERR_PRIO_INVALID if you specified an invalid priority:
* A higher value than the idle task or not OS_PRIO_SELF.
* OS_ERR_NAME_SET_ISR if you called this function from an ISR
*
* Returns : None
**********************************************************************************************************/
#if OS_TASK_NAME_EN > 0u
void OSTaskNameSet (INT8U prio,//优先级
INT8U *pname,//任务名
INT8U *perr)
{
OS_TCB *ptcb;
#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr = 0u;
#endif
#ifdef OS_SAFETY_CRITICAL
if (perr == (INT8U *)0) {
OS_SAFETY_CRITICAL_EXCEPTION();
return;
}
#endif
#if OS_ARG_CHK_EN > 0u
if (prio > OS_LOWEST_PRIO) { /* Task priority valid ? */
if (prio != OS_PRIO_SELF) {
*perr = OS_ERR_PRIO_INVALID; /* No */
return;
}
}
if (pname == (INT8U *)0) { /* Is 'pname' a NULL pointer? */
*perr = OS_ERR_PNAME_NULL; /* Yes */
return;
}
#endif
if (OSIntNesting > 0u) { /* See if trying to call from an ISR */
*perr = OS_ERR_NAME_SET_ISR;
return;
}
OS_ENTER_CRITICAL();
if (prio == OS_PRIO_SELF) { /* See if caller desires to set it's own name */
prio = OSTCBCur->OSTCBPrio;
}
ptcb = OSTCBPrioTbl[prio];
if (ptcb == (OS_TCB *)0) { /* Does task exist? */
OS_EXIT_CRITICAL(); /* No */
*perr = OS_ERR_TASK_NOT_EXIST;
return;
}
if (ptcb == OS_TCB_RESERVED) { /* Task assigned to a Mutex? */
OS_EXIT_CRITICAL(); /* Yes */
*perr = OS_ERR_TASK_NOT_EXIST;
return;
}
ptcb->OSTCBTaskName = pname;
OS_EXIT_CRITICAL();
*perr = OS_ERR_NONE;
}
#endif
四、任务堆栈使用情况输出打印效果
说明:
uC/OS-II Idle为空闲任务。
uC/OS-II Stat为统计任务。
uC/OS-II Tmr为软件定时器任务。
空闲任务为系统自动创建任务且为必须创建的任务,空闲任务的优先级最低。
软件定时器任务优先级最高,且软件定时器任务可通过宏定义来决定是否创建。
宏OS_TMR_EN为1,则创建软件定时器任务。
宏OS_TASK_STAT_EN为1,则创建统计任务。
printf使用前,需要对 fputc 函数进行重定向,这样可以使其发送到指定的串口。当选上”Use MicroLIB”这是KEIL自带的一个简易的库,例如你用printf函数的时候,就会从串口1 输出字符串,直接默认定向到串口1。只要在任意一个运行的任务中调用该函数就可以了。
/**********************************************************************************************************************************************
* 函数名 : vAppTask_DebugInfo
* 描 述 : 任务堆栈信息
**********************************************************************************************************************************************/
static void vAppTask_DebugInfo(void)
{
OS_TCB *ptcb; //定义一个任务控制块,结构体指针
OS_STK_DATA stkDat; //定义堆栈结构体变量
ptcb = &OSTCBTbl[0];//将指针指向任务表的第一个任务
printf("************************************ App Task Debug Info ***********************************\r\n");
printf(" Prio Used Free Per TaskName\r\n");
while (ptcb != NULL)//轮询每一个任务
{
OSTaskStkChk(ptcb->OSTCBPrio, &stkDat);//Check task stack
printf(" %2d %5d %5d %02d%% %s\r\n", ptcb->OSTCBPrio, stkDat.OSUsed, stkDat.OSFree, (stkDat.OSUsed * 100)/(stkDat.OSUsed + stkDat.OSFree), ptcb->OSTCBTaskName);
ptcb = ptcb->OSTCBPrev;//Previous TCB list
}
printf("\r\n");
}
************************************ App Task Debug Info ***********************************
Prio Used Free Per TaskName
63 15 113 11% uC/OS-II Idle
62 21 107 16% uC/OS-II Stat
0 25 103 19% uC/OS-II Tmr
5 66 14 82% Start
10 66 34 66% USART3
9 27 73 27% USART2
11 27 73 27% IWDG
12 52 48 52% Queue
3 27 73 27% Debug