在Amazon FreeRTOS V10中使用运行时统计信息

在MCU on Eclipse网站上看到Erich Styger在8月2日发的博文,一篇关于在Amazon FreeRTOS V10中使用运行时统计信息的文章,本人觉得很有启发,特将其翻译过来以备参考。原文网址:https://mcuoneclipse.com/2018/08/02/tutorial-using-runtime-statistics-with-amazon-freertos-v10/

FreeRTOS包含一个很好的功能,可以向我提供有关每个任务在系统上运行的时间的信息:
这里写图片描述
FreeRTOS运行时信息
本教程解释了FreeRTOS运行时统计功能以及如何打开和使用它。
♣软件和工具
在本文中,我使用以下内容:
 MCUXpresso IDE 10.2.1
 FRDM-K64F板
 来自MCUXpresso SDK 2.4.0的Amazon FreeRTOS V10.0.1
但是当然可以使用任何其他工具/ IDE或FreeRTOS版本(FreeRTOS至少应该是9.0.0或更高版本)。
使用以下步骤,还可以使用FreeRTOS任务运行时信息收集来更新现有项目。
♣怎么运行的
FreeRTOS使用用户/应用程序特定的计时器来测量任务执行时间。为此,RTOS中的每个任务描述符都有一个累积计数器,用于添加为该任务花费的计时器滴答。当任务获得CPU时间时,当前计时器滴答计数被记忆,当RTOS切换出该任务时,则记忆当前计时器滴答计数。然后将对应于任务执行时间的增量时间添加到任务执行时间计数器。
我需要配置FreeRTOS,并将以下宏设置为1以执行运行时分析:

#define configGENERATE_RUN_TIME_STATS 1

另外,需要提供以下两个宏:

portCONFIGURE_TIMER_FOR_RUN_TIME_STATS()
portGET_RUN_TIME_COUNTER_VALUE()

RTOS使用它来配置运行时计数器计时器并获取计时器值。
运行时计数器在每个任务描述符中存储为32位值,这意味着对于每个任务,我对系统的RAM要求将增加4个字节:
这里写图片描述
FreeRTOS TCB中的ulRunTimeCounter
假设计数器周期为10 kHz(0.1 ms),这意味着变量将在大约5天后溢出。
此外,RTOS在task.c中维护额外的全局变量:

#if ( configGENERATE_RUN_TIME_STATS == 1 )PRIVILEGED_DATA static uint32_t ulTaskSwitchedInTime = 0UL; /*< Holds the value of a timer/counter the last time a task was switched in. */PRIVILEGED_DATA static uint32_t ulTotalRunTime = 0UL;       /*< Holds the total amount of execution time as defined by the run time counter clock. */
#endif

第一个变量用于记住任务切换的时间,第二个变量是系统的总运行时间。这是在任务切换时发生的事情(内核函数vTaskSwitchContext):

/* Add the amount of time the task has been running to theaccumulated time so far.  The time the task started running wasstored in ulTaskSwitchedInTime.  Note that there is no overflowprotection here so count values are only valid until the timeroverflows.  The guard against negative values is to protectagainst suspect run time stat counter implementations - whichare provided by the application, not the kernel. */
if( ulTotalRunTime > ulTaskSwitchedInTime )
{pxCurrentTCB->ulRunTimeCounter += ( ulTotalRunTime - ulTaskSwitchedInTime );
}
else
{mtCOVERAGE_TEST_MARKER();
}
ulTaskSwitchedInTime = ulTotalRunTime;

通常,周期性定时器中断用于计算执行时间,并且定时器频率应该是嘀嗒中断频率的大约10倍(比如说“Hello”到“奈奎斯特 - 香农”采样定理)。这意味着如果我的滴答中断是1 kHz,我的运行时分析定时器频率应该是10 kHz。
运行时统计信息通常带有两个数字:
 绝对(时间)数字
 百分比
