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

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

3天内不再提示

测量ARM Cortex-M MCU上的代码执行时间

星星科技指导员 来源:嵌入式计算设计 作者:Jean Labrosse 2022-06-08 16:50 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

在许多实时应用程序中,CPU 可以在不到 5% 的代码中花费 95%(或更多)的时间。电机控制、发动机控制、无线通信和许多其他对时间敏感的应用就是这种情况。这些嵌入式系统通常是用 C 语言编写的,并且开发人员经常被迫手动优化代码,可能会恢复为汇编语言,以满足紧迫的期限。测量部分代码的实际执行时间可以帮助您找到代码中的热点。本文将展示如何轻松测量和显示实时基于 Cortex-M 的 MCU 上的代码执行时间。

测量代码的执行时间

有很多方法可以测量代码执行时间。作为一名嵌入式工程师,我经常使用一个或多个数字输出和示波器。您只需在执行要监视的代码之前将其中一个输出设置为高电平,然后再将输出设置为低电平。当然,在您执行此操作之前还有相当多的设置工作:找到一个或多个空闲输出,确保它们易于探测,将端口配置为输出,编写代码,编译,设置范围等等。 收到信号后,您可能需要对其进行一段时间的监控以查看最小值和最大值。数字存储示波器使这个过程更容易,但还有其他方法比这更容易。

测量执行时间的另一种方法是使用具有跟踪功能的调试探针。您只需运行代码、查看跟踪、计算增量时间(通常是手动)并将 CPU 周期转换为微秒。不幸的是,跟踪为您提供了一个执行实例,您可能需要进一步查看跟踪捕获以找到最坏情况下的执行时间。这可能是一个乏味的过程。

Cortex-M 周期计数器

大多数基于 Cortex-M 的处理器上的 CoreSight 调试端口都包含一个 32 位自由运行计数器,用于计算 CPU 时钟周期。该计数器是调试监视和跟踪 (DWT) 模块的一部分,可轻松用于测量代码的执行时间。以下代码是启用和初始化这个非常有用的功能所需的全部内容。

#define ARM_CM_DEMCR (*(uint32_t *)0xE000EDFC)

#define ARM_CM_DWT_CTRL (*(uint32_t *)0xE0001000)

#define ARM_CM_DWT_CYCCNT (*(uint32_t *)0xE0001004)

if (ARM_CM_DWT_CTRL != 0) { // 看看

DWTDEMCR是否可用 ARM = 1 《《 24; // 设置位 24

ARM_CM_DWT_CYCCNT = 0;

ARM_CM_DWT_CTRL |= 1 《《 0; // 设置位 0

}

使用 DWT 循环计数器测量代码执行时间

您可以通过读取该段之前和之后的循环计数器的值来测量和计算代码段的执行时间,如下所示。当然,这意味着您必须检测您的代码,但您会得到一个非常准确的值。

uint32_t 开始;

uint32_t 停止;

uint32_t 增量;

开始 = ARM_CM_DWT_CYCCNT;

// 测量

停止的代码 = ARM_CM_DWT_CYCCNT;

delta = 停止 - 开始;

因为我们使用的是无符号数学,所以 delta 表示测量代码的实际执行时间(以 CPU 时钟周期为单位),即即使 stop 小于 start。

当然,在测量开始和停止读数之间括起来的代码的执行时间时可能会发生中断,因此每次执行此序列时很可能会有不同的值。在这种情况下,您可能希望在测量期间禁用中断以删除该伪影,如下所示,但要了解禁用中断是暂时的,并且仅包含在测量中。话虽如此,包含中断的工件可能会很有用,因为它们会影响代码的截止日期。

禁用中断;

开始 = ARM_CM_DWT_CYCCNT;

// 测量

停止的代码 = ARM_CM_DWT_CYCCNT;

启用中断;

delta = 停止 - 开始;

如果被测量的代码包含条件语句、循环或任何可能导致变化的东西,那么获得的值可能不代表最坏情况下的执行时间。要纠正这个问题,您可以简单地添加一个峰值检测器,如下所示。当然,在进行任何测量之前,需要声明 max 并将其初始化为最小值(即 0)。

