0
点赞
收藏
分享

微信扫一扫

【STM32H7】第8章 ThreadX调试方法(串口和RTT两种方式打印任务执行情况)

逸省 2022-09-09 阅读 188

论坛原始地址(持续更新):http://www.armbbs.cn/forum.php?mod=viewthread&tid=99514

第8章   ThreadX调试方法(串口和RTT两种方式打印任务执行情况)

本章节为大家介绍ThreadX的调试方法,这里的调试方法主要是教会大家如何获取任务的执行情况,通过获取的任务信息,可以进一步的配置和优化工程,这种方法非常实用,建议初学者必须掌握。

8.1 初学者重要提示

8.1 串口或RTT打印调试说明

8.2 ThreadX实现串口或者RTT打印任务执行情况

8.3 ThreadX的CPU利用率实现方法

8.4 总结

 

 

8.1   初学者重要提示。

  • RTT打印相关基础知识可以看此贴:

【专题教程第5期】工程调试利器RTT实时数据传输组件,替代串口调试,速度飞快,可以在中断和多任务中随意调用

​​http://www.armbbs.cn/forum.php?mod=viewthread&tid=86177​​ 。

8.2   串口或RTT打印调试说明

很多时候我们需要了解任务的执行状态,任务栈的使用情况以及各个任务的CPU使用率。对此,我们这里封装了一个函数。

获取了任务执行情况后,可以通过串口或者RTT将其打印出来,当然,也可以通过任何其它方式将其显示出来。本教程配套的例子配套了串口和RTT两种打印方式显示任务的执行情况。另外有一点要特别注意,这种调试方式仅限测试目的,实际项目中不要使用。

8.3   ThreadX实现串口或者RTT打印任务执行情况

我们这里分串口和RTT两种打印方式为大家做个说明。

8.3.1      串口打印

串口打印主要用于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;
}
}

  • 函数App_Printf专门封装了一个线程安全的printf方式
  • 这个函数的关键是通过任务控制列表检索所有创建的任务,并将相关信息打印出来。

打印效果如下:

【STM32H7】第8章   ThreadX调试方法(串口和RTT两种方式打印任务执行情况)_串口

 

8.3.2      RTT打印

本章节配套的例子对RTT打印方式也做了支持,对于MDK AC5,MDK AC6或者IAR,使能bsp.h文件中的宏定义为1即可

#define Enable_RTTViewer  1

实现方法和串口打印是一样的,只是换了一种打印方式。效果如下(也可以用SEGGER的 RTT Viewer):

 

【STM32H7】第8章   ThreadX调试方法(串口和RTT两种方式打印任务执行情况)_串口_02

使用Embedded Studio的话,不要使能宏定义,它可以直接调试状态在IDE上展示:

 

【STM32H7】第8章   ThreadX调试方法(串口和RTT两种方式打印任务执行情况)_宏定义_03

由于Embedded Studio不支持中文,所以中文部分显示乱码,不用管。

8.4   ThreadX的CPU利用率实现方法

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
}
}

实现步骤如下:

  • 进入到启动任务后,其它任何任务都不要创建,先创建一个统计任务,不让执行。
  • 启动任务延迟100ms,延迟的这100ms时间基本都是空闲任务在执行,在空闲任务里面做32变量加1计算。我们就以这100ms,变量计数的最大值作为CPU利用率的分母。
  • 然后开启统计任务的执行,每100ms执行一次,统计即可。空闲任务此时的计数值作为分子。通过这种方式就实现了CPU利用率的统计。

8.5   实验例程

本章节配套了例子:

  • V7-3003_ThreadX Task Debug Info

含有GCC,IAR,MDK AC5和AC6四个版本工程。

 

通过按键K1打印任务的执行情况,工程默认是通过串口打印的,如果使用RTT打印的话,使用bsp.h中的宏定义为1即可。

#define Enable_RTTViewer  1

使用Embedded Studio的话,不要使能宏定义,它可以直接调试状态在IDE上展示。

8.6   总结

本章节主要是指导大家如何获取任务的执行情况,非常的实用,建议初学者务必掌握。

 

微信公众号:armfly_com


举报

相关推荐

0 条评论