下面是一个文本任务列表,其中包含右侧的运行时信息:
TCB Static Handle Name State Prio Stack Beg Stack End Size Stack Top Unused Runtime
1 no (0) 0x20000450 Shell Running (1,1) 0x20000440 0x20000060 1000 B 0x200001EC ( 600 B) 392 B 0x00000000 ( <1%)
7 no (0) 0x20001E68 IDLE Ready (0,0) 0x20001E58 0x20001CD0 400 B 0x20001DFC ( 96 B) 312 B 0x00007C35 ( 91%)
2 no (0) 0x20000740 Refl Blocked (4,4) 0x20000730 0x20000510 552 B 0x200006BC ( 120 B) 384 B 0x00000C6E ( 9%)
6 no (0) 0x20001C68 Main Blocked (1,1) 0x20001C58 0x20001A08 600 B 0x20001BDC ( 128 B) 356 B 0x00000000 ( <1%)
3 no (0) 0x20001378 Radio Blocked (3,3) 0x20001368 0x20000F88 1000 B 0x200012F4 ( 120 B) 680 B 0x00000001 ( <1%)
4 no (0) 0x20001658 Sumo Blocked (2,2) 0x20001648 0x20001458 504 B 0x200015C4 ( 136 B) 360 B 0x00000000 ( <1%)
5 no (0) 0x20001948 Drive Blocked (3,3) 0x20001938 0x20001748 504 B 0x200018B4 ( 136 B) 264 B 0x00000000 ( <1%)
绝对数字是运行时间计时器滴答数(TCB中的ulRunTimeCounter)以及此计数器相对于总运行时间的百分比(task.c中的ulTotalRunTime)。
对于IDLE任务,它显示了这一点:
TCB Static Handle Name State Prio Stack Beg Stack End Size Stack Top Unused Runtime
7 no (0) 0x20001E68 IDLE Ready (0,0) 0x20001E58 0x20001CD0 400 B 0x20001DFC ( 96 B) 312 B 0x00007C35 ( 91%)
0x7C35是定时器计数器(在本例中使用0.1 ms定时器,因此它意味着IDLE任务运行约3秒(0x7C35 / 10 => 3179 ms)并使用91%的运行时间。
问题可能是:中断花费的时间是多少?答案是RTOS不知道中断,它只知道任务使用了多少运行时间计时器。或者换句话说:FreeRTOS运行时计数器显示的运行时* includes*中断的时间。
♣教程:使用FreeRTOS进行运行时分析
在下一节中,我将展示如何使用FreeRTOS启用运行时分析。基本步骤是:
 创建一个新项目(如果尚未存在)
 更新FreeRTOSConfig.h
 初始化和配置计时器
 添加钩子/回调到应用程序
1、创建项目
创建一个基于你的目标板的项目:
这里写图片描述
项目创建的目标板
确保包含FreeRTOS:
这里写图片描述
项目的FreeRTOS选项
2、添加FreeRTOS任务
接下来添加一个任务,例如:

#include "FreeRTOS.h"
#include "task.h"static void MyTask(void *pvParameters) {for(;;) {vTaskDelay(pdMS_TO_TICKS(100));}
}

在main()内部,创建一个任务并启动调度程序:

/* create task */if (xTaskCreate(MyTask, "MyTask", 500/sizeof(StackType_t), NULL, tskIDLE_PRIORITY+1, NULL) != pdPASS) {for(;;){} /* error */}vTaskStartScheduler(); /* start RTOS */for(;;) {/* should not get here */}

这里写图片描述
添加FreeRTOS任务
构建和调试该项目,只是为了确保一切正常。
这里写图片描述
调试FreeRTOS任务
要在Debug视图中显示FreeRTOS线程,请参阅https://mcuoneclipse.com/2018/06/29/show-freertos-threads-in-eclipse-debug-view-with-segger-j-link-and-nxp-s32-design-studio/
但是FreeRTOS任务列表(使用Menu FreeRTOS>任务列表来显示该视图)不显示任何运行时信息:
这里写图片描述
FreeRTOS任务列表,没有运行时信息
这是我们将在接下来的步骤中添加的内容。
3、跟踪和运行时统计信息
在FreeRTOSConfig.h中,确保将以下定义设置为1(打开):