开始 = ARM_CM_DWT_CYCCNT;

// 测量

停止的代码 = ARM_CM_DWT_CYCCNT;

delta = 停止 - 开始;

if (max 《 delta) {

max = delta;

}

同样,了解最短执行时间也可能很有趣且有用。在进行任何测量之前,只需声明 min 并将其初始化为最大可能值(即 0xFFFFFFFF)。这是新代码:

开始 = ARM_CM_DWT_CYCCNT;

// 测量

停止的代码 = ARM_CM_DWT_CYCCNT;

delta = 停止 - 开始;

if (max 《 delta) {

max = delta;

}

if (min 》 delta) {

min = delta;

}

执行时间还取决于 CPU 是否配备高速缓存,就像某些 Cortex-M4 处理器和 Cortex-M7 一样。如果您的系统使用指令或数据缓存,则同一段代码的多次测量可能会不一致。您可能会考虑禁用缓存以测量最坏的情况。

为了显示这些值,大多数调试器允许您实时显示这些变量值。如果是这种情况,则需要在全局范围内声明显示的变量以保留其值并允许实时监控。此外,不幸的是,这些值代表 CPU 时钟周期,并且大多数调试器都不够复杂,无法缩放变量以用于显示目的。假设 CPU 时钟速度为 16 MHz,显示 70.19 微秒比显示 1123 个周期要方便得多。实际上有一种更好的方法来显示实时变量,它还提供了缩放值的能力,因此您可以以更易读的形式查看它们。我将很快解释如何做到这一点。

经过时间模块

您当然可以将代码片段添加到您的应用程序中,或者您可以使用我编写的一个简单模块(包含在本文中)。与 elapsed_time.h 模块一起出现在下方的“elapsed_time.c”模块仅包含 4 个函数。

要使用:

只需#include

在使用 elapsed_time.c 中定义的其他函数之前调用 elapsed_time_init()。

通过设置 ELAPSED_TIME_MAX_SECTIONS 定义经过时间测量结构的最大数量。这对应于您要使用停止/启动代码包装的不同代码片段的数量。

调用 elapsed_time_start() 并将您要监视的代码片段的索引传递给它(即 0 。. ELAPSED_TIME_MAX_SECTIONS-1)。

调用 elapsed_time_stop() 并将您在 elapsed_time_start() 调用中使用的索引传递给它。

如果您的调试器允许您实时监控变量(即在目标运行时),您可以显示 elapsed_time_tbl[] 并查看您使用的相应索引的 ELAPSED_TIME 结构。

重复执行第 4 步到第 6 步,并让您的代码处于最坏和最好的情况下,以便 ELAPSED_TIME 结构的 .min 和 .max 字段很好地表示您正在测量的代码片段的执行时间。

您会注意到(请参阅 elapsed_time.c)我在测量期间没有禁用中断,因为可能涉及 ISR,您可能想知道这如何影响感知的执行时间。

void main (void)

{

// 一些代码

elapsed_time_init(); // 初始化模块

// 一些代码

}

void MyCode (void)

{

// 这里的一些代码

elapsed_time_start(0); // 开始测量代码片段 #0

// 正在测量的代码

elapsed_time_stop(0); // 停止和

// 一些其他代码

}

当然,最小和最大执行时间取决于您进行测量的频率以及代码是否分别受制于其最佳和最差条件。

elapsed_time_tbl[] 中的字段可以使用 Silicon Labs 的 Micrium uC/Probe 显示。事实上,uC/Probe 可以显示每个字段并缩放每个值,以便可以将 CPU 时钟周期转换为微秒,这更加友好。与大多数 Cortex-M MCU 内置的 CoreSight 调试端口连接时,uC/Probe 不需要对您的代码进行任何检测。

附带说明一下,不需要显示起始字段,因为它仅用于记录测量开始时 DWT 循环计数器的值。但是,开始字段可用于显示活动。换句话说,当您看到此值发生变化时,您就会知道正在进行测量。

