gpt4 book ai didi

assembly - 了解 Cortex M4 上的周期计数

转载 作者:行者123 更新时间:2023-12-02 08:03:43 27 4
gpt4 key购买 nike

我正在使用带有 Cortex M4 的 STM32F407,并且通过在调用我实现的函数(C 语言)之前和之后直接读取 DWT_CYCCNT 来测量函数的周期计数集会。我想了解我得到的结果。

08000610 <my_function>:
8000610: f04f 20ff mov.w r0, #4278255360 ; 0xff00ff00
8000614: f04f 11ff mov.w r1, #16711935 ; 0xff00ff
8000618: ea81 0100 eor.w r1, r1, r0
800061c: ea81 0100 eor.w r1, r1, r0
8000620: ea81 0100 eor.w r1, r1, r0
8000624: ea81 0100 eor.w r1, r1, r0
8000628: 4770 bx lr
800062a: bf00 nop

执行上述(包括函数调用)需要21个周期。当我添加一条 eor 指令时:

08000610 <my_function>:
8000610: f04f 20ff mov.w r0, #4278255360 ; 0xff00ff00
8000614: f04f 11ff mov.w r1, #16711935 ; 0xff00ff
8000618: ea81 0100 eor.w r1, r1, r0
800061c: ea81 0100 eor.w r1, r1, r0
8000620: ea81 0100 eor.w r1, r1, r0
8000624: ea81 0100 eor.w r1, r1, r0
8000628: ea81 0100 eor.w r1, r1, r0
800062c: 4770 bx lr
800062e: bf00 nop

这突然变成了 28 个周期。

添加另一个 eor 不会改变周期计数(仍然是 28)。再添加 1 会使周期计数器按预期增加 1(即 29)。

为什么?

  • 根据ARMeor 应该始终为 1 个周期。
  • 我不明白三级管道如何解释这种行为。
  • 这些说明都是字对齐的,因此没有问题。
  • 我怀疑它与闪存访问有关,尽管我尝试将此代码放入 IWRAM 并从那里执行,但这并没有改变任何内容。
  • 查看二进制文件的 objdump,我可以确认我的测量结果没有任何问题。
  • 最后,我尝试了强制使用 16 位 Thumb 编码,但这并没有帮助我理解发生了什么。

有什么想法吗? :)

(这个问题有点类似于 #18960524 ,但没有 mul 和加载指令,可能会弄乱事情。)

最佳答案

核心没有缓存*,但系统肯定有 - 即 ST 的“ART Accelerator”。

the TRM 第 3.5.2 节所述,这个东西位于总线路径中,从闪存中进行全宽(128 位)读取,然后根据请求将这些指令提供给核心的 ICode 接口(interface)。

第 3.5.1 节记录了闪存等待状态数量与时钟速度和电压配置的关系,这对于 STM32F407 来说意味着最坏情况下最多为 7 个周期。我将从问题的本质猜测您可能尚未启用加速器的预取或指令缓存功能,这意味着您将暂停每 16 字节的指令 n 在从闪存中拖入下一个 block 时循环这些等待状态。

数学变得比我现在想要计算的更尴尬,但足以说明 21 个周期是至少 7 个执行周期、2 个管道重新填充的重叠组合(每个周期 1-3 个周期)调用并返回)和至少 2*n 个等待状态以从闪存获取至少 2 个 block 。

现在,值得注意的是,第一个函数的长度为 28 字节,而第二个函数的长度为 32 - 即两个 16 字节的 block 。第二个值得注意的事实是:M4 的 ICode 接口(interface)仅执行 32 位读取,然后从该读取阶段为管道的获取阶段提供数据(我假设当管道仅消耗第一个半字时,它只是简单地转动拇指一个周期)。我非常有信心,您在第二个示例中看到的是两者之间不愉快的交互 - 通过一些有根据的猜测,我想象了这样的情况:

  • 当管道的提取阶段拉入 0x800062c 处的指令时,ICode 接口(interface)开始请求 0x8000630 处的下一个字。
  • 当管道解码 bx lr 并从同一指令字获取 0x800062e 时,ICode 接口(interface)稍作喘息,但加速器现在正在等待闪存传送 0x8000630-0x8000640 的读取数据.
  • 分支执行,ICode 接口(interface)现在必须等待 n-1 个周期,以便加速器完成读取,而该读取现在将在它之前被丢弃可以请求 lr 持有的任何地址(然后再等待 n 个周期才能实际获取它)。

如果您确实想尝试考虑每个周期,那么查看 FLASH_ACR 似乎应该可以更清楚地了解您的配置是什么 - 除非您将整个时钟精确到 ARM 的零等待状态配置核心时序假设( note the first paragraph ),您将不得不考虑的不仅仅是核心。更一般地说,我建议“在不彻底研究供应商文档的情况下对微 Controller 进行编程”与“简单地走进魔多”一样;)

* Cortex-M7 是第一个真正拥有自己的内部缓存的 ARM M 级内核。

关于assembly - 了解 Cortex M4 上的周期计数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34725105/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com