在MCU on Eclipse网站上看到Erich Styger在2月25日发的博文,一篇关于使用FreeRTOS进行性能和运行分析的文章,本人觉得很有启发,特将其翻译过来以备参考。当然限于个人水平,有描述不当之处恳请指正。原文网址:https://mcuoneclipse.com/2018/02/25/performance-and-runtime-analysis-with-freertos/#more-23229

FreeRTOS操作系统的优点之一是它提供了免费的性能分析:它向我们展示在每个任务中花费了多少时间。最好的是:它在Eclipse中也以图形的方式显示了相应内容:

Eclipse中的FreeRTOS运行时信息

在上面的输出中,我看到我的应用程序现在是97.5%的空闲,这是一件好事,符合我的期望,因为这个机器人正等待着在轨道上运行。

如何获得这样的信息?

在Eclipse中的图形视图中需要一个Eclipse插件(请参阅Eclipse中更好的FreeRTOS调试)。该插件已经预先安装在NXP MCUXpresso IDE中。

另一种查看该信息的方法是使用“tasklist”命令,该命令将输出发送到控制台(Segger RTT, UART, USB或类似的):

Tasklist命令

此命令可用于GitHub上的McuOnEclipse FreeRTOS。

如何工作的?

在每个任务切换时,FreeRTOS记录会切换到该任务所传递的时间(或消耗的时间)。为此,它在任务信息结构中使用了一个32位计数器。这实际上是在“运行时”列下的“任务列表”命令显示的计数器。然后根据总运行时的总数来计算百分比。

FreeRTOS内部的计数器值为32位,所以它不太适合长时间的测量。

为了修正这些数字,在FreeRTOSConfig.h中必须将两个FreeRTOS配置定义为1。

#define configUSE_TRACE_FACILITY 1 /* 1: 包括额外的结构成员和功能,以协助执行可视化和跟踪,0: 没有运行时状态跟踪*/

#define configGENERATE_RUN_TIME_STATS 1 /* 1: 生成运行时统计; 0: 没有运行时统计 */

如果使用处理器专家,上述两个配置项有一个图形化设置:

用于性能分析的处理器专家设置

计数器

如上所述:FreeRTOS记录了每个任务所花费的时间。但这实际上不是实时的,如果configGENERATE_RUN_TIME_STATS打开,它只是某种计时器的计数器值。在这种情况下,FreeRTOSConfig。h需要配置有两个应用程序功能配置的宏:

#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() AppConfigureTimerForRuntimeStats()

#define portGET_RUN_TIME_COUNTER_VALUE()         AppGetRuntimeCounterValueFromISR()

第一个是在RTOS启动时配置timer,第二个是返回实际的计时器计数器值。

一般的经验法则是,用于测量任务的计时器应该比实际的滴答计数器快10倍。

处理器专家的用户又有了一个优势:他们可以在处理器专家设置中轻松地配置这样的计时器,并且一切都得到了处理:

FreeRTOS的处理器专家计时器

下面是一个计时器的设置,它的运行速度是1 kHz RTOS计时器的10倍。

性能计数器

下面是产生的定时器代码:

/*

** ===================================================================

**     Method      :  FRTOS1_OnCounterRestart (component FreeRTOS)

**

**     Description :

**         This method is internal. It is used by Processor Expert only.

** ===================================================================

*/

void RTOSCNTRLDD1_OnCounterRestart(LDD_TUserData *UserDataPtr __attribute__((unused)))

{

FRTOS1_RunTimeCounter++; /* increment runtime counter */

}

/*

** ===================================================================

**     Method      :  FRTOS1_AppConfigureTimerForRuntimeStats (component FreeRTOS)

**     Description :

**         Configures the timer for generating runtime statistics

**     Parameters  : None

**     Returns     : Nothing

** ===================================================================

*/

#if configGENERATE_RUN_TIME_STATS

void FRTOS1_AppConfigureTimerForRuntimeStats(void)

{

#if configGENERATE_RUN_TIME_STATS_USE_TICKS

/* nothing needed, the RTOS will initialize the tick counter */

#else

FRTOS1_RunTimeCounter = 0;

FRTOS1_RunTimeCounterHandle = RTOSCNTRLDD1_Init(NULL);

(void)RTOSCNTRLDD1_Enable(FRTOS1_RunTimeCounterHandle);

#endif

}