使用 uC/Probe 的示例显示

我将 elapsed_time.c 模块与 uC/Probe 结合使用,并测量了四个代码片段的执行时间。

图 1 显示了使用 IAR 的 LiveWatch(左)和 uC/Probe 的 Tree View 控件(右)的原始形式的值。请注意,屏幕截图是在不同时间拍摄的。elapsed_time_tbl[] 是一个数组,用于存储不同代码片段的测量值。

图 1,IAR 和 uC/Probe 的树形视图控件。

您还可以将最小/最大/当前值分配给仪表和数字指示器,如图 2 所示。在这里,这些值以微秒为单位显示,因为我应用了 0.0125 的缩放因子,CPU 以 80 MHz 运行。我还决定只显示最大执行时间。左侧的按钮用于重置统计信息,从而强制重新计算最小值和最大值。

【图2 | 使用 uC/Probe 的仪表之一显示最大执行时间。]

uC/Probe 非常强大的功能之一是能够与 Microsoft 的 Excel 交互,从而在电子表格上显示值(实时),如图 3 所示。

【图3 | 使用 Excel 显示实时数据。]

概括

作为嵌入式开发人员,我们有很多工具可以用来测试和验证我们的设计。我已经演示了使用 Cortex-M 处理器的众多功能之一是多么容易,即 DWT 循环计数器。

Micrium 的 uC/Probe 提供了许多功能,允许您使用仪表、仪表、数字指示器、Excel 界面或图形/绘图来监控应用程序中的许多变量。凭借其内置的示波器功能,一旦满足触发条件,您还可以捕获多达七个附加变量的值。

随意使用或改进 elapsed_time.* 模块。不要犹豫,向我发送反馈。我考虑添加的另一个功能是在最大执行时间超过阈值时调用的回调函数。如果您想在这种情况发生时立即收到通知(打开 LED、发出警报等),这可能很有用。事实上,您甚至可以设置一个断点,以防您想查看是什么条件导致超过阈值。

审核编辑:郭婷

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

    关注

    68

    文章

    20148

    浏览量

    246983
  • led
    led
    +关注

    关注

    243

    文章

    24433

    浏览量

    687298
  • 计数器
    +关注

    关注

    32

    文章

    2306

    浏览量

    97559
