基于STM32F407的FreeRTOS学习笔记(4)

发布时间:2024-03-21  

CPU工作的时候,各个任务运行会占用CPU的资源,在Windows系统中我们可以通过任务管理器来看各任务(进程)占用系统资源的情况。

c5eed059a3f26dbbb0de868bf5fbe22a_wKgaomVJsiWAN448AAGaH1evFwY604.jpg

那么,FreeRTOS怎么实现这个功能呢?


我们翻阅FreeRTOS官网,查询API文档,在内核控制函数部分找到了相关的函数。

bf235b9809b7bc4679b6b114bb1e5859_wKgZomVJsiaAEOLlAASjvNCEefQ603.jpg

文档指出实现运行时间功能需要配置外设定时器,即32板载定时器,计时器频率应为滴答计时器(1ms)的至少10倍。


传入参数为pcWriteBUffer,其实是一个char类型的数组用以存储相关信息。


我们现在工程上调用这个函数。


char informationbuff[400];

void Get_info(void * pvParameters)

{


  //vTaskGetRunTimeStats(informationbuff);

  while(1)

  {

    if(KEY_Scan(0)==1)//按下按键1

    {

      memset(informationbuff,0,400);//清空数组内容

      vTaskGetRunTimeStats(informationbuff);//获得运行时间

      printf("%srn",informationbuff);//打印运行时间

    }

    vTaskDelay(10);

  }

}

上述任务的作用为检测按键,如果按键按下即尝试获得运行状态,并打印运行状态。


出现了如下错误,显示我们未定义该函数,我们利用Ctrl+F全局寻找这个函数定义在哪里。


FreeRTOSFreeRTOS.axf: Error: L6218E: Undefined symbol vTaskGetRunTimeStats (referred from main.o).

F:CodeSTM32CodeSTM32F407_FreeRtosFreeRTOSFreeRTOSSourcetasks.c(4539) :     void vTaskGetRunTimeStats( char * pcWriteBuffer )

F:CodeSTM32CodeSTM32F407_FreeRtosFreeRTOSFreeRTOSSourcetasks.c(4552) :          * vTaskGetRunTimeStats() calls uxTaskGetSystemState(), then formats part

F:CodeSTM32CodeSTM32F407_FreeRtosFreeRTOSFreeRTOSSourcetasks.c(4557) :          * vTaskGetRunTimeStats() has a dependency on the sprintf() C library

F:CodeSTM32CodeSTM32F407_FreeRtosFreeRTOSFreeRTOSSourcetasks.c(4567) :          * through a call to vTaskGetRunTimeStats().

第一行内容,即为函数定义的位置,我们跳转过去查看其情况。


#if ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) && ( configUSE_TRACE_FACILITY == 1 ) )



    void vTaskGetRunTimeStats( char * pcWriteBuffer )

