论坛原始地址(持续更新):http://www.armbbs.cn/forum.php?mod=viewthread&tid=99514
本章节为大家介绍ThreadX的调试方法,这里的调试方法主要是教会大家如何获取任务的执行情况,通过获取的任务信息,可以进一步的配置和优化工程,这种方法非常实用,建议初学者必须掌握。
8.1 初学者重要提示
8.1 串口或RTT打印调试说明
8.2 ThreadX实现串口或者RTT打印任务执行情况
8.3 ThreadX的CPU利用率实现方法
8.4 总结
【专题教程第5期】工程调试利器RTT实时数据传输组件,替代串口调试,速度飞快,可以在中断和多任务中随意调用
http://www.armbbs.cn/forum.php?mod=viewthread&tid=86177 。
很多时候我们需要了解任务的执行状态,任务栈的使用情况以及各个任务的CPU使用率。对此,我们这里封装了一个函数。
获取了任务执行情况后,可以通过串口或者RTT将其打印出来,当然,也可以通过任何其它方式将其显示出来。本教程配套的例子配套了串口和RTT两种打印方式显示任务的执行情况。另外有一点要特别注意,这种调试方式仅限测试目的,实际项目中不要使用。
我们这里分串口和RTT两种打印方式为大家做个说明。
串口打印主要用于MDK AC5,MDK AC6或者IAR创建的工程。通过下面函数实现任务执行情况信息获取:
/*
*********************************************************************************************************
* 函 数 名: DispTaskInfo
* 功能说明: 将ThreadX任务信息通过串口打印出来
* 形 参:无
* 返 回 值: 无
*********************************************************************************************************
*/
static void DispTaskInfo(void)
{
TX_THREAD *p_tcb; /* 定义一个任务控制块指针 */
p_tcb = &AppTaskStartTCB;
/* 打印标题 */
App_Printf("===============================================================\r\n");
App_Printf("OS CPU Usage = %5.2f%%\r\n", OSCPUUsage);
App_Printf("===============================================================\r\n");
App_Printf(" 任务优先级 任务栈大小 当前使用栈 最大栈使用 任务名\r\n");
App_Printf(" Prio StackSize CurStack MaxStack Taskname\r\n");
/* 遍历任务控制块列表(TCB list),打印所有的任务的优先级和名称 */
while (p_tcb != (TX_THREAD *)0)
{
App_Printf(" %2d %5d %5d %5d %s\r\n",
p_tcb->tx_thread_priority,
p_tcb->tx_thread_stack_size,
(int)p_tcb->tx_thread_stack_end - (int)p_tcb->tx_thread_stack_ptr,
(int)p_tcb->tx_thread_stack_end - (int)p_tcb->tx_thread_stack_highest_ptr,
p_tcb->tx_thread_name);
p_tcb = p_tcb->tx_thread_created_next;
if(p_tcb == &AppTaskStartTCB) break;
}
}
打印效果如下:
本章节配套的例子对RTT打印方式也做了支持,对于MDK AC5,MDK AC6或者IAR,使能bsp.h文件中的宏定义为1即可
#define Enable_RTTViewer 1
实现方法和串口打印是一样的,只是换了一种打印方式。效果如下(也可以用SEGGER的 RTT Viewer):
使用Embedded Studio的话,不要使能宏定义,它可以直接调试状态在IDE上展示:
由于Embedded Studio不支持中文,所以中文部分显示乱码,不用管。
ThreadX的CPU利用率主要是通过创建一个统计任务和一个空闲任务来实现:
/*
*********************************************************************************************************
* 函 数 名: AppTaskStatistic
* 功能说明: 统计任务,用于实现CPU利用率的统计。为了测试更加准确,可以开启注释调用的全局中断开关
* 形 参: thread_input 创建该任务时传递的形参
* 返 回 值: 无
* 优 先 级: 30
*********************************************************************************************************
*/
void OSStatInit (void)
{
OSStatRdy = FALSE;
tx_thread_sleep(2u); /* 时钟同步 */
//__disable_irq();
OSIdleCtr = 0uL; /* 清空闲计数 */
//__enable_irq();
tx_thread_sleep(100); /* 统计100ms内,最大空闲计数 */
//__disable_irq();
OSIdleCtrMax = OSIdleCtr; /* 保存最大空闲计数 */
OSStatRdy = TRUE;
//__enable_irq();
}
static void AppTaskStat(ULONG thread_input)
{
(void)thread_input;
while (OSStatRdy == FALSE)
{
tx_thread_sleep(200); /* 等待统计任务就绪 */
}
OSIdleCtrMax /= 100uL;
if (OSIdleCtrMax == 0uL)
{
OSCPUUsage = 0u;
}
//__disable_irq();
OSIdleCtr = OSIdleCtrMax * 100uL; /* 设置初始CPU利用率 0% */
//__enable_irq();
for (;;)
{
// __disable_irq();
OSIdleCtrRun = OSIdleCtr; /* 获得100ms内空闲计数 */
OSIdleCtr = 0uL; /* 复位空闲计数 */
// __enable_irq(); /* 计算100ms内的CPU利用率 */
OSCPUUsage = (100uL - (float)OSIdleCtrRun / OSIdleCtrMax);
tx_thread_sleep(100); /* 每100ms统计一次 */
}
}
/*
*********************************************************************************************************
* 函 数 名: AppTaskIDLE
* 功能说明: 空闲任务
* 形 参: thread_input 创建该任务时传递的形参
* 返 回 值: 无
优 先 级: 31
*********************************************************************************************************
*/
static void AppTaskIDLE(ULONG thread_input)
{
TX_INTERRUPT_SAVE_AREA
(void)thread_input;
while(1)
{
TX_DISABLE
OSIdleCtr++;
TX_RESTORE
}
}
实现步骤如下:
本章节配套了例子:
含有GCC,IAR,MDK AC5和AC6四个版本工程。
通过按键K1打印任务的执行情况,工程默认是通过串口打印的,如果使用RTT打印的话,使用bsp.h中的宏定义为1即可。
#define Enable_RTTViewer 1
使用Embedded Studio的话,不要使能宏定义,它可以直接调试状态在IDE上展示。
本章节主要是指导大家如何获取任务的执行情况,非常的实用,建议初学者务必掌握。