#endif /* configGENERATE_RUN_TIME_STATS */

/*

** ===================================================================

**     Method      :  FRTOS1_AppGetRuntimeCounterValueFromISR (component FreeRTOS)

**     Description :

**         returns the current runtime counter. Function can be called

**         from an interrupt service routine.

**     Parameters  : None

**     Returns     :

**         ---             - runtime counter value

** ===================================================================

*/

uint32_t FRTOS1_AppGetRuntimeCounterValueFromISR(void)

{

#if configGENERATE_RUN_TIME_STATS

#if configGENERATE_RUN_TIME_STATS_USE_TICKS

return xTaskGetTickCountFromISR(); /* using RTOS tick counter */

#else /* using timer counter */

return FRTOS1_RunTimeCounter;

#endif

#else

return 0; /* dummy value */

#endif

}

中断服务例程计数一个计时器计数器,该计数器用于度量在任务中花费的时间。

如果中断是从性能角度考虑的问题,并且不需要很高的精度,那么处理器专家端口就有一个很好的特性:它不使用专用计时器,而是重新使用RTOS的滴答计时器。为此,有一个额外的设置来配置这个:

#define configGENERATE_RUN_TIME_STATS_USE_TICKS 0 /* 1: 使用RTOS tick计数器作为运行时计数器。 0: 使用额外的

在UI中对应的设置如下:

使用Tick计数器

有了这些,我们可以做一些基本的测量。但这不适合测量短任务执行时间。说RTOS的计时器是1毫秒,那么运行不到1毫秒的任务将很少被测量。

使用ARM Cortex循环计数器

另一种在ARM Cortex M(例如:Cortex-M4或M7)上测量执行时间的方法是使用ARM Cortex循环计数器。

#include "KIN1.h"

static uint32_t prevCycleCounter, cycleCntCounter = 0;

void AppConfigureTimerForRuntimeStats(void) {

cycleCntCounter = 0;

KIN1_InitCycleCounter();

prevCycleCounter = KIN1_GetCycleCounter();

}

uint32_t AppGetRuntimeCounterValueFromISR(void) {

uint32_t newCntr, diff;

newCntr = KIN1_GetCycleCounter();

diff = newCntr-prevCycleCounter;

prevCycleCounter = newCntr;

cycleCntCounter += diff>>12; /* scale down the counter */

return cycleCntCounter;

}

这种方法测量循环计数器区别两个调用AppGetRuntimeCounterValueFromISR()和基于价值的计数器计数。为了不过快地计算,计数器的值在上面的实现(使用120 MHz ARM的Cortex-M4)上按12位的偏移量缩小。对于运行速度更快或更慢的内核,您可能需要调整该值。

总结

FreeRTOS具有跟踪任务执行时间的内置函数。它是在每个任务描述符中使用一个计数器实现的,因此不需要太多RAM。应用程序必须提供一个计数器,其速度通常比正常情况下要快10倍,以获得一些合理的测量值。但是,即使使用tick计数器本身也会给出一些粗略的性能分析数据。否则,应用程序可以提供一个定期计时器计数器。如果使用臂皮质- m3 /M4/M7,使用手臂皮层循环计数器是另一种选择,因为它不需要任何定时器或中断。

欢迎关注:

使用FreeRTOS进行性能和运行时分析的更多相关文章

  1. Go 程序的性能监控与分析 pprof

    你有没有考虑过,你的goroutines是如何被go的runtime系统调度的?是否尝试理解过为什么在程序中增加了并发,但并没有给它带来更好的性能?go执行跟踪程序可以帮助回答这些疑问,还有其他和其有 ...

  2. [源码解析] PyTorch 流水线并行实现 (3)--切分数据和运行时系统

    [源码解析] PyTorch 流水线并行实现 (3)--切分数据和运行时系统 目录 [源码解析] PyTorch 流水线并行实现 (3)--切分数据和运行时系统 0x00 摘要 0x01 分割小批次 ...

  3. vue.js2.0的独立构建和运行时构建

    转自:https://jingsam.github.io/2016/10/23/standalone-vs-runtime-only-build-in-vuejs2.html?utm_source=t ...

  4. 深入理解OOP(三):多态和继承(动态绑定和运行时多态)

    在前面的文章中,我们介绍了编译期多态.params关键字.实例化.base关键字等.本节我们来关注另外一种多态:运行时多态, 运行时多态也叫迟绑定. 深入理解OOP(一):多态和继承(初期绑定和编译时 ...

  5. 转——Android应用开发性能优化完全分析

    [工匠若水 http://blog.csdn.net/yanbober 转载请注明出处.] 1 背景 其实有点不想写这篇文章的,但是又想写,有些矛盾.不想写的原因是随便上网一搜一堆关于性能的建议,感觉 ...

  6. 如何使用工具进行线上 PHP 性能追踪及分析?

    工作了一两年的 PHPer 大概都多多少少知道一些性能分析的工具,比如 Xdebug.xhprof.New Relic .OneAPM.使用基于 Xdebug 进行 PHP 的性能分析,对于本地开发环 ...

  7. Android 应用开发性能优化完全分析

    1 背景 其实有点不想写这篇文章的,但是又想写,有些矛盾.不想写的原因是随便上网一搜一堆关于性能的建议,感觉大家你一总结.我一总结的都说到了很多优化注意事项,但是看过这些文章后大多数存在一个问题就是只 ...

  8. 【转】Android应用开发性能优化完全分析

    http://blog.csdn.net/yanbober/article/details/48394201 1 背景 其实有点不想写这篇文章的,但是又想写,有些矛盾.不想写的原因是随便上网一搜一堆关 ...

  9. Android应用开发性能优化完全分析

    1 背景 其实有点不想写这篇文章的,但是又想写,有些矛盾.不想写的原因是随便上网一搜一堆关于性能的建议,感觉大家你一总结.我一总结的都说到了很多优化注意事项,但是看过这些文章后大多数存在一个问题就是只 ...

随机推荐

  1. 符号执行-基于python的二进制分析框架angr

    转载:All Right 符号执行概述 在学习这个框架之前首先要知道符号执行.符号执行技术使用符号值代替数字值执行程序,得到的变量的值是由输入变 量的符号值和常量组成的表达式.符号执行技术首先由Kin ...

  2. 嵌入式-迅为iTOP-4418/6818开发板编译Android镜像技术分享

    迅为是基于Ubuntu12.04.2 平台做开发,所有的配置和编译脚本也是基于此平台.如果你对Linux 和Android 开发很熟悉,相信你会根据错误提示逐步找到原因并解决,错误提示一般是选用的平台 ...

  3. linux 截图工具 shutter

    ubuntu 安装shutter sudo apt install shutter libgoo-canvas-perl libgoo-canvas-perl是提供对截图编辑功能,例如,添加画框,文字 ...

  4. python 的基础 学习 11天 作业题

    1.整理函数相关知识点,写博客 2.写函数,检查获取传入列表或元组对象的所有奇数位索引对应的元素,并将其作为新列表返回给调用者. def func1(argv): li = [] for i in r ...

  5. 【译】第六篇 SQL Server安全执行上下文和代码签名

    本篇文章是SQL Server安全系列的第六篇,详细内容请参考原文. SQL Server决定主体是否有必要的执行代码权限的根本途径是其执行上下文规则.这一切都可能复杂一个主体有执行代码的权限,但是却 ...

  6. Leetcode#169. Majority Element(求众数)

    题目描述 给定一个大小为 n 的数组,找到其中的众数.众数是指在数组中出现次数大于 ⌊ n/2 ⌋ 的元素. 你可以假设数组是非空的,并且给定的数组总是存在众数. 示例 1: 输入: [3,2,3] ...

  7. python中的私有变量

    class Test1: def f1(self): self.name ="张三" self.__age = 20 #使用名称变形实现私有变量 print(self.name) ...

  8. retrofit动态代理

    https://blog.csdn.net/dalong3976/article/details/83479816

  9. Serv-U日志文件保存设置【转】

    Serv-U的日志默认是不保存在本地的,但是大多数企业对于文件传输是有审计需求的,所以这里我们可以手动配置Serv-U的日志保存到本地文件. 首先打开“域活动”,选择“设置”,在“记录到文件”处设置日 ...

  10. 拿什么守护你的Node.JS进程: Node出错崩溃了怎么办?

    被吐嘈的NodeJS的异常处理 许多人都有这样一种映像,NodeJS比较快: 但是因为其是单线程,所以它不稳定,有点不安全,不适合处理复杂业务: 它比较适合对并发要求比较高,而且简单的业务场景. 在E ...