#define configGENERATE_RUN_TIME_STATS 1 /* 1: generate runtime statistics; 0: no runtime statistics */
#define configUSE_TRACE_FACILITY      1 /* 1: include additional structure members and functions to assist with execution visualization and tracing, 0: no runtime stats/trace */

这里写图片描述
启用运行时统计信息和跟踪功能
该configUSE_TRACE_FACILITY需要使用RTOS有在任务描述当前存储的运行时间计数器的附加数据元素,在configGENERATE_RUN_TIME_STATS自动关上,以创纪录的任务执行时间的功能。
4、配置定时器
接下来,我们必须设置一个计时器来测量任务执行时间。该计时器的运行速度至少比RTOS Tick计时器快10倍。
在我们的示例中,滴答率为1 kHz:

#define configTICK_RATE_HZ ((TickType_t)1000)

这意味着我们的运行时间应至少以10 kHz运行。
要配置这样的计时器,我可以使用MCUXpresso配置外设工具:
这里写图片描述
外围设备工具
在外设工具中,我们选择了FTM0定时器(我们也可以使用任何其他定时器)。
这里写图片描述
添加FTM0
定时器配置为10 kHz:
这里写图片描述
定时器输出频率
我们将使用定时器中断来增加一个计数器,所以不要忘记打开中断:
这里写图片描述
定时器溢出中断使能
然后单击按钮以更新项目源:
这里写图片描述
更新项目
切换回开发人员视角。
5、定时器ISR
接下来,我们将定时器中断代码添加到应用程序:

#include "fsl_ftm.h"
static uint32_t RTOS_RunTimeCounter; /* runtime counter, used for configGENERATE_RUNTIME_STATS */void FTM0_IRQHandler(void) {/* Clear interrupt flag.*/FTM_ClearStatusFlags(FTM0, kFTM_TimeOverflowFlag);RTOS_RunTimeCounter++; /* increment runtime counter */
}

6、添加定时器驱动
该项目尚未编译,因为必要的驱动程序尚未成为项目的一部分。要添加它们,请使用“管理SDK组件”按钮:
这里写图片描述
管理SDK组件按钮
然后检查ftm驱动程序并按OK,将额外的驱动程序源添加到项目中。
这里写图片描述
FTM驱动程序
7、向FreeRTOS添加定时器:用于运行时统计的FreeRTOS定时器宏
将以下行添加到FreeRTOSConfig.h:

extern void RTOS_AppConfigureTimerForRuntimeStats(void);
#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS()   RTOS_AppConfigureTimerForRuntimeStats()
extern uint32_t RTOS_AppGetRuntimeCounterValueFromISR(void);
#define portGET_RUN_TIME_COUNTER_VALUE()           RTOS_AppGetRuntimeCounterValueFromISR()

这告诉FreeRTOS它将用于初始化定时器的功能以及获取定时器值的功能。
这里写图片描述
向FreeRTOSConfig.h添加了运行时计数器设置
8、FreeRTOS Callback for Timer
现在我们需要添加我们配置FreeRTOS使用的两个回调。

void RTOS_AppConfigureTimerForRuntimeStats(void) {RTOS_RunTimeCounter = 0;EnableIRQ(FTM0_IRQn);
}uint32_t RTOS_AppGetRuntimeCounterValueFromISR(void) {return RTOS_RunTimeCounter;
}

9、正在运行…。
构建和调试您的应用程序。如果您现在停止应用程序并检查任务列表,它现在显示运行时信息:
这里写图片描述
显示运行时信息
10、没有Eclipse?没问题!
上面我使用了FreeRTOS的Eclipse Task List视图,这是NXP为他们的基于Eclipse的IDE(MCUXpresso IDE,S32DS for ARM和Kinetis Design Studio)所做的事情。但是可以直接从应用程序显示该信息,例如在终端LCD显示器上。McuOnEclipse上的FreeRTOS 包含一个使用它的shell /终端接口。
这里写图片描述
控制台上的任务运行时信息
下面的代码片段显示了如何为每个任务打印信息:

#if configGENERATE_RUN_TIME_STATSulTotalTime = portGET_RUN_TIME_COUNTER_VALUE(); /* get total time passed in system */ulTotalTime /= 100UL; /* For percentage calculations. */
#endif
...
#if configGENERATE_RUN_TIME_STATS && configUSE_TRACE_FACILITY/* runtime */UTIL1_strcpy(tmpBuf, sizeof(tmpBuf), (unsigned char*)"0x");UTIL1_strcatNum32Hex(tmpBuf, sizeof(tmpBuf), taskStatus.ulRunTimeCounter);if (ulTotalTime>0) { /* to avoid division by zero *//* What percentage of the total run time has the task used?This will always be rounded down to the nearest integer.ulTotalRunTime has already been divided by 100. */ulStatsAsPercentage = taskStatus.ulRunTimeCounter/ulTotalTime;if (ulStatsAsPercentage>0) {UTIL1_strcat(tmpBuf, sizeof(tmpBuf), (unsigned char*)" (");UTIL1_strcatNum16uFormatted(tmpBuf, sizeof(tmpBuf), ulStatsAsPercentage, ' ', 3);UTIL1_strcat(tmpBuf, sizeof(tmpBuf), (unsigned char*)"%)");} else {/* If the percentage is zero here then the task has consumed less than 1% of the total run time. */UTIL1_strcat(tmpBuf, sizeof(tmpBuf), (unsigned char*)" ( <1%)");}}buf[0] = '\0';UTIL1_strcatPad(buf, sizeof(buf), tmpBuf, ' ', PAD_STAT_TASK_RUNTIME);CLS1_SendStr(buf, io->stdOut);
#endifCLS1_SendStr((unsigned char*)"\r\n", io->stdOut);

♣概要
FreeRTOS运行时统计是一个非常有用的功能:它显示每个任务使用了多少时间,包括其中断时间。我需要的只是设置一些FreeRTOS配置宏并设置周期性定时器中断。当然,这并不是免费提供额外的定时器中断以及该功能所需的RAM和FLASH,但如果需要,它可以很容易地关闭以供最终版本使用。
♣链接
 GitHub上的示例项目:https://github.com/ErichStyger/mcuoneclipse/tree/master/Examples/MCUXpresso/FRDM-K64F/FRDM-K64F_SDK_FreeRTOS
 使用FreeRTOS进行性能和运行时分析
 MCUXpresso IDE网页:http://www.nxp.com/mcuxpresso/ide
 MCUXpresso IDE社区:http://www.nxp.com/mcuxpresso/ide/forum
 在Eclipse中更好的FreeRTOS调试
 McuOnEclipse库项目:https://github.com/ErichStyger/McuOnEclipseLibrary/tree/master/lib/FreeRTOS/Source
 ARM Cortex-M循环计数器:https://mcuoneclipse.com/2017/01/30/cycle-counting-on-arm-cortex-m-with-dwt/
 更好的FreeRTOS调试:https://mcuoneclipse.com/2017/03/18/better-freertos-debugging-in-eclipse/
 FreeRTOS RuntimeStats:https://www.freertos.org/rtos-run-time-stats.html
欢迎关注:
这里写图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/499469.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

github无法加载图片的解决办法

最近发现我的github上面项目README里面的图片全裂了&#xff0c;一直以为是github最近服务器不稳定。今天通过简单的查询&#xff0c;发现原来这个问题可以解决&#xff0c;但是不能永久有效&#xff0c;之后还会用到&#xff0c;因此记录在这里&#xff0c; 也分享给大家。 解…

C语言学习及应用笔记之二:C语言static关键字及其使用

