FreeRtos入门-9 统计任务信息

统计任务信息

1,目的:可以通过查看任务的CPU情况、使用栈情况,进行针对优化

2,栈使用情况:由于创建任务时候,栈固定的填充了0xa5,以后可以通过使用下面函数查看栈的高水位,也就是剩余栈空间

UBaseType_t uxTaskGetStackHighWaterMark( TaskHandle_t xTask );

原理是:从栈底往栈顶逐个字节地判断,它们的值持续是0xa5就表示它是空闲的

3,任务运行时间统计:需要比tick更快的始终,比如tick周期1ms,选择0.1ms的定时器

  1. 切换task1时候,使用更快的定时器记录当前时间T1
  2. task1被切出去时,使用更快的定时器记录当前时间T4
  3. T4-T1 就是运行时间,累加起来。

代码学习步骤

1,在main.c包含更高timer的相关配置

#include "timer.h"
/*main.c 创建两个任务*/
    xTaskCreate(Task1Function, "Task1", 100, NULL, 1, &xHandleTask1);
    xTaskCreate(Task2Function, "Task2", 100, NULL, 1, NULL);

/*新建两个任务*/
char pcWriteBuffer[200];
void Task1Function(void * param)
{
    volatile int i = 0;
    while (1)
    {
        vTaskGetRunTimeStats(pcWriteBuffer);/*获取vTaskGetRunTimeStats running信息*/
        printf(pcWriteBuffer);/*打印*/
        vTaskDelay(5000);
    }
}

void Task2Function(void * param)
{
    volatile int i = 0;
    while (1)
    {
    }
}

在启动调度文件vTaskStartScheduler()中,包含了代码:

portCONFIGURE_TIMER_FOR_RUN_TIME_STATS();

启动更高定时器

在FreeRTOSConfig.h 文件中

添加宏定义

extern void TimerInit(void);
extern unsigned int TimerGetCount(void);

#define configGENERATE_RUN_TIME_STATS 1
#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS     TimerInit
#define portGET_RUN_TIME_COUNTER_VALUE             TimerGetCount
#define configUSE_TRACE_FACILITY    1
#define configUSE_STATS_FORMATTING_FUNCTIONS  1

extern void TimerInit(void);

#define configGENERATE_RUN_TIME_STATS 1

#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS TimerInit

这3条宏定义,作用是将vTaskStartScheduler 开启调度函数中的

portCONFIGURE_TIMER_FOR_RUN_TIME_STATS 定义为TimerInit

即在开启调度函数中调用定时器初始化函数。

运行路径:

TimerInit<=#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS TimerInit

portCONFIGURE_TIMER_FOR_RUN_TIME_STATS<=vTaskStartScheduler

extern unsigned int TimerGetCount(void);

#define portGET_RUN_TIME_COUNTER_VALUE TimerGetCount

#define configUSE_TRACE_FACILITY 1

#define configUSE_STATS_FORMATTING_FUNCTIONS 1

在timer.c中定义了一个全局变量,在定时器中断中,自增

#include "timer.h"
#include "stm32f10x_tim.h"

NVIC_InitTypeDef            gTIMx_NVIC_Init;        // 定义一个中断对象结构体
TIM_TimeBaseInitTypeDef     gTIMX_TimeBase_Init;    // 定义一个定时器对象结构体

static vu8 test_cnt = 0;

static unsigned int  g_timer_cnt;

void TimerInit(void)
{    
    /* 1. 使能时钟 */
    TIMx_Clk_Enable();
    
    /* 2. 配置定时器对象结构体的成员,设置定时器属性 */
    gTIMX_TimeBase_Init.TIM_Period          = TIMx_PRE_LOAD_VALUE;      // 设置预装载值,定时器会向上从0计数到value或者向下从value计数到0
    gTIMX_TimeBase_Init.TIM_Prescaler       = TIMx_PRESCALER;           // 设置预分频系数
    gTIMX_TimeBase_Init.TIM_ClockDivision   = TIMx_DIV;                 // 设置分频系数     
    gTIMX_TimeBase_Init.TIM_CounterMode     = TIM_CounterMode_Up;       // 设置计数方式:Up/Down
    
    /* 3. 调用库函数初始化定时器 */
    TIM_TimeBaseInit( TIMx, &gTIMX_TimeBase_Init );

    /* 4. 配置中断的属性 */
    gTIMx_NVIC_Init.NVIC_IRQChannel                     = TIMx_IRQ;                 // 选择中断
    gTIMx_NVIC_Init.NVIC_IRQChannelSubPriority          = TIMx_NVIC_SUB_PRIORITY;   // 设置中断的子优先级
    gTIMx_NVIC_Init.NVIC_IRQChannelPreemptionPriority   = TIMx_NVIC_PRE_PRIORITY;   // 设置中断的抢占优先级
    gTIMx_NVIC_Init.NVIC_IRQChannelCmd                  = ENABLE;                   // 使能中断
    
    /* 5. 初始化中断 */
    NVIC_Init( &gTIMx_NVIC_Init );
        
    /* 6. 选择定时器的中断触发方式 */
    TIM_ITConfig( TIMx, TIM_IT_Update, ENABLE );    // 选择为更新触发中断,即向上计数到预装载值或者向下技术到0触发中断
    
    /* 7. 使能定时器 */
    TIM_Cmd( TIMx, ENABLE );
}

