0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

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

CHANBAEK 来源:实在太懒于是不想取名 作者: 电路小白 2023-11-07 11:43 次阅读

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

图片

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

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

图片

文档指出实现运行时间功能需要配置外设定时器,即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("%s\r\n",informationbuff);//打印运行时间
    }
    vTaskDelay(10);
  }
}

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

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

FreeRTOS\FreeRTOS.axf: Error: L6218E: Undefined symbol vTaskGetRunTimeStats (referred from main.o).
F:\Code\STM32Code\STM32F407_FreeRtos\FreeRTOS\FreeRTOS\Source\tasks.c(4539) :     void vTaskGetRunTimeStats( char * pcWriteBuffer )
F:\Code\STM32Code\STM32F407_FreeRtos\FreeRTOS\FreeRTOS\Source\tasks.c(4552) :          * vTaskGetRunTimeStats() calls uxTaskGetSystemState(), then formats part
F:\Code\STM32Code\STM32F407_FreeRtos\FreeRTOS\FreeRTOS\Source\tasks.c(4557) :          * vTaskGetRunTimeStats() has a dependency on the sprintf() C library
F:\Code\STM32Code\STM32F407_FreeRtos\FreeRTOS\FreeRTOS\Source\tasks.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时间的返回值。

图片

#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;

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

图片

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

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

图片

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

FreeRTOSRunTime也可以定义在这里。

图片

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

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

图片

/* USER CODE BEGIN 4 */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
  if(htim->Instance == htim1.Instance)
  {
    FreeRTOSRunTime++;
  }
}
/* USER CODE END 4 */

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

图片

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

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • cpu
    cpu
    +关注

    关注

    68

    文章

    10443

    浏览量

    206565
  • WINDOWS
    +关注

    关注

    3

    文章

    3440

    浏览量

    87144
  • 定时器
    +关注

    关注

    23

    文章

    3147

    浏览量

    112038
  • FreeRTOS
    +关注

    关注

    12

    文章

    473

    浏览量

    61348
  • STM32F407
    +关注

    关注

    15

    文章

    187

    浏览量

    28973