C语言有很多关键字&#xff0c;大多关键字使用起来是很明确的&#xff0c;但有一些关键字却要相对复杂一些。我们这里要说明的static关键字就是如此&#xff0c;它的功能很强大&#xff0c;相应的使用也就更复杂。 一般来说static关键字的常见用法有三种&#xff1a;一是用作局…

μCUnit,微控制器的单元测试框架

在MCU on Eclipse网站上看到Erich Styger在8月26日发布的博文&#xff0c;一篇关于微控制器单元测试的文章&#xff0c;有很高的参考价值&#xff0c;特将其翻译过来以备学习。原文网址&#xff1a;https://mcuoneclipse.com/2018/08/26/tutorial-%CE%BCcunit-a-unit-test-fram…

PID控制器开发笔记之十一:专家PID控制器的实现

前面我们讨论了经典的数字PID控制算法及其常见的改进与补偿算法&#xff0c;基本已经覆盖了无模型和简单模型PID控制经典算法的大部。再接下来的我们将讨论智能PID控制&#xff0c;智能PID控制不同于常规意义下的智能控制&#xff0c;是智能算法与PID控制算法的结合&#xff0c…

Modbus协议栈开发笔记之七:Modbus ASCII Slave开发

与Modbus RTU在串行链路上分为Slave和Master一样&#xff0c;Modbus ASCII也分为Slave和Master&#xff0c;这一节我们就来开发Slave。对于Modbus ASCII从站来说&#xff0c;需要实现的功能其实与Modbus RTU的Slave是一样的。其操作过程也是一样的。首先接收到主站的访问命令&a…

Modbus协议栈开发笔记之八:Modbus ASCII Master开发

这一节我们来封装Modbus ASCII Master应用&#xff0c;Modbus ASCII主站的开发与RTU主站的开发是一致的。同样的我们也不是做具体的应用&#xff0c;而是实现ASCII主站的基本功能。我们将ASCII主站的功能封装为函数&#xff0c;以便在开发具体应用时调用。 对于ASCII主站我们主…

在Eclipse中使用Git

本文原文出自MCU on Eclipse网站&#xff0c;作者为Erich Styger&#xff0c;原文网址&#xff1a;https://mcuoneclipse.com/2018/09/30/tutorial-git-with-eclipse/。本人翻译了此篇文章&#xff0c;有些短语难以找到准确表达的中文词语&#xff0c;所以保持了原文。限于个人…

C语言学习及应用笔记之三:C语言const关键字及其使用

在C语言程序中&#xff0c;const关键字也是经常会用到的一个关键字&#xff0c;那么使用const关键字的目的是什么呢&#xff1f;事实上&#xff0c;在程序中使用const关键字的主要目的就是为了向使用者传递设计者的一些意图。 事实上&#xff0c;无论我们是使用const关键字声明…

nlp cs224n 学习笔记1 Introduction and Word Vectors

注&#xff1a;个人笔记&#xff0c;价值有限&#xff0c;不建议逗留。 word embedding 的意义和目的&#xff1f; 通过一种映射&#xff0c;将自然语言中的单词&#xff0c;嵌入到n维欧式空间中&#xff0c;得到可以用数学语言表达并用计算机计算的“词向量”。 同时我们希望…

Modbus协议栈开发笔记之一:实现功能的基本设计

Modbus作为开放式的工业通讯协议&#xff0c;在各种工业设备中应用极其广泛。本人也使用Modbus通讯很多年了&#xff0c;或者用现成的&#xff0c;或者针对具体应用开发&#xff0c;一直以来都想要开发一个比较通用的协议栈能在后续的项目中复用&#xff0c;而不必每次都写一遍…

天池CV学习赛:街景字符识别-思路与上分技巧汇总

Datawhale 和 天池 合作的零基础入门CV - 街景字符编码识别比赛的正式赛已经结束。本文对一些比赛思路和上分技巧进行了汇总和整理&#xff0c;希望对大家深入学习CV能够有帮助。 本文分为以下几部分&#xff1a; 如何优化官方baseline的效果&#xff1f; 其它解题思路的整理…