u32 Test_GetCount(void)
{
    return test_cnt;
}


u32 TimerGetCount(void)
{
    return g_timer_cnt;
}


void TIMx_IRQHandler(void)
{
    if( TIM_GetITStatus(TIMx, TIM_IT_Update) == SET )   // 判断是否是更新触发中断
    {
        test_cnt = !test_cnt;
        g_timer_cnt++;
        TIM_ClearITPendingBit( TIMx, TIM_IT_Update );   // 清除中断
    }
}

timer.h

#define __TIMER_H

#include "stm32f10x_lib.h"

#define SYS_FREQ                (72000000)  // 系统频率

#define TIMx                    TIM3        // 目标定时器
#define TIMx_PERIOD             (100-1)       // 定时器的周期,单位:us
#define TIMx_PRE_LOAD_VALUE     (1024-1)    // 定时器的计数预装载值,范围:0~65535
#define TIMx_PRESCALER          (SYS_FREQ/1000000*TIMx_PERIOD/TIMx_PRE_LOAD_VALUE)           // 定时器预分频系数,范围:0~65535
#define TIMx_DIV                (TIM_CKD_DIV1)
#define TIMx_Clk_Enable()       RCC_APB1PeriphClockCmd( RCC_APB1Periph_TIM3, ENABLE )   // 目标定时器的时钟使能

#define TIMx_IRQ                TIM3_IRQChannel     // 目标中断
#define TIMx_NVIC_PRE_PRIORITY  (0)             // 中断的抢占优先级等级
#define TIMx_NVIC_SUB_PRIORITY  (1)             // 中断的子优先级等级

#define TIMx_IRQHandler         TIM3_IRQHandler

extern void TimerInit(void);
extern u32 Test_GetCount(void);

#endif /* __TIMER_H */

gTIMX_TimeBase_Init.TIM_Prescaler= TIMx_PRESCALER=(SYS_FREQ/1000000*TIMx_PERIOD/TIMx_PRE_LOAD_VALUE)

=(72000000/1000000*99/1023) = 7

中断时间 = ((1023 + 1) * (7 + 1)) / 72000000 = 0.1ms

extern unsigned int TimerGetCount(void); //获取定时器中断的计数值,这里0.1ms进一次中断计数

#define portGET_RUN_TIME_COUNTER_VALUE TimerGetCount

#define configUSE_TRACE_FACILITY 1

#define configUSE_STATS_FORMATTING_FUNCTIONS 1

portGET_RUN_TIME_COUNTER_VALUE《=

uxTaskGetSystemState《=

void vTaskList( char * pcWriteBuffer )

最终通过vTaskList 将计数值 保持到pcWriteBuffer

在task1任务中,将vTaskList(pcWriteBuffer); 中的字符串打印出来(运行时间)

void Task1Function(void * param)
{
    volatile int i = 0;

    //xTimerStart(xMyTimerHandle, 0);
    
    while (1)
    {
        //printf("Task1Function ...\r\n");
        vTaskList(pcWriteBuffer);
        vTaskGetRunTimeStats(pcWriteBuffer);
        printf(pcWriteBuffer);
        vTaskDelay(5000);
    }
}

对于:vTaskGetRunTimeStats

vTaskGetRunTimeStats=》

打印运行时间占比

新代码使用步骤

1,添加定时器的代码

timer.c

timer.h

2,在FreeRTOSConfig.h添加宏定义,及声明函数
extern void TimerInit(void);
extern unsigned int TimerGetCount(void);

#define configGENERATE_RUN_TIME_STATS 1
#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS TimerInit
#define portGET_RUN_TIME_COUNTER_VALUE TimerGetCount
#define configUSE_TRACE_FACILITY    1
#define configUSE_STATS_FORMATTING_FUNCTIONS  1
3,在task中添加测试代码
char pcWriteBuffer[200];

void Task1Function(void * param)
{
    volatile int i = 0;
    while (1)
    {
        //vTaskList(pcWriteBuffer);
        vTaskGetRunTimeStats(pcWriteBuffer);
        printf(pcWriteBuffer);
        vTaskDelay(100);
    }
}

void Task1Function(void * param)
{
    volatile int i = 0;
    char pcWriteBuffer[200] = {0};


    //xTimerStart(xMyTimerHandle, 0);
    
    while (1)
    {
        #if 1
        vTaskList(pcWriteBuffer);
        //vTaskGetRunTimeStats(pcWriteBuffer);
        printf(pcWriteBuffer);
        vTaskDelay(100);
        
        #endif
    }
}

  • 10
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值