收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    Cortex-M产品的特色

    与外部设备进行通信。 指令集:Cortex-M系列处理器支持ARM Thumb指令集,包括16位和32位的Thumb-2指令集,以及可选的DSP指令和浮点单元,提供了高性能的信号处理能力
    发表于 11-26 07:22

    Cortex-M内核中的精确延时的方法

    使用 CYCCNT寄存器来测量执行某个任务所花的周期数,这也可以用作时间基准相关的目的(操作系统中统计 CPU使用率可以用到它)。” Cortex-M中的DWT它有一个32位的寄存器叫
    发表于 11-21 07:51

    Cortex-M级别的转换

    一、 简述 Cortex-M 里面有特权级别的概念,不同级别可以设定不同的权限,如何转换特权级别基本是本章的内容。 二、操作模式 ARM M 核操作模式有两个: 线程(Thread)模式:在复位时或
    发表于 11-19 07:32

    STM32C031x4/x6:面向主流应用的Arm® Cortex®-M0+ 微控制器

    STMicroelectronics的STM32C0x Arm^® ^Cortex ^®^ -M0+ 32位MCU安装了高性能Arm
    的头像 发表于 10-27 15:05 334次阅读
    STM32C031x4/x6:面向主流应用的<b class='flag-5'>Arm</b>® <b class='flag-5'>Cortex</b>®-<b class='flag-5'>M</b>0+ 微控制器

    MSPM0G1507 80MHz Arm® Cortex-M0®+ MCU技术手册

    MSPM0G150x 微控制器 (MCU) 是 MSP 高度集成、超低功耗 32 位 MCU 系列的一部分,基于增强型 Arm Cortex-M0+ 32 位核心平台,工作频率高达 8
    的头像 发表于 09-30 09:08 578次阅读
    MSPM0G1507 80MHz <b class='flag-5'>Arm</b>® <b class='flag-5'>Cortex-M</b>0®+ <b class='flag-5'>MCU</b>技术手册

    【RA-Eco-RA6M4开发板评测】使用ULINK2开发瑞萨MCU

    · 支持 ARM7、ARM9、Cortex-M、8051 和 C166 设备 · JTAG 速度高达 10MHz · 针对基于 ARM Corte
    发表于 09-25 23:08

    请问NuMicro® Cortex-M® 系列芯片是否支持 I2C 监视器功能?

    NuMicro® Cortex-M® 系列芯片是否支持 I2C 监视器功能?
    发表于 08-21 06:04

    请问如何在 M48x 激活 ETM?

    最后,我得到了新唐新款出色的MCU芯片M48x及其评估板。 最令人兴奋的新功能之一是ETM,这是新唐科技的其他Cortex-M MCU没有
    发表于 08-15 07:49

    Analog Devices Inc. MAX32675C超低功耗Arm® Cortex®-M4F MCU数据手册

    MCU基于带浮点单元(FPU)的超低功耗Arm Cortex- M4,包括384KB(376KB用户)闪存和160KB SRAM。在整个闪存、SRAM和缓存
    的头像 发表于 06-03 10:04 670次阅读
    Analog Devices Inc. MAX32675C超低功耗<b class='flag-5'>Arm</b>® <b class='flag-5'>Cortex</b>®-<b class='flag-5'>M</b>4F <b class='flag-5'>MCU</b>数据手册

    PPEC新品发布丨图形化编程数字电源专用 ARM Cortex-M4 MCU

    痛点。该芯片基于120MHz主频Cortex-M4内核,集成高精度PWM、多协议通信接口等丰富资源。在硬件设计,采用LQFP64封装,兼容主流ARM芯片引脚布局
    的头像 发表于 05-22 17:30 1132次阅读
    PPEC新品发布丨图形化编程数字电源专用 <b class='flag-5'>ARM</b> <b class='flag-5'>Cortex-M</b>4 <b class='flag-5'>MCU</b>

    tc397如何高精度(微秒级别)测量代码执行时间

    tc397如何高精度(微秒级别)测量代码执行时间
    发表于 04-21 07:31

    MSPM0G1505 80MHz Arm® Cortex-M0®+ MCU数据手册

    MSPM0G150x 微控制器 (MCU) 是 MSP 高度集成、超低功耗 32 位 MCU 系列的一部分,该系列基于增强型 Arm Cortex-M0+ 32 位内核平台,运行频率高
    的头像 发表于 04-15 14:08 873次阅读
    MSPM0G1505 80MHz <b class='flag-5'>Arm</b>® <b class='flag-5'>Cortex-M</b>0®+ <b class='flag-5'>MCU</b>数据手册

    MSPM0G3106 80MHz Arm® Cortex-M0®+ MCU数据手册

    MSPM0G310x 微控制器 (MCU) 是 MSP 高度集成、超低功耗 32 位 MCU 系列的一部分,基于增强型 Arm Cortex-M0+ 32 位内核平台,运行频率高达 8
    的头像 发表于 04-15 11:44 895次阅读
    MSPM0G3106 80MHz <b class='flag-5'>Arm</b>® <b class='flag-5'>Cortex-M</b>0®+ <b class='flag-5'>MCU</b>数据手册

    MSPM0C1103 24MHz Arm® Cortex-M0®+ MCU数据手册

    MSPM0C110x 微控制器 (MCU) 是 MSP 高度集成的超低功耗 32 位 MCU 系列的一部分,基于增强型 Arm Cortex-M0+ 内核平台,运行频率高达 24MHz
    的头像 发表于 04-15 09:39 1045次阅读
    MSPM0C1103 24MHz <b class='flag-5'>Arm</b>® <b class='flag-5'>Cortex-M</b>0®+ <b class='flag-5'>MCU</b>数据手册

    充电桩CCC认证什么时候执行

    充电桩CCC认证的执行时间表如下:
    的头像 发表于 12-25 17:12 1358次阅读