Modbus协议栈开发笔记之二:Modbus消息帧的生成

前面我们已经对Modbus的基本事务作了说明&#xff0c;也据此设计了我们将要实现的主从站的操作流程。这其中与Modbus直接相关的就是Modbus消息帧的生成。Modbus消息帧也是实现Modbus通讯协议的根本。 1、Modbus消息帧分析 MODBUS协议在不同的物理链路上的消息帧有一些差异&am…

动手学CV-目标检测入门教程:基本概念

3.1 目标检测基本概念 本文来自开源组织 DataWhale &#x1f433; CV小组创作的目标检测入门教程。 对应开源项目 《动手学CV-Pytorch》 的第3章的内容&#xff0c;教程中涉及的代码也可以在项目中找到&#xff0c;后续会持续更新更多的优质内容&#xff0c;欢迎⭐️。 如果使…

动手学CV-目标检测入门教程2:VOC数据集

3.2 目标检测数据集VOC 本文来自开源组织 DataWhale &#x1f433; CV小组创作的目标检测入门教程。 对应开源项目 《动手学CV-Pytorch》 的第3章的内容&#xff0c;教程中涉及的代码也可以在项目中找到&#xff0c;后续会持续更新更多的优质内容&#xff0c;欢迎⭐️。 如果…

C语言学习及应用笔记之四:C语言volatile关键字及其使用

在C语言中&#xff0c;还有一个并不经常使用但却非常有用的关键字volatile。那么使用volatile关键字究竟能干什么呢&#xff1f;接下来我将就此问题进行讨论。 一个使用volatile关键字定义变量&#xff0c;其实就是告诉编译系统这变量可能会被意想不到地改变。那么编译时&…

Modbus协议栈开发笔记之三:Modbus TCP Server开发

在完成了前面的工作后&#xff0c;我们就可以实现有针对性的应用了&#xff0c;首先我们来实现Modbus TCP的服务器端应用。当然我们不是做具体的应用&#xff0c;而是对Modbus TCP的服务器端应用进行封装以供有需要时调用。 这里我们不涉及TCP的协议&#xff0c;这部分与Modbu…

动手学CV-目标检测入门教程3:锚框(anchor)

3.3 锚框 or 先验框 本文来自开源组织 DataWhale &#x1f433; CV小组创作的目标检测入门教程。 对应开源项目 《动手学CV-Pytorch》 的第3章的内容&#xff0c;教程中涉及的代码也可以在项目中找到&#xff0c;后续会持续更新更多的优质内容&#xff0c;欢迎⭐️。 如果使…

动手学CV-目标检测入门教程4:模型结构

3.4 模型结构 本文来自开源组织 DataWhale &#x1f433; CV小组创作的目标检测入门教程。 对应开源项目 《动手学CV-Pytorch》 的第3章的内容&#xff0c;教程中涉及的代码也可以在项目中找到&#xff0c;后续会持续更新更多的优质内容&#xff0c;欢迎⭐️。 如果使用我们…

PID控制器开发笔记之十二:模糊PID控制器的实现

在现实控制中&#xff0c;被控系统并非是线性时不变的&#xff0c;往往需要动态调整PID的参数&#xff0c;而模糊控制正好能够满足这一需求&#xff0c;所以在接下来的这一节我们将讨论模糊PID控制器的相关问题。模糊PID控制器是将模糊算法与PID控制参数的自整定相结合的一种控…

动手学CV-目标检测入门教程5:损失函数

3.5 损失函数 本文来自开源组织 DataWhale &#x1f433; CV小组创作的目标检测入门教程。 对应开源项目 《动手学CV-Pytorch》 的第3章的内容&#xff0c;教程中涉及的代码也可以在项目中找到&#xff0c;后续会持续更新更多的优质内容&#xff0c;欢迎⭐️。 如果使用我们…