HAL库的FreeRTOS的任务时间和历史最小剩余堆栈获取

    由于本人在Stm32cubemx中配置FreeRTOS时未发现有开启任务时间获取函数的选项,在生成的代码中无法使用任务时间获取函数,因此决定参考网上的相关文章记录一下如何在HAL库生成的代码中使用任务时间获取函数vTaskGetRunTimeStats();

  为了得到任务的运行时间,我们需要额外提供一个比系统时钟中断更加精确地时基,一般是系统时钟的10-100倍。一般系统时钟Systick中断为1ms,那么这个新的时基应该在10us - 100us。在单片机中,利用定时器中断可以很容易提供一个固定周期的时基,因此我们需要配置一个定时器产生时钟脉冲(这里我们配置周期为50us)。这里我们选择定时器2,中断优先级为1,大于FreeRTOS的管辖范围,配置如下:

我们可以查到f103的定时器2是挂载在APB1上,频率为72M,我们再配置为72分频+50自动重载值,则每50us进入一次定时器2中断;

然后将定时器2的回调函数设置为:

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
  /* USER CODE BEGIN Callback 0 */

  /* USER CODE END Callback 0 */
  if (htim->Instance == TIM1) {
    HAL_IncTick();
  }
  /* USER CODE BEGIN Callback 1 */
	
	if(htim->Instance == TIM2)
		{
			FreeRTOSRunTimeTicks++;	   //这个变量在tim.c中定义并设置为外部声明
		}
	
  /* USER CODE END Callback 1 */
}

为了能够使用任务时间获取函数vTaskGetRunTimeStats()我们还需要在FreeRTOS.h中配置相关的宏,得满足下面这三个条件才可以。

 于是我们将相应的宏定义为1,再之后还需要在FreeRTOS.h中define两个函数portCONFIGURE_TIMER_FOR_RUN_TIME_STATS()和portGET_RUN_TIME_COUNTER_VALUE(),如下:

上图的FreeRTOSRunTimeTicks和ConfigureTimerForRunTimeStats()为:

volatile unsigned long long FreeRTOSRunTimeTicks = 0;

void ConfigureTimerForRunTimeStats(void)
{
	MX_TIM2_Init();
  HAL_TIM_Base_Start_IT(&htim2);
  FreeRTOSRunTimeTicks = 0;
}

这样我们的任务时间获取函数就配置好了,总结一下就是首先设置一个比Systick中断周期小10-100倍的新的定时器时基,这个定时器可以为单片机的任何一个可用的定时器外设,中断优先级设置高一些,比FreeRTOS管辖范围大即可(即0-4之间)。然后再设置相应的宏为1以及定义两个函数,那两个函数的作用分别为初始化定时器时基和传递定时器中断中累加的值。最后我们就使用任务时间获取函数vTaskGetRunTimeStats()即可。使用方法如下:

char Task_buff[500];
/* USER CODE END Header_StartTask03 */
void StartTask03(void *argument)
{
  /* USER CODE BEGIN StartTask03 */
  /* Infinite loop */
	uint8_t key = 0;
  for(;;)
  {
		key = KEY_Scan(0);    //保存返回值,方便后面判断
		if(key == KEY0_PRES)
		{
			vTaskGetRunTimeStats(Task_buff);
			myprintf("\n**********任务运行时间打印**********\n");
			myprintf("%s\r\n",Task_buff);

	        vTaskList(Task_buff);
            myprintf("任务名      任务状态   优先级   历史最小剩余栈   任务序号\r\n");
            myprintf("\r\n%s\r\n", Task_buff);
			myprintf("任务状态:   r-运行  R-就绪  B-阻塞  S-挂起  D-删除\n");
		}
    osDelay(10);
  }
  /* USER CODE END StartTask03 */
}

这里我们定义一个字符型的数组Task_buff用来存放人物事件函数返回的任务时间占用表和任务历史最小剩余堆栈等信息,然后按下按键调用该函数,并将返回的时间表打印出来即可。这里我们配置了三个任务,任务一和任务二都是翻转LED灯并打印一句话。打印结果为:

打印的结果中数字的单位为定时器时基,这里是50us。表示该任务一共运行了多久和该任务占总时间的百分比。历史剩余最小堆栈的单位为字。

/********************************                                               ***********************************/

补:关于配置宏,可以再cubemx中对任务时间获取函数的两个宏进行配置,同时cubemx会自动在freertos.c中生成两个需要我们定义的函数。这样我们只需要配置一个定时器,写定时器回调函数,配置下面两个宏,写两个函数就可以使用vTaskGetRunTimeStats()了,如下:

参考文章:【STM32のHAL库开发】时钟树上的APB/AHB总线对应外设_apb1和apb2挂载外设有哪些-CSDN博客FreeRTOS-任务运行时间统计_configgenerate_run_time_stats-CSDN博客

freertos的可视化追踪和运行时间统计功能_freertos运行过程可视化-CSDN博客

  • 26
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
如果你想获取一段时间内每个任务的CPU占用率,可以使用FreeRTOS提供的`uxTaskGetSystemState()`函数。这个函数会返回一个包含系统中所有任务状态信息的结构体,其中就包括每个任务的CPU占用率。你可以定期调用这个函数来获取一段时间内的任务状态信息,然后根据任务的CPU占用率来分析任务的运行情况。 具体来说,`uxTaskGetSystemState()`函数会返回一个包含以下信息的结构体: ```c typedef struct xTASK_STATUS { TaskHandle_t xHandle; /* 任务句柄 */ const char *pcTaskName; /* 任务名称 */ UBaseType_t uxCurrentPriority; /* 当前优先级 */ UBaseType_t uxBasePriority; /* 基本优先级 */ eTaskState eCurrentState; /* 当前状态 */ uint32_t ulRunTimeCounter; /* 运行时间计数器 */ uint32_t ulStackHighWaterMark; /* 堆栈高水位线 */ } TaskStatus_t; typedef struct xTASK_STATUS_INFO { TaskStatus_t *pxTaskStatusArray; /* 任务状态数组 */ UBaseType_t uxCurrentNumberOfTasks; /* 当前任务数量 */ UBaseType_t uxTaskStatusArraySize; /* 任务状态数组大小 */ uint32_t ulTotalRunTime; /* 系统总计运行时间 */ } TaskStatusArray_t; ``` 其中,`pxTaskStatusArray`是一个指向任务状态数组的指针,可以通过这个指针来获取每个任务的状态信息,包括任务的名称、优先级、状态、运行时间计数器等。`uxCurrentNumberOfTasks`是当前系统中任务的数量,`uxTaskStatusArraySize`是任务状态数组的大小,`ulTotalRunTime`是系统的总计运行时间。 你可以定期调用`uxTaskGetSystemState()`函数,然后遍历任务状态数组来获取每个任务在一段时间内的CPU占用率。具体来说,你可以在两次调用`uxTaskGetSystemState()`函数之间计算每个任务的运行时间差,然后根据总计运行时间和差值来计算每个任务的CPU占用率。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值