为什么在Cortex-M FreeRTOS的WFI之后需要ISB



当使用依赖于 WFI 指令的无时钟空闲功能时,我在 FreeRTOS 的 Cortex-M 端口中看到以下行

__asm volatile( "dsb" );
__asm volatile( "wfi" );
__asm volatile( "isb" );

见 https://github.com/cjlano/freertos/blob/V9.0.0/FreeRTOS/Source/portable/GCC/ARM_CM3/port.c#L530

我看到根据 ARM Cortex-M 内存屏障指令编程指南文档:"在执行 WFI 或 WFE 指令之前,应使用 DSB 来确保没有未完成的内存事务。

但我很好奇为什么这里需要 ISB?也许这确保了从 WFI 唤醒芯片的中断在管道中可能存在的任何进一步指令之前立即执行?这是我最好的猜测,但想听听任何其他想法或确认。

我相信

ISB的意图是确保wfi指令"按顺序"执行,并且在它被唤醒之前没有指令被执行。也就是说,我认为根据 ARM 文档不需要它。我怀疑这是腰带和牙套的方法。

ISB 被添加到 WFI 之后,因为程序员希望确保 WFI 应该在 WFI 之后的任何指令之前执行。ARM还具有支持乱序执行的A级内核。如果我们通过删除无序内核上的 ISB 来运行上述代码,则遵循 WFI 的指令可能会在 WFI 之前执行。

ISB 指令将导致流水线在某个时候被刷新,它的一个用例是强制指令执行的顺序,基于如果我们在 WFI 之后有一个指令,我们可能希望 WFI 在下一条指令之前真正执行,特别是对于支持无序执行模型或超标量的更复杂的 arm 处理器,我们可能会在 WFI 被获取并馈送到处理器管道已经存在,这里的一种解决方法是使用 ISB 刷新导致执行 WFI 的管道,从而触发 CPU 进入睡眠模式,我们保证下一条指令不会被执行

ISB 指令刷新管道并确保所有在执行新指令之前,先完成先前的指令。

来自 ARM cortex-M3 指南。

DSB 和 ISB 指令对于自修改代码可能很重要。例如,如果一个程序 改变自己的程序代码,下一个执行的指令应该基于更新的程序。 但是,由于处理器是流水线的,因此修改后的指令位置可能已经 获取。使用 DSB 和 ISB 可以确保再次获取修改后的程序代码。 从体系结构上讲,应在更新 CONTROL 寄存器的值后使用 ISB 指令。在 Cortex-M3 处理器中,这不是严格要求的。但是,如果要确保应用程序是可移植的,则应确保在更新到CONTROL寄存器后使用ISB指令。

相关内容

最新更新