收藏 人收藏

    评论

    相关推荐

    基于STM32F407FreeRTOS学习笔记(1)

    其实从很早之前就想学实时操作系统(RTOS)了,但是一直没有时间去学,以前使用STM32单片机一直停留在逻辑开发以及前后台系统,而真正被广泛使用的则是RTOS。
    的头像 发表于 11-07 11:37 414次阅读
    基于<b class='flag-5'>STM32F407</b>的<b class='flag-5'>FreeRTOS</b><b class='flag-5'>学习</b><b class='flag-5'>笔记</b>(1)

    基于STM32F407FreeRTOS学习笔记(2)

    上一期配置完FreeRTOS的环境后,这一期记录自己关于任务创建的学习过程。
    的头像 发表于 11-07 11:39 387次阅读
    基于<b class='flag-5'>STM32F407</b>的<b class='flag-5'>FreeRTOS</b><b class='flag-5'>学习</b><b class='flag-5'>笔记</b>(2)

    基于STM32F407FreeRTOS学习笔记(3)

    上一期学习了任务的创建和删除,这一期学习任务的挂起与恢复。
    的头像 发表于 11-07 11:41 355次阅读
    基于<b class='flag-5'>STM32F407</b>的<b class='flag-5'>FreeRTOS</b><b class='flag-5'>学习</b><b class='flag-5'>笔记</b>(3)

    基于STM32F407FreeRTOS学习笔记(5)

    在数据结构中有一种很重要的数据结构叫做队列,其特点是数据先进先出。在FreeRTOS中也有一类队列,我们利用这类队列在FreeRTOS中实现任务与任务间的消息传递,所以也可以称之为消息队列。
    的头像 发表于 11-07 11:43 377次阅读
    基于<b class='flag-5'>STM32F407</b>的<b class='flag-5'>FreeRTOS</b><b class='flag-5'>学习</b><b class='flag-5'>笔记</b>(5)

    基于STM32F407FreeRTOS学习笔记(6)

    信号量(Semaphore)也被称为信号灯。有时被称为信号灯,是在多线程环境下使用的一种设施,是可以用来保证两个或多个关键代码段不被并发调用。在进入一个关键代码段之前,线程必须获取一个信号量;一旦该关键代码段完成了,那么该线程必须释放信号量。其它想进入该关键代码段的线程必须等待直到第一个线程释放信号量(来自百度百科)
    的头像 发表于 11-08 11:00 365次阅读
    基于<b class='flag-5'>STM32F407</b>的<b class='flag-5'>FreeRTOS</b><b class='flag-5'>学习</b><b class='flag-5'>笔记</b>(6)

    基于STM32F407FreeRTOS学习笔记(7)

    本期在二进制信号量的基础上介绍计数信号量
    的头像 发表于 11-08 11:04 292次阅读
    基于<b class='flag-5'>STM32F407</b>的<b class='flag-5'>FreeRTOS</b><b class='flag-5'>学习</b><b class='flag-5'>笔记</b>(7)

    基于STM32F407FreeRTOS学习笔记(8)

    前面几期我们介绍过队列、二进制信号量以及计数信号量。但是在使用二进制信号量的时候会有一种优先级反转问题的出现,简而言之就是低优先级任务因为无法及时释放信号量而导致等待信号量发生的高优先级任务迟迟无法进行。
    的头像 发表于 11-08 11:07 353次阅读
    基于<b class='flag-5'>STM32F407</b>的<b class='flag-5'>FreeRTOS</b><b class='flag-5'>学习</b><b class='flag-5'>笔记</b>(8)

    基于STM32F407FreeRTOS学习笔记(9)

    在嵌入式编程中,定时器是一个非常重要且强大的功能,用来帮我们定时性的调用中断服务函数来帮助我们处理程序。定时器通常是用硬件来实现的,例如STM32F407就有8个硬件定时器。
    的头像 发表于 11-08 11:08 416次阅读
    基于<b class='flag-5'>STM32F407</b>的<b class='flag-5'>FreeRTOS</b><b class='flag-5'>学习</b><b class='flag-5'>笔记</b>(9)

    基于STM32F407FreeRTOS学习笔记(10)

    在介绍二进制信号量时曾经讲过,二进制信号量可以代替我们裸机开发中的标志位来使用。在裸机开发中我们使用标志位来表示某个事件是否发生,并且其他程序利用标记位的状态来判断程序是否可以继续进行。但是这种大量使用标记位的情况会导致代码的逻辑异常的复杂。
    的头像 发表于 11-08 11:10 333次阅读
    基于<b class='flag-5'>STM32F407</b>的<b class='flag-5'>FreeRTOS</b><b class='flag-5'>学习</b><b class='flag-5'>笔记</b>(10)

    基于STM32F407FreeRTOS学习笔记(11)

    在前面的学习中例如信号量、队列中经常会出现提示:在许多情况下,“任务通知”可以提供二进制信号量的轻量级替代方案。
    的头像 发表于 11-13 17:23 465次阅读
    基于<b class='flag-5'>STM32F407</b>的<b class='flag-5'>FreeRTOS</b><b class='flag-5'>学习</b><b class='flag-5'>笔记</b>(11)

    基于STM32F407FreeRTOS学习笔记(12)

    在上一期内容中我们简单的介绍了任务通知的几个函数以及简单的使用了任务通知来实现两个信号之间的通信。
    的头像 发表于 11-13 17:27 434次阅读
    基于<b class='flag-5'>STM32F407</b>的<b class='flag-5'>FreeRTOS</b><b class='flag-5'>学习</b><b class='flag-5'>笔记</b>(12)

    STM32F407时钟配置学习

    STM32F407时钟配置学习
    发表于 08-04 07:14

    如何使用STM32F407去移植FreeRTOS

    如何使用STM32F407去移植FreeRTOS呢?有哪些操作步骤?
    发表于 10-21 09:45

    STM32F407 FreeRTOS开发指南

    参考资料:正点原子《littleVGL 开发指南》正点原子《STM32F407 FreeRTOS 开发指南》硬件平台:stm32f407开发板(或最小系统)、4.3寸TFTLCD以正点原子的例程为
    发表于 01-05 06:55

    STM32F407 FreeRTOS开发手册 V1.1

    STM32F407 FreeRTOS开发手册_V1.1PDF文件下载。
    发表于 07-31 11:16 44次下载