【问题标题】:ARM ITCM interface and FLash accessARM ITCM 接口和闪存访问
【发布时间】:2020-05-27 21:39:00
【问题描述】:

如果对闪存的访问从地址 0x0200 0000 开始,则通过 ITCM 总线自动执行。应该启用 ART 加速器™,以通过 ITCM 总线获得对闪存的 0 等待状态访问。通过设置 FLASH_ACR 寄存器中的第 9 位来启用 ART,而通过设置同一寄存器中的第 8 位来启用 ART-Prefetch。

如果我将我的程序代码从 0x0200 0000 开始,如果 ART 加速器未启用会怎样?仅使用 AXIM 总线代替启动代码然后启用 ART 加速器并将执行指向位于 0x0200 0000 的程序区域是否有益。

我只是有点困惑。

https://www.st.com/content/ccc/resource/technical/document/application_note/0e/53/06/68/ef/2f/4a/cd/DM00169764.pdf/files/DM00169764.pdf/jcr:content/translations/en.DM00169764.pdf

第 12 页

【问题讨论】:

    标签: arm bus


    【解决方案1】:

    所以让我们试试吧。 NUCLEO-F767ZI

    一般的Cortex-M7:

    Prefetch Unit
    The Prefetch Unit (PFU) provides:
    1.2.3
    • 64-bit instruction fetch bandwidth.
    • 4x64-bit pre-fetch queue to decouple instruction pre-fetch from DPU pipeline operation.
    • A Branch Target Address Cache (BTAC) for the single-cycle turn-around of branch predictor state and target address.
    • A static branch predictor when no BTAC is specified.
    • Forwarding of flags for early resolution of direct branches in the decoder and first execution stages of the processor pipeline.
    

    对于此测试,分支预测会妨碍您将其关闭:

    将 ACTLR 设置为 00003000(十六进制,这里的大多数数字都是十六进制)

    不知道如何禁用 PFU 无论如何也不希望有这样的控制。

    所以我们希望预取一次读取 64 位,对齐的 4 条指令 边界。

    来自 ST

    DBANK 位被设置,表示单个银行

    指令预取

    在单组模式的情况下(nDBANK 选项位设置)256 位代表 8 条 32 位指令到 16 位 16 位指令根据启动的程序。因此,在顺序代码的情况下,至少需要 8 个 CPU 周期才能执行上一条读取的指令行。

    所以 ST 将把它变成 256 位或 16 条指令

    使用 systick 计时器。我以 16Mhz 运行,因此闪存处于零等待状态。

    08000140 <inner>:
     8000140:   46c0        nop         ; (mov r8, r8)
     8000142:   46c0        nop         ; (mov r8, r8)
     8000144:   46c0        nop         ; (mov r8, r8)
     8000146:   46c0        nop         ; (mov r8, r8)
     8000148:   46c0        nop         ; (mov r8, r8)
     800014a:   46c0        nop         ; (mov r8, r8)
     800014c:   3901        subs    r1, #1
     800014e:   d1f7        bne.n   8000140 <inner>
    
    00120002
    

    所以每个循环有 12 个时钟。来自 ARM 的两个预取,第一个成为单个 ST 取指。应该是零等待状态。请注意这是 AXIM 的地址

    如果我减少 nop 的数量,它会一直保持在 0x1200xx 直到这里:

    08000140 <inner>:
     8000140:   46c0        nop         ; (mov r8, r8)
     8000142:   46c0        nop         ; (mov r8, r8)
     8000144:   3901        subs    r1, #1
     8000146:   d1fb        bne.n   8000140 <inner>
    
    00060003
    

    一个手臂取而不是两个。时间减半,所以预取主导了我们的 性能。

    08000140 <inner>:
     8000140:   46c0        nop         ; (mov r8, r8)
     8000142:   46c0        nop         ; (mov r8, r8)
     8000144:   46c0        nop         ; (mov r8, r8)
     8000146:   46c0        nop         ; (mov r8, r8)
     8000148:   3901        subs    r1, #1
     800014a:   d1f9        bne.n   8000140 <inner>
    
    000 (zero wait states)
    
    00120002
    
    001 (1 wait state)
    
    00140002
    
    002 (2 wait states)
    
    00160002
    
    202 (2 wait states enable ART)
    
    0015FFF3
    

    为什么这会影响 AXIM?

    所以每个等待状态每个循环增加 2 个时钟,每个循环有两个取指,所以也许每次取指都会导致 st 执行它的 256 位取指之一,但这似乎被打破了。

    切换到 ITCM

    00200140 <inner>:
      200140:   46c0        nop         ; (mov r8, r8)
      200142:   46c0        nop         ; (mov r8, r8)
      200144:   46c0        nop         ; (mov r8, r8)
      200146:   46c0        nop         ; (mov r8, r8)
      200148:   3901        subs    r1, #1
      20014a:   d1f9        bne.n   200140 <inner>
    
    000
    
    00070004
    
    001
    
    00080003
    
    002
    
    00090003
    
    202
    
    00070004
    
    ram
    
    00070003
    

    所以单独使用 ITCM,零等待状态,ART 关闭是每循环 7 个时钟,对于 6 条指令 用一个分支循环。似乎有道理。对于这个小测试,开启 ART 并有 2 个等待状态让我们回到每个循环 7 个。

    请注意,从 ram 开始,此代码也以每个循环 7 次运行。让我们试试另一对

    00F
    
    00230007
    
    20F
    
    00070004
    

    我没有寻找除 BTAC 之外的其他分支预测器

    首先要注意的是,您不想让 MCU 运行得比您必须的更快,会消耗电力,许多您需要添加闪存等待状态,许多 CPU 和外围设备具有不同的最大时钟速度,因此存在界限它变成非线性的(以慢时钟速率占用 X 个时钟周期,外围时钟 = CPU 时钟,有一个地方 N 倍快是 N X 个时钟来做某事,但它需要一个或多个边界当 CPU 时钟快 N 倍时,多于 NX 做某事)。这个特定的部分有这个非线性问题。如果您使用 ST 的库来设置时钟,那么您可能会遇到最坏的闪存等待状态,如果您设置它并阅读文档,您可能会刮掉一两个/几个。

    Cortex-M7 有可选的 L1 缓存,这次没有搞砸它,但 ST 在这些东西出来之前就有这个 ART 东西,我相信他们至少会打败/禁用 i 缓存,它会变得更好还是更糟糕的是两者兼而有之?如果它拥有它,那么即使在 AXIM 空间中,第一个过去的速度也会变慢,然后剩下的速度可能会更快。欢迎您尝试一下。似乎记得他们在处理器内核上做了一些棘手的事情,很难看出它是如何被打败的,而且可能不是这个芯片/内核,但绝对是 ST。 M4没有缓存,所以它必须是我弄乱的M7(特别是这个)。

    因此,简短的回答是,如果您不使用 ART 和/或用完 AXIM,性能不会那么糟糕。 ST 实施了闪存,使得 ITCM 接口比 AXIM 更快。如果您启用分支预测,我们可以看到 ARM 获取自身的效果,如果您打开它,您也可以看到。

    创建一个不符合这些功能的基准应该不难,就像您可以创建一个使 L1 缓存(或任何其他缓存)损害性能的基准一样。 ART 与任何其他缓存一样,会降低性能的可预测性,并且当您更改代码、添加一行、删除一行时,性能可能会从无变化到很多变化。

    根据处理器和获取大小和对齐方式,您的代码性能可能会因在项目的性能敏感部分上方添加或删除代码而有所不同,但这取决于我们很少能看到的一些因素。

    很难说他们声称 ART 会降低功率。我希望它能够增加这些 sram 的开启/计时功能。如果您关闭闪光灯并从 ram 运行,则看不到明显节省了多少。 M7 部件并不是真正意义上的低功率部件,如一些 STM32L 部件,您可以达到几微安/几十微安(微不是毫,已经做到了)。

    少量时钟 0x70004 而不是 0x70000 与一些获取开销有关,无论是 ARM 还是 ST 或两者的组合。要查看内存/闪存性能,您需要禁用尽可能多的功能,例如分支预测、可以禁用的缓存等。否则,很难衡量性能,然后对闪存/内存/总线的功能做出假设。我怀疑还有一些东西我没有关闭以进行干净的测量,和/或无法关闭。简单的 nop 循环(尝试了其他非 nop 指令,没有改变它)不会告诉你一切。使用文档作为指南,您可以尝试缓存 ART 或其他内容,看看会发生什么样的命中。

    对于性能关键代码,您可以从 RAM 运行并避免所有这些问题,我没有搜索它,但假设这些部分 SRAM 可以像 CPU 一样快地运行。答案不是在我身上跳出来,你自己想办法。

    注意我的测试实际上看起来像

        ldr r2,[r0]
    inner:
        nop
        nop
        nop
        nop
        sub r1,#1
        bne inner
        ldr r3,[r0]
        sub r0,r2,r3
        bx lr
    

    systick 的采样就在前面和后面。分店前。要测量 ART,您需要对尚未读取的内存范围的分支之前的时间进行采样,因此不可能神奇地读取速度更快,第一次读取缓存应该更慢。如果我将时间采样移得更远,我可以看到它从 0x7000A 变为 0x70027,用于 0 到 15 个等待状态,同时开启 ART。对于分支到尚未运行/缓存的代码来说,这是一个明显的性能损失。知道艺术提取的大小,应该很容易进行跳跃很多的测试,并且艺术特征开始变得无关紧要。


    简短的回答,ITCM 是 ARM 内核上的不同总线接口,ST 已经实现了他们的设计,从而提高了性能。因此,即使没有启用 ART,使用 ITCM 也比 AXIM 更快(可能是 ARM 总线而不是 ST 闪存)。如果您运行的时钟频率足够快,不得不向闪存添加等待状态,那么 ART 基本上可以擦除这些。

    【讨论】:

    • 我是否正确阅读了这些数字 (00F/00230007/ 20F/00070004),禁用 ART 会导致 15 个等待状态的简单循环的性能下降 5 倍?对于使用 F7 频率为 216 MHz 的用户来说,这将是一个重要的结果。
    • 否,如果您查看 216 处的表格,则取决于您的电压范围,您处于 7,8 或 9 个等待状态。 (图书馆可以告诉我,所以我假设 9)。同时,是的,您必须添加等待状态才能快速运行,但与 AXIM 相比,ITCM 仍然会明显更快,根据文档和上述实验假设。 15 是为了演示目的而完成的。处理器将以非常高的速率消耗这 4 或 8 条指令,而不是等待状态更少的速度更慢。然后可能还有一个 l1 缓存......
    • 是的,使用 15 演示了 ART,但即使使用 ART,我也演示了它不是隐含的魔法,你不会有效地获得 0 等待状态性能,只有在重新运行的代码上,我会期望它与 L1 缓存相提并论,ART 基本上是 L2 缓存,如果 ST 以某种方式设计它,它可能比 L1 更快(如果在这些部分中实现 L1),他们控制 ART 和闪存几何/界面。
    • 从问题开始(对我来说)在 AXIM 上开始然后仅仅因为 ART 关闭而切换。似乎您可以随时打开 ART,当您在运行时更改 nDBANK 时,有停止/清除 ART 的程序。如果您想使用 ART,则将性能敏感代码放入该地址范围并启用它。如果您不使用它运行仍然优于 AXIM。如果闪存足够大,则任何不适合 ITCM 的代码都需要在 0x08000000 范围内,并为该空间构建或构建。
    【解决方案2】:

    我认为这个问题比其他答案所假设的要简单得多。

    如果您正在考虑做一些事情,例如将您的程序放在其他地方而不是简单地放在闪存中:不要。正如 ST 所说:使用 ART,性能将非常接近“零等待状态”。所以不用担心。您尝试做的任何其他事情都不会比这更快。

    【讨论】:

      【解决方案3】:

      问。如果我将我的程序代码从 0x0200 0000 开始,如果没有启用 ART 加速器会发生什么?

      A.程序执行(指令获取和持续访问)会非常缓慢,等待周期数非常多(15 个?)。

      [ 更新。我必须纠正这更多地适用于具有高时钟频率的配置,例如216 MHz 需要 15 个等待状态。对于较低的频率,闪存访问代价将不那么显着,并且在 16 MHz 时最小。我们不知道 O.P. 使用什么频率]

      [ UPD2。在 216 MHz 上最多需要 9 个等待状态,抱歉。 ]

      问。哪种总线更适合闪存代码访问,AXI 还是 ITCM?

      A.您提到的大量文档包括一些性能测量,还比较了各种代码放置选项。由于高速缓存大小和总线宽度不同,处理器型号之间的结果有些不同。您的代码可能会受到不同的影响。我从本文中得出的结论是,除非您的代码对性能至关重要,否则这两个选项都可以正常工作。但是,拥有两条带缓存的并行总线使您能够进行创造性的操作,例如将代码分成多个片段并将它们分配到单独的总线上,这样关键但很少使用的代码就不会从缓存中清除。我的意思是,如果你真的需要的话。

      【讨论】:

        猜你喜欢
        • 2021-04-26
        • 2021-02-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多