由于本人在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博客