ARM ITCM 接口和闪存访问
ARM ITCM interface and FLash access
If the access to the Flash memory is done starting from the address 0x0200 0000, it is performed automatically via the ITCM bus. The ART accelerator™ should be enabled to get the equivalent of 0-wait state access to the Flash memory via the ITCM bus. The ART is enabled by setting the bit 9 in the FLASH_ACR register while the ART-Prefetch is enabled by setting the bit 8 in the same register.
如果我将我的程序代码从 0x0200 0000 开始,如果没有启用 ART 加速器会发生什么情况?只使用 AXIM 总线代替启动代码然后启用 ART 加速器并将执行指向位于 0x0200 0000 的程序区域是否有益。
我只是有点困惑。
第 12 页
问。如果我把我的程序代码从 0x0200 0000 开始,如果没有启用 ART 加速器会发生什么?
一个。程序执行(指令获取和持续访问)将非常缓慢,等待周期数量惊人(15?)。
[更新。我必须更正,这更适用于具有高时钟频率的配置,例如216 MHz 需要 15 个等待状态。使用较低的频率,闪存访问损失将不那么明显,并且在 16 MHz 时最小。我们不知道 O.P 使用什么频率。 ]
[UPD2。抱歉,216 MHz 最多需要 9 个等待状态。 ]
问。哪种总线更适合闪存代码访问,AXI 还是 ITCM?
一个。您提到的大量文档包括一些性能测量,还比较了各种代码放置选项。由于高速缓存大小和总线宽度不同,处理器型号之间的结果略有不同。您的代码可能会受到不同的影响。我从本文中得出的结论是,除非您的代码对性能至关重要,否则这两种选择都可以很好地工作。然而,拥有两条带缓存的并行总线使您能够做一些创造性的事情,比如将代码分成几部分并将它们分配给单独的总线,这样关键但很少使用的代码就不会从缓存中被逐出。我的意思是,如果你真的需要它。
所以让我们试试吧。 NUCLEO-F767ZI
一般的 Cortex-M7s:
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 位表示单个存储区
Instruction prefetch
In case of single bank mode (nDBANK option bit is set) 256 bits representing 8 instructions of 32 bits to 16 instructions of 16 bits according to the program launched. So, in the case of sequential code, at least 8 CPU cycles are needed to execute the previous instruction line read.
所以 ST 将把它变成 256 位或 16 条指令
使用系统计时器。 运行正在以 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
因此对于 6 条指令,仅 ITCM,零等待状态,ART 关闭是每个循环 7 个时钟
用一个分支循环。似乎有道理。对于这个微小的测试,打开具有 2 个等待状态的 ART 使我们回到每个循环 7 个。
请注意,从 ram 开始,这段代码 运行s 也是每个循环 7 次。让我们再试一对
00F
00230007
20F
00070004
除了 BTAC
,我没有寻找其他分支预测器
首先要注意的是,您不希望 运行 MCU 比您必须的速度更快,消耗功率,许多您需要添加闪存等待状态,许多 CPU 和外围设备有不同的最大时钟速度,所以有一个边界,它变得非线性(以低时钟速率需要 X 个时钟周期,外设时钟 = CPU 时钟,有一个地方快 N 倍是 NX 时钟来做某事,但一个或多个边界,当 CPU 时钟快 N 倍时,它需要 NX 来做某事)。这个特定的部分有这个非线性问题。如果您使用 ST 的库来设置时钟,那么您可能会遇到最坏的闪存等待状态,如果您设置它并阅读文档,您可能会刮掉一个或 two/few.
Cortex-M7 有可选的 L1 缓存,这次没有弄乱它,但 ST 在这些出现之前就有了这个 ART 东西,我相信它们至少 defeat/disable i 缓存,会吗两者兼有是好是坏?如果它有它,那么即使在 AXIM space 中,这也会使第一个过去变慢,然后剩下的可能更快。欢迎您尝试。似乎记得他们在处理器核心上做了一些棘手的事情,很难看出它是如何被击败的,那可能不是这个 chip/core 但绝对是 ST。 M4 没有缓存,所以它必须是我弄乱的 M7(尤其是这个)。
所以简短的回答是,如果您将 ART and/or 运行 排除在 AXIM 之外,性能并不会那么糟糕。 ST 已实现闪存,因此 ITCM 接口比 AXIM 更快。如果您启用分支预测,我们可以看到 ARM 获取自身的效果,如果您打开它,您也可以看到它。
创建一个击败这些功能的基准应该不难,就像您可以创建一个使 L1 缓存(或任何其他缓存)损害性能的基准一样。与任何其他缓存一样,ART 使性能更难预测,并且当您更改代码、添加一行、删除一行时,性能可能会从无变化跳到很多地方。
根据处理器和提取大小和对齐方式,您的代码性能可能会因在项目的性能敏感部分之上添加或删除代码而有所不同,但这取决于我们很少了解的一些因素。
很难说他们声称 ART 会降低功耗。我希望它能增加那些 srams on/clocked 的功率。如果关闭闪光灯并从 ram 中 运行,则看不到明显节省多少。 M7 部件并不是像某些 STM32L 部件那样的低功率部件,在那里你可以达到 ones/tens 微安(微安而不是毫安,已经做到了)。
时钟 0x70004 而不是 0x70000 的少量时钟与一些获取开销有关,无论是 ARM 还是 ST 或两者的组合。要查看 memory/flash 性能,您需要禁用尽可能多的功能,例如分支预测、可以禁用的缓存等。否则,很难衡量性能,然后对 flash/memory/bus 正在做什么做出假设.我怀疑还有一些东西我没有关闭以进行干净的测量,and/or 无法关闭。简单的 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 打开。对于尚未 run/cached 的代码分支来说,这是一个明显的性能损失。知道 art fetch 的大小,应该很容易进行跳跃很多的测试,ART 功能开始变得无关紧要。
简短回答,ITCM 是 ARM 内核上的一个不同的总线接口,ST 已经实现了他们的设计,从而提高了性能。因此,即使没有启用 ART,使用 ITCM 也比 AXIM 更快(可能是 ARM 总线而不是 ST 闪存)。如果您 运行 时钟速率足够快,必须向闪存添加等待状态,那么 ART 几乎可以擦除这些。
我认为这个问题比其他答案假设的要简单得多。
如果您正在考虑将您的程序放在别处而不是简单地放在 Flash 中:不要这样做。正如 ST 所说:使用 ART,性能将非常接近 "zero wait state"。所以不用担心。您尝试做的任何其他事情都不会比这更快。
If the access to the Flash memory is done starting from the address 0x0200 0000, it is performed automatically via the ITCM bus. The ART accelerator™ should be enabled to get the equivalent of 0-wait state access to the Flash memory via the ITCM bus. The ART is enabled by setting the bit 9 in the FLASH_ACR register while the ART-Prefetch is enabled by setting the bit 8 in the same register.
如果我将我的程序代码从 0x0200 0000 开始,如果没有启用 ART 加速器会发生什么情况?只使用 AXIM 总线代替启动代码然后启用 ART 加速器并将执行指向位于 0x0200 0000 的程序区域是否有益。
我只是有点困惑。
第 12 页
问。如果我把我的程序代码从 0x0200 0000 开始,如果没有启用 ART 加速器会发生什么?
一个。程序执行(指令获取和持续访问)将非常缓慢,等待周期数量惊人(15?)。
[更新。我必须更正,这更适用于具有高时钟频率的配置,例如216 MHz 需要 15 个等待状态。使用较低的频率,闪存访问损失将不那么明显,并且在 16 MHz 时最小。我们不知道 O.P 使用什么频率。 ]
[UPD2。抱歉,216 MHz 最多需要 9 个等待状态。 ]
问。哪种总线更适合闪存代码访问,AXI 还是 ITCM?
一个。您提到的大量文档包括一些性能测量,还比较了各种代码放置选项。由于高速缓存大小和总线宽度不同,处理器型号之间的结果略有不同。您的代码可能会受到不同的影响。我从本文中得出的结论是,除非您的代码对性能至关重要,否则这两种选择都可以很好地工作。然而,拥有两条带缓存的并行总线使您能够做一些创造性的事情,比如将代码分成几部分并将它们分配给单独的总线,这样关键但很少使用的代码就不会从缓存中被逐出。我的意思是,如果你真的需要它。
所以让我们试试吧。 NUCLEO-F767ZI
一般的 Cortex-M7s:
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 位表示单个存储区
Instruction prefetch
In case of single bank mode (nDBANK option bit is set) 256 bits representing 8 instructions of 32 bits to 16 instructions of 16 bits according to the program launched. So, in the case of sequential code, at least 8 CPU cycles are needed to execute the previous instruction line read.
所以 ST 将把它变成 256 位或 16 条指令
使用系统计时器。 运行正在以 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
因此对于 6 条指令,仅 ITCM,零等待状态,ART 关闭是每个循环 7 个时钟 用一个分支循环。似乎有道理。对于这个微小的测试,打开具有 2 个等待状态的 ART 使我们回到每个循环 7 个。
请注意,从 ram 开始,这段代码 运行s 也是每个循环 7 次。让我们再试一对
00F
00230007
20F
00070004
除了 BTAC
,我没有寻找其他分支预测器首先要注意的是,您不希望 运行 MCU 比您必须的速度更快,消耗功率,许多您需要添加闪存等待状态,许多 CPU 和外围设备有不同的最大时钟速度,所以有一个边界,它变得非线性(以低时钟速率需要 X 个时钟周期,外设时钟 = CPU 时钟,有一个地方快 N 倍是 NX 时钟来做某事,但一个或多个边界,当 CPU 时钟快 N 倍时,它需要 NX 来做某事)。这个特定的部分有这个非线性问题。如果您使用 ST 的库来设置时钟,那么您可能会遇到最坏的闪存等待状态,如果您设置它并阅读文档,您可能会刮掉一个或 two/few.
Cortex-M7 有可选的 L1 缓存,这次没有弄乱它,但 ST 在这些出现之前就有了这个 ART 东西,我相信它们至少 defeat/disable i 缓存,会吗两者兼有是好是坏?如果它有它,那么即使在 AXIM space 中,这也会使第一个过去变慢,然后剩下的可能更快。欢迎您尝试。似乎记得他们在处理器核心上做了一些棘手的事情,很难看出它是如何被击败的,那可能不是这个 chip/core 但绝对是 ST。 M4 没有缓存,所以它必须是我弄乱的 M7(尤其是这个)。
所以简短的回答是,如果您将 ART and/or 运行 排除在 AXIM 之外,性能并不会那么糟糕。 ST 已实现闪存,因此 ITCM 接口比 AXIM 更快。如果您启用分支预测,我们可以看到 ARM 获取自身的效果,如果您打开它,您也可以看到它。
创建一个击败这些功能的基准应该不难,就像您可以创建一个使 L1 缓存(或任何其他缓存)损害性能的基准一样。与任何其他缓存一样,ART 使性能更难预测,并且当您更改代码、添加一行、删除一行时,性能可能会从无变化跳到很多地方。
根据处理器和提取大小和对齐方式,您的代码性能可能会因在项目的性能敏感部分之上添加或删除代码而有所不同,但这取决于我们很少了解的一些因素。
很难说他们声称 ART 会降低功耗。我希望它能增加那些 srams on/clocked 的功率。如果关闭闪光灯并从 ram 中 运行,则看不到明显节省多少。 M7 部件并不是像某些 STM32L 部件那样的低功率部件,在那里你可以达到 ones/tens 微安(微安而不是毫安,已经做到了)。
时钟 0x70004 而不是 0x70000 的少量时钟与一些获取开销有关,无论是 ARM 还是 ST 或两者的组合。要查看 memory/flash 性能,您需要禁用尽可能多的功能,例如分支预测、可以禁用的缓存等。否则,很难衡量性能,然后对 flash/memory/bus 正在做什么做出假设.我怀疑还有一些东西我没有关闭以进行干净的测量,and/or 无法关闭。简单的 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 打开。对于尚未 run/cached 的代码分支来说,这是一个明显的性能损失。知道 art fetch 的大小,应该很容易进行跳跃很多的测试,ART 功能开始变得无关紧要。
简短回答,ITCM 是 ARM 内核上的一个不同的总线接口,ST 已经实现了他们的设计,从而提高了性能。因此,即使没有启用 ART,使用 ITCM 也比 AXIM 更快(可能是 ARM 总线而不是 ST 闪存)。如果您 运行 时钟速率足够快,必须向闪存添加等待状态,那么 ART 几乎可以擦除这些。
我认为这个问题比其他答案假设的要简单得多。
如果您正在考虑将您的程序放在别处而不是简单地放在 Flash 中:不要这样做。正如 ST 所说:使用 ART,性能将非常接近 "zero wait state"。所以不用担心。您尝试做的任何其他事情都不会比这更快。