使用FreeRTOS进行性能和运行时分析

摘要:
在MCUonEclipse网站上,我看到了2月25日埃里希·斯蒂格的博客文章,一篇关于使用FreeRTOS进行性能和操作分析的文章。我认为这很有启发性,因此我翻译了它以供参考。当切换每个任务时,FreeRTOS会记录任务经过的时间。FreeRTOS内部的计数器值为32位,因此不适合长时间测量。在本例中,使用FreeRTOSConfig。

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

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

 使用FreeRTOS进行性能和运行时分析第1张

Eclipse中的FreeRTOS运行时信息

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

如何获得这样的信息?

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

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

 使用FreeRTOS进行性能和运行时分析第2张

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进行性能和运行时分析第3张

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

计数器

如上所述: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进行性能和运行时分析第4张

FreeRTOS的处理器专家计时器

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

 使用FreeRTOS进行性能和运行时分析第5张

性能计数器

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

/*

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

**     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中对应的设置如下:

 使用FreeRTOS进行性能和运行时分析第6张

使用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进行性能和运行时分析第7张

免责声明:文章转载自《使用FreeRTOS进行性能和运行时分析》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇使用 Vue 开发 scrollbar 滚动条组件MySQL 连接查询下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

c#数字图像处理(二)彩色图像灰度化,灰度图像二值化

为加快处理速度,在图像处理算法中,往往需要把彩色图像转换为灰度图像,在灰度图像上得到验证的算法,很容易移植到彩色图像上。24位彩色图像每个像素用3个字节表示,每个字节对应着R、G、B分量的亮度(红、绿、蓝)。当R、G、B分量值不同时,表现为彩色图像;当R、G、B分量值相同时,表现为灰度图像,该值就是我们所求的一般来说,转换公式有3种。第一种转换公式为: G...

FreeRTOS官方翻译文档——第二章 队列管理

2.1 概览基于 FreeRTOS 的应用程序由一组独立的任务构成——每个任务都是具有独立权限的小程序。这些独立的任务之间很可能会通过相互通信以提供有用的系统功能。FreeRTOS 中所有的通信与同步机制都是基于队列实现的。 2.2队列的特性数据存储队列可以保存有限个具有确定长度的数据单元。队列可以保存的最大单元数目被称为队列的“深度”。在队列创建时需要设...

FreeRTOS 消息队列

以下基础内容转载自安富莱电子: http://forum.armfly.com/forum.php 本章节为大家讲解 FreeRTOS 的一个重要的通信机制----消息队列,初学者要熟练掌握,因为消息队列在实际项目中应用较多。 消息队列的概念及其作用消息队列就是通过 RTOS 内核提供的服务,任务或中断服务子程序可以将一个消息(注意,FreeRTOS消息队...

countdown(倒计时)具体需求分析(NABCD)

N(Need,需求) 我们了解到一些记忆力不好或者是没有固定目标激励的用户的痛苦,他们需要有一个人在他们忙的不可开交焦头烂额的时候提醒他们接下来要做的事,或者是一些有重大考试的用户提醒,给他们一些压力和固定目标,但是现有的方案并没有很好地解决这些需求,我们这款计时器是为了让他们记住一些重要的场合时间以及目标而设计。 A(Approach,做法) 我们这款计...

lwip TCP client 客户端 & FreeRTOS

static void tcpecho_thread(void *arg) { ip_addr_t serverIpAddr; struct netbuf *buf; void *data; u16_t len; err_t err; struct netconn *conn; IP4_ADDR(&serverIpA...

System.Threading.Timer类的TimerCallback 委托(转载)

System.Threading.Timer 是一个使用回调方法的计时器,而且由线程池线程服务,简单且对资源要求不高。   只要在使用 Timer,就必须保留对它的引用。对于任何托管对象,如果没有对 Timer 的引用,计时器会被垃圾回收。即使 Timer 仍处在活动状态,也会被回收。当不再需要计时器时,请使用 Dispose 方法释放计时器持有的资源。...