繁体   English   中英

ARM Cortex M 中的 ISB 指令

[英]ISB instruction in ARM Cortex M

到目前为止,我使用 3 个 NOP 来“清理”管道。 最近我遇到了为我做这件事的 ISB 指令。 查看 arm 信息中心,我注意到此命令需要 4 个周期(在 Cortex M0 下),而 3 个 NOP 只需要 3 个。

我为什么要使用这个命令? 它与 3 NOP 有什么不同?

这是 NOP 的问题( http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0552a/CHDJJGFB.html ):

手术

NOP 不执行任何操作,并且不保证一定是耗时的。 处理器可能会在它到达执行阶段之前将其从管道中删除。

使用 NOP 进行填充,例如将后续指令放置在 64 位边界上。

其他 ARM Cortex 设备的文档中也有相同的信息,因此将该指令用于填充以外的任何目的根本不可靠。 您唯一的保证是该指令将占用 2 ( nop ) 或 4 个字节 ( nop.w ) 并且它不会执行任何操作——仅此而已。

您应该使用 ISB 指令来确保管道清晰。 正如上面的评论所述,不同 ARM 处理器之间的流水线可能不同(例如,M7 具有 6 级流水线,而 M3/4 为 3 级)。 根据 M4 技术参考手册“对于 ISB,最小周期数相当于管道重新填充所需的数量。”。

我不确定为什么这是 4 个周期而不是 3 个周期,这可能与确保分支预测逻辑正确有关。 无论您是否希望您的代码可移植,我都会建议使用 ARM 为这项工作提供的内容,如果他们认为您需要 4 个周期,那么我希望您这样做。 如果您只有 3 个,则在某些情况下可能会出现错误操作。

ISB 指令是 4 个周期的原因很简单。 Cortex-M 指令集是 16 位和 32 位指令的混合体。 Cortex-M 设计(例如 Cortex-M0)支持 6 条 32 位指令:BL、MSR、MRS、ISB、DMB、DSB。

所有这六个指令都可以在 16 位指令中混合使用。

问题是处理器如何知道哪条指令是 16 位的,哪一条是 32 位的? 为了回答这个问题,处理器读取前 16 位并对其进行解码(1 个周期)。 如果操作码与 32 位指令匹配,则它知道下一个 16 位指令实际上是 32 位指令的后半部分,并尝试执行它(3 个周期)。

这使得 Cortex-M 内核中的所有 32 位指令为 1+3 个周期 = 4 个周期。

要刷新管道,如果您确定核心实现,您可以使用 3 个 NOP。 您必须确保核心没有分支预测和即时指令优化,该优化删除了连续的 NOP。 如果您确定没有此功能,则使用 3 个 NOP 指令,您将节省 1 个周期。 但是如果你不使用并且你也希望你的 ARM 代码可以移植到其他架构,比如 ARMv7 等,那么你必须使用 ISB 指令,它是一条 32 位指令,需要 4 个周期。

3 个 NOP 不能保证消耗 3 个周期。 在某些情况下,它们会在 Cortex-M3 上消耗 2 个周期 - 在这些情况下,您可能需要使用 3 个以上的 NOP 才能获得所需的效果。

“有趣”的场景很可能不会出现在公共代码中,或者还需要其他事件的特定时间——因此您可能不太可能观察到它们。 关键是没有保证,这种故障的可观察性通常很低。

即使您在某处错误地仅使用了 2 个 NOP,您的代码也可能大部分时间都在工作 - 直到其他地方的更改可能会影响对齐并导致失败。

关于“清理”管道的权威信息在这里:

“ARM Cortex™-M Memory 屏障指令编程指南”应用笔记 321

它适用于:Cortex-M3、Cortex-M4、Cortex-M0、Cortex-M0+ 和 Cortex-M1 处理器。

如何清理管道取决于正在使用的指令,例如,__enable_irq()、__WFI()(睡眠)等。

据我所知,该文档没有提到使用 NOP 来清理管道。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM