在ARM Cortex-M上实现FreeRTOS性能计数器

  说明:本文翻译自Erich Styger的文章《Implementing FreeRTOS Performance Counters on ARM Cortex-M》,文章的权属属于原作者。

  当使用像FreeRTOS这样的RTOS时,迟早要问一个问题:每个任务花费多少时间?基于Eclipse的MCUXpresso IDE具有很好的视图,准确显示了此类信息:

FreeRTOS运行时信息

  为了使FreeRTOS(或“任务列表”视图)显示非常有用的信息,开发人员必须提供帮助,以便RTOS可以收集此信息。本文说明如何在ARM Cortex-M上完成此操作。

1、概述

  不久前,我从处理器专家的角度讨论了FreeRTOS的性能和运行时分析中的该主题。这次是关于使用“本机” FreeRTOS和使用NXP MCUXpresso SDK,但是相同的原理将适用于Cortex-M处理器和微控制器的所有其他环境。至于FreeRTOS端口,我正在使用https://github.com/ErichStyger/McuOnEclipseLibrary中的端口,因为该端口已经存在所有需要的钩子。GitHub上提供了本文中使用的所有文件和源。

2、如何工作

  操作系统使用计数器来衡量任务执行时间。因此,在任务上下文切换时间,此计数器用于确定该任务使用的时间。重要的一点是,该时间不是绝对的(例如37毫秒),而是一些“滴答声”(例如241个滴答声)。RTOS知道总体上使用了多少“滴答声”。RTOS知道系统中有多少个任务,因此它可以显示每个任务花费了总时间的百分比。另一个要注意的是,时间*包括*在中断中花费的时间。

  这是一种非常简单但功能强大的估算任务执行时间的方法,通常就是您所需要的。它可以通过一种非常简单的方式来实现:使用一个使计数器递增的计时器和一个用于读取计数器值的函数。

  要打开性能测量,我必须启用两个FreeRTOS配置设置:

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

  要配置计时器并读取计数器,我必须使用两个宏来告诉函数名称:

1 #define configGET_RUNTIMER_COUNTER_VALUE_FROM_ISR   AppGetRuntimeCounterValueFromISR
2
3 #define configCONFIGURE_TIMER_FOR_RUNTIME_STATS     AppConfigureTimerForRuntimeStats

3、使用“滴答”计数器

  一种非常简单的衡量任务执行情况的方法是使用FreeRTOS滴答计数器本身。可以通过以下方式启用

1 #define configGENERATE_RUN_TIME_STATS_USE_TICKS     (1)

  但是,这仅在任务执行时间超过RTOS滴答周期时才能测量任务执行时间。对于更快的任务,此方法没有用。根据Nyquist-Shannon采样定理,我最好使用2倍(更好:10倍)的测量频率。

4、使用Cortex-M周期计数器

  实现该计数器的另一种方法是使用Cortex-M周期计数器,该计数器已在许多设备上实现,并给出了很好的结果。最好的是:无需中断或额外的计时器。可能的实现如下所示:

 1 static uint32_t prevCycleCounter, cycleCntCounter = 0;
 2
 3 void AppConfigureTimerForRuntimeStats(void) {
 4   cycleCntCounter = 0;
 5   McuArmTools_InitCycleCounter();
 6   prevCycleCounter = McuArmTools_GetCycleCounter();
 7 }
 8
 9 uint32_t AppGetRuntimeCounterValueFromISR(void) {
10   uint32_t newCntr, diff;
11
12   newCntr = McuArmTools_GetCycleCounter();
13   diff = newCntr-prevCycleCounter;
14   prevCycleCounter = newCntr;
15   cycleCntCounter += diff>>12; /* scale down the counter */
16   return cycleCntCounter;
17 }

5、使用定期定时器中断

  标准方法是使用定期中断计时器,该计时器增加计数器。对于1 kHz滴答计时器,推荐的频率是FreeRTOS滴答计时器频率的10倍,在这种情况下为10 kHz(100 us):

 1 static uint32_t perfCounter = 0;
 2
 3 #define PIT_BASEADDR       PIT
 4 #define PIT_SOURCE_CLOCK   CLOCK_GetFreq(kCLOCK_BusClk)
 5 #define PIT_CHANNEL        kPIT_Chnl_0
 6 #define PIT_HANDLER        PIT0_IRQHandler
 7 #define PIT_IRQ_ID         PIT0_IRQn
 8
 9 void PIT_HANDLER(void) {
10   PIT_ClearStatusFlags(PIT_BASEADDR, PIT_CHANNEL, kPIT_TimerFlag);
11   perfCounter++;
12   __DSB();
13 }
14
15 void AppConfigureTimerForRuntimeStats(void) {
16   pit_config_t config;
17
18   PIT_GetDefaultConfig(&config);
19   config.enableRunInDebug = false;
20   PIT_Init(PIT_BASEADDR, &config);
21   PIT_SetTimerPeriod(PIT_BASEADDR, PIT_CHANNEL, USEC_TO_COUNT(100U, PIT_SOURCE_CLOCK));
22   PIT_EnableInterrupts(PIT_BASEADDR, PIT_CHANNEL, kPIT_TimerInterruptEnable);
23   NVIC_SetPriority(PIT_IRQ_ID, 0);
24   EnableIRQ(PIT_IRQ_ID);
25   PIT_StartTimer(PIT_BASEADDR, PIT_CHANNEL);
26 }
27
28 uint32_t AppGetRuntimeCounterValueFromISR(void) {
29   return perfCounter;
30 }

