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

论坛原始地址(持续更新):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方式
  •   这个函数的关键是通过任务控制列表检索所有创建的任务,并将相关信息打印出来。

 

打印效果如下:

 

8.3.2      RTT打印

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

#define Enable_RTTViewer  1

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

 

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

 

由于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   实验例程

本章节配套了例子:

  •   V6-3003_ThreadX Task Debug Info

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

 

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

#define Enable_RTTViewer  1

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

8.6   总结

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

 

posted @ 2021-04-20 15:21  硬汉嵌入式  阅读(402)  评论(0编辑  收藏  举报