{

        TaskStatus_t * pxTaskStatusArray;

        UBaseType_t uxArraySize, x;

        configRUN_TIME_COUNTER_TYPE ulTotalTime, ulStatsAsPercentage;



省略后续内容(防止说水字数)


我们看到了函数模型以及相关注释,从头中我们可以看出需要相关的宏定义,分别是configGENERATE_RUN_TIME_STATS、configUSE_STATS_FORMATTING_FUNCTIONS、configUSE_TRACE_FACILITY。


我们在FreeRTOSconfig.h文件(头文件都行,方便管理)中添加使能这三个宏。

图片

再次运行,依旧报错,从报错内容来看,提醒我们如果将configGENERATE_RUN_TIME_STATS使能的话,我们也必须定义portCONFIGURE_TIMER_FOR_RUN_TIME_STATS这个启动函数,以及后面的一条报错,我们必须定义portGET_RUN_TIME_COUNTER_VALUE时间的返回值。

3b57dfef8e1f13d5b90d4c8c60f0c844_wKgaomVJsiaAbxHDAADtuMrYpG4898.jpg

#ifndef portCONFIGURE_TIMER_FOR_RUN_TIME_STATS

  (import)    #error If configGENERATE_RUN_TIME_STATS is defined then portCONFIGURE_TIMER_FOR_RUN_TIME_STATS must also be defined.  portCONFIGURE_TIMER_FOR_RUN_TIME_STATS should call a port layer function to setup a peripheral timer/counter that can then be used as the run time counter time base.

    #endif /* portCONFIGURE_TIMER_FOR_RUN_TIME_STATS */



    #ifndef portGET_RUN_TIME_COUNTER_VALUE

        #ifndef portALT_GET_RUN_TIME_COUNTER_VALUE

    (import)    #error If configGENERATE_RUN_TIME_STATS is defined then either portGET_RUN_TIME_COUNTER_VALUE or portALT_GET_RUN_TIME_COUNTER_VALUE must also be defined.  See the examples provided and the FreeRTOS web site for more information.

        #endif /* portALT_GET_RUN_TIME_COUNTER_VALUE */

    #endif /* portGET_RUN_TIME_COUNTER_VALUE *

启动函数即为外部定时器启动函数,返回值则是一个数用以计算时间。


#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS()  configTIM_START()//定时器1提供时间统计的时基,频率为10K,即周期为100us           

#define portGET_RUN_TIME_COUNTER_VALUE()   FreeRTOSRunTime//时基

extern volatile unsigned long long FreeRTOSRunTime;

我们定义这两个宏,本来这个括号是没加上去的,后来发现其调用的时候是代括号的,所以定义宏的时候不带括号就会出错

3b57dfef8e1f13d5b90d4c8c60f0c844_wKgaomVJsiaAbxHDAADtuMrYpG4898.jpg

此外我们定义了long long 类型的变量用以存储我们的时间,加上extern表示这个变量的实际定义并不在头文件中,之所以加上volatile是因为我们的变量会在不同的文件以及中断中被修改(这种修改属于意外修改),加上volatile标志给系统提前吱会一声。


之后,我们去CUBEMX启动我们的定时器。

8d2dacee162777446ba33f22dc67d00b_wKgZomVJsiaABNxvAAR4M1dG90M069.jpg

定时器我们选择定时器1,时钟源选择内部时钟,分频系数由于我们的单片机主频是168MHZ,因此我们选择168分频,这样子定时器频率即为1MHZ,溢出值我们选择为50,通过这样的设置我们定时器的频率就是20KHZ,是滴答定时器时钟的20倍。


FreeRTOSRunTime也可以定义在这里。

dcbfe24eff4795af5b0950068b17d41f_wKgaomVJsiaAPeibAADOrePiUzY598.jpg

之后我们将刚才宏定义的启动函数进行定义,内容则是重置计数器并启动定时器。


完成这步之后,我们还需要在主函数中启用定时器1 的中断并且编写相应的中断服务函数,其内容为FreeRTOSRunTime递增。


0ca3d2388d58331716d379b14b6d1a5c_wKgaomVJsiaALgqjAAGDXtqKUYk326.jpg

/* USER CODE BEGIN 4 */

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)

{

  if(htim->Instance == htim1.Instance)

  {

    FreeRTOSRunTime++;

  }

}

/* USER CODE END 4 */

之后我们运行程序观察串口的输出。

3fd0c145f8ae9466887fc2a138e3aee4_wKgZomVJsiaAQ_d2AAIV21XUNFU219.jpg


这样子我们就可以打印出各个程序运行时间以及占用系统资源的占比了。


文章来源于:电子工程世界    原文链接
本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。

我们与500+贴片厂合作,完美满足客户的定制需求。为品牌提供定制化的推广方案、专属产品特色页,多渠道推广,SEM/SEO精准营销以及与公众号的联合推广...详细>>

利用葫芦芯平台的卓越技术服务和新产品推广能力,原厂代理能轻松打入消费物联网(IOT)、信息与通信(ICT)、汽车及新能源汽车、工业自动化及工业物联网、装备及功率电子...详细>>

充分利用其强大的电子元器件采购流量,创新性地为这些物料提供了一个全新的窗口。我们的高效数字营销技术,不仅可以助你轻松识别与连接到需求方,更能够极大地提高“闲置物料”的处理能力,通过葫芦芯平台...详细>>

我们的目标很明确:构建一个全方位的半导体产业生态系统。成为一家全球领先的半导体互联网生态公司。目前,我们已成功打造了智能汽车、智能家居、大健康医疗、机器人和材料等五大生态领域。更为重要的是...详细>>

我们深知加工与定制类服务商的价值和重要性,因此,我们倾力为您提供最顶尖的营销资源。在我们的平台上,您可以直接接触到100万的研发工程师和采购工程师,以及10万的活跃客户群体...详细>>

凭借我们强大的专业流量和尖端的互联网数字营销技术,我们承诺为原厂提供免费的产品资料推广服务。无论是最新的资讯、技术动态还是创新产品,都可以通过我们的平台迅速传达给目标客户...详细>>

我们不止于将线索转化为潜在客户。葫芦芯平台致力于形成业务闭环,从引流、宣传到最终销售,全程跟进,确保每一个potential lead都得到妥善处理,从而大幅提高转化率。不仅如此...详细>>