【问题标题】:DSB on ARM Cortex M4 processorsARM Cortex M4 处理器上的 DSB
【发布时间】:2018-12-04 08:59:51
【问题描述】:

我已阅读 ARM 文档,似乎他们在某些地方说 Cortex M4 可以重新排序内存写入,而在其他地方则表明 M4 不会。

具体来说,我想知道是否需要 DBM 指令,例如:

volatile int flag=0; 
char buffer[10]; 
void foo(char c)
{     
      __ASM volatile ("dbm" : : : "memory");
      __disable_irq(); //disable IRQ as we use flag in ISR
    buffer[0]=c;
    flag=1;
      __ASM volatile ("dbm" : : : "memory");
      __enable_irq(); 
}

【问题讨论】:

  • 注意我问这个问题是因为我看到的所有示例代码在 __disable_irq() 和 __enable_irq() 之前都没有使用 DBM。所以我想知道它是否应该在那里?我也想知道什么时候应该使用 DBM。

标签: arm


【解决方案1】:

呃,这取决于你的flag是什么,而且它也因芯片而异。

如果该标志存储在内存中:

这里不需要DSB。访问标志的中断处理程序必须首先从内存中加载它。即使您之前的写入仍在进行中,CPU 也会确保存储之后的加载将以正确的顺序发生。

如果您的标志存储在外围存储器中:

现在变得有趣了。让我们假设标志位于某些硬件外围设备中。对它的写入可能会使中断挂起或确认中断(也就是清除挂起的中断)。与上面的内存示例相反,这种效果在 CPU 不必先读取标志的情况下发生。所以商店和装载的自动排序不会帮助你。此外,由于 CPU 和外设之间的时钟域不同,写入标志可能会以惊人的长延迟生效。

因此可能会发生以下情况:

  • 您编写 flag=1 以清除已处理的中断。
  • 您可以通过调用__enable_irq() 来启用中断
  • 中断已启用,对 flag=1 的写入仍处于挂起状态。
  • 哇,一个中断挂起,CPU 跳转到中断处理程序。
  • flag=1 生效。您现在处于中断处理程序中,无事可做。

__enable_irq() 前面执行一个DSB 可以防止这个问题,因为flag=1 触发的任何东西都会在__enable_irq() 执行之前生效。

如果你认为这个案例纯粹是学术性的:不,这是真的。

想想实时时钟。这些通常以 32khz 运行。如果您从以 64Mhz 运行的 CPU 写入其外围空间,则可能需要高达 2000 个周期才能使写入生效。现在对于实时时钟,数据表通常会显示特定的序列,以确保您不会遇到这个问题。

但是,慢速外围设备也会发生同样的事情。

我的个人轶事是在项目后期实施节电时发生的。一切正常。然后,我们将 I²C 和 SPI 外设的外设时钟速度降低到我们可以避免的最低速度。这可以节省大量电力并延长电池寿命。我们发现突然间中断开始做意想不到的事情。他们似乎每次都会开火两次,造成严重破坏。在每个受影响的中断处理程序的末尾放置一个 DSB 解决了这个问题,因为 - 您可以猜到 - 由于外围时钟速度较慢,较低的时钟速度导致我们在清除中断源之前离开中断处理程序。

【讨论】:

  • 这种使用 DSB 听起来不错。我想知道核心是如何知道跨时钟域的写入发生的?
  • Nils,您的部件是否启用了数据缓存?
  • @Trampas 该部分仅用于代码缓存以补偿小闪存。 RAM 片上 SRAM,因此不需要缓存。
  • 所以我猜想使用 ARM 指令流水线会停止到外围设备的总线,但它仍然可以退出中断服务处理程序。因此需要DMB。我知道 Atmel 对其外围设备做了一些疯狂的事情,并且由于时钟差异而具有本地同步位。我认为他们可能有一个以核心速度运行的寄存器的本地缓存,然后外围更新发生。
  • @Trampas 我认为重点是:如果你写多个寄存器,大多数时候你只关心顺序,而不是写入生效的确切时间。因此,如果您将逻辑放入芯片并在每次写入时在时钟域上进行同步,您将为每次外设访问付出代价。最后有一个 DMB 解决了只有一个档位的问题。
【解决方案2】:

Cortex M4 generic device user guide 的这一部分列举了可能影响重新排序的因素。

  • 处理器可以重新排序一些内存访问以提高效率,前提是这不会影响指令序列的行为。

  • 处理器有多个总线接口

  • 内存映射中的内存或设备具有不同的等待状态

  • 一些内存访问是缓冲的或推测的。

您还应该记住,DSB 和 ISB 通常都是必需的(按此顺序),并且 C 不对顺序做出任何保证(线程内 vol​​atile 访问除外)。

您经常会观察到,短流水线和指令序列可以以这样的方式组合,使得竞争条件似乎无法通过特定的编译映像达到,但这不是您可以依赖的。时序条件可能很少(但可能),或者后续代码更改可能会更改生成的指令序列。

【讨论】:

  • 我已经阅读了 ARM 文档中的一些内容。包括这一点,因为我的处理器是单核,即使有缓存,它也不会重新排序内存访问或指令。但是,同时建议使用 DSB 和 ISB,以使代码对未来的处理器更具可移植性。我也读过类似上面的链接,内存访问可能发生乱序,尤其是当您在内存上有等待状态时。
  • 肯定有像这样的单 CPU 场景,其中 DSB/ISB 不仅仅是为了便携性。
  • 您有在单核 M4 上应使用 DMB、DSB、ISB 的示例吗?
  • 启用 FPU,对 MPU 进行编程,更改 SP。并非总是如此,但如果您尝试,您可以找到案例。
猜你喜欢
  • 2020-01-10
  • 2017-06-23
  • 1970-01-01
  • 2017-01-20
  • 2012-07-16
  • 2018-09-29
  • 2017-12-03
  • 2016-10-16
  • 1970-01-01
相关资源
最近更新 更多