6、摘要

  FreeRTOS包含一项功能,可以测量相对于系统中其他任务的任务执行时间。我需要提供的是计时器或某种计数器的初始化例程,以及获取计数器值的方法。如果您对检查FreeRTOS计时的其他方式感兴趣,请查看Percepio Tracealyzer或Segger SystemView。如果您希望应用程序本身显示性能数据,请查看“ 使用FreeRTOS进行性能和运行时分析”中介绍的Shell / Commandline实现。

7、链接

欢迎关注:

原文地址:https://www.cnblogs.com/foxclever/p/12151472.html

时间: 2024-10-12 22:35:56

在ARM Cortex-M上实现FreeRTOS性能计数器的相关文章

ARM7与ARM Cortex比较

ARM7与ARM Cortex比较  1.ARM实现方法 ARM Cortex是一种基于ARM7v架构的最新ARM嵌入式内核,它采用哈佛结构,使用分离的指令和数据总线(冯诺伊曼结构下,数据和指令共用一条总 线).从本质上来说,哈佛结构在物理上更为复杂,但是处理速度明显加快.根据摩尔定理,复杂性并不是一件非常重要的事,而吞吐量的增加却极具价值. ARM公司对Cortex的定位是:向专业嵌入式市场提供低成本.低功耗的芯片.在成本和功耗方面,Cortex具有相当好的性能,ARM公司认为它特别适用于汽车

ARM cortex a 之时钟系统1

ARM cortex a系列的时钟系统是一个非常复杂而且麻烦的东西,下面我们首先明确一些概念和东西. 本部分主要介绍一下时钟系统的初始化工作,以及里面的一些原理. S5PV210的时钟系统是一个非常麻烦的东西,首先需要时钟信号的产生,时钟发生器只有和晶振一起工作才能产生时钟信号,这两个单独使用的话是没有任何作用的. 时钟系统分为三个大域:即主系统(MSYS),显示系统(DSYS),和外围系统(PSYS). (1)MSYS域包括cortexA8处理器,DRAM内存控制器(DMC0和DMC1),3D

opencv在arm和x86上的移植

一.开发环境 操作系统:fedora14 Opencv版本:2.0 Qt版本:4.7 arm:mini6410 交叉编译工具:arm-linux-gcc-4.5.1 二.安装与配置 Linux系统的安装,交叉Qt-creator的安装还有交叉编译工具的安装,网上说的基本都没什么问题,测试后都可以用.这里安装Qt-Creator遇到了一点小问题,按照网上的和mini6410开发手册上的安装方法太复杂了,用QtSdk-offline-linux-x86-v1.2.1.run安装方便又准确. 这篇文章

ARM Cortex M0权威指南_PDF电子书下载 带书签目录 高清完整版 http://pan.baidu.com/s/1jGKQSwY MariaDB入门很简单_PDF电子书下载 带

ARM  Cortex  M0权威指南_PDF电子书下载 带书签目录 高清完整版   http://pan.baidu.com/s/1jGKQSwY MariaDB入门很简单_PDF电子书下载 带书签目录 高清完整版  http://pan.baidu.com/s/1hqpgV20 管理就是走流程__没有规范流程,管理一切为零_PDF电子书下载 带书签目录 高清完整版  http://pan.baidu.com/s/1bntuLyf 搜索引擎优化  SEO  方法与技巧  第5版_PDF电子书下

STM32 32-bit Arm Cortex MCUs&&MPUS

一.STM32 32-bit Arm Cortex MCUs 二.STM32 Arm Cortex MPUs 原文地址:https://www.cnblogs.com/TonyJia/p/12677712.html

ARM cortex M3寄存器及指令集

1.cortex M3拥有通用寄存器R0-R15及一些特殊寄存器: R0‐R7 也被称为低组寄存器.所有指令都能访问它们.它们的字长全是 32 位,复位后的初始值是不可预料的. R8‐R12 也被称为高组寄存器.这是因为只有很少的 16 位 Thumb 指令能访问它们, 32位的指令则不受限制.它们也是 32 位字长,且复位后的初始值是不可预料的 . R13 是堆栈指针.在 CM3 处理器内核中共有两个堆栈指针,于是也就支持两个堆栈.当引用 R13(或写作 SP)时,你引用到的是当前正在使用的那

ARM Cortex Design Considerations for Debug

JTAG was the traditional mechanism for debug connections for ARM7/9 parts, but with the Cortex-M family, ARM introduced the Serial Wire Debug (SWD) Interface. SWD is designed to reduce the pin count required for debug from the 5 used by JTAG (includi

Windows下通过ARM目标板上的gdbserver进行远程调试的方法

因某种需要,要在Windows平台上进行程序开发,目标板是基于Micrel芯片(ARMv4t)做的,上面运行有Linux最小系统,只有最基本的命令,需要在Windows平台上交叉编译能在ARMv4t上运行的目标代码,并且还要能进行远程调试.基于这些需求,初步计划按以下步骤进行: 1.先在Windows平台上交叉编译一个简单的C语言程序,并上传到开发板上,能正常运行即可: 2.交叉编译gdbserver,并上传到开发板: 3.进行远程调试. 按上述计划,首先要找一个Windows环境下的交叉编译环

arm开发板上找不到/dev/i2c-*设备

最近在调试arm与外设iic通讯是,想来个投机取巧,先不写单独的驱动,直接通过iic bus设备是否可以连接到外设,然后发现在板子上找不到"/dev/i2c-n"的设备,标准的系统应该都是有的. 回去看内核驱动 代码位于 lichee/linux-3.10/drivers/i2c/ # # Makefile for the i2c core. # obj-$(CONFIG_I2C_BOARDINFO) += i2c-boardinfo.o obj-$(CONFIG_I2C) += i2