ARM Cortex M4处理器上的DSB

ARM Cortex M4处理器上的DSB,arm,Arm,我已经阅读了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

我已经阅读了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(); 
}
本节列举了可能影响重新排序的因素

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

  • 处理器有多个总线接口

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

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

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


您经常会发现,短管道和指令序列的组合方式可能会使特定编译映像无法达到竞争条件,但这不是您可以依赖的。定时条件可能很少(但可能),或者后续的代码更改可能会更改生成的指令序列。

嗯,这取决于您的标志是什么,而且它也因芯片而异

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

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

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

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

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

  • 写入
    flag=1
    以清除已处理的中断
  • 您可以通过调用
    \uu enable\u irq()
  • 中断被启用,写入标志=1仍处于挂起状态
  • 当中断被挂起时,CPU跳转到中断处理程序
  • flag=1
    生效。您现在处于中断处理程序中,无需执行任何操作
\uuu enable\u irq()
前面执行DSB将防止此问题,因为
标志=1
触发的任何内容都将在
\uu enable\u irq()
执行之前生效

如果你认为这个案子纯粹是学术性的:不,它是真实的

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

但是,同样的事情也可能发生在速度较慢的外围设备上


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

我在ARM文档中读到了一些内容。包括这一点,因为我的处理器是单核的,即使有缓存,它也不会重新排序内存访问或指令。然而,同时建议使用DSB和ISB,以使代码更便于将来的处理器移植。我还阅读了上面的类似链接,指出内存访问可能出现无序情况,特别是当内存上存在等待状态时。当然,在这样的情况下,单cpu的DSB/ISB不仅仅是为了可移植性。您是否有在单核M4上使用DMB、DSB、ISB的示例?启用FPU,对MPU进行编程,更改SP。不总是这样,但是如果您尝试,您可以找到案例。DSB的这种使用听起来很有用。我想知道内核如何知道跨时钟域的写操作发生了?Nils,您的部分启用了数据缓存了吗?@tramp因为该部分只有代码缓存来补偿小闪存。RAM片上SRAM,因此不需要缓存。因此,我猜通过ARM指令管道,它暂停了到外围设备的总线,但仍然可以退出中断服务处理程序。因此需要DMB。我知道Atmel对他们的外设做了一些疯狂的事情,并且由于时钟的差异而有本地同步位。我认为他们可能有一个以核心速度运行的寄存器本地缓存,然后外围设备更新会在稍后发生。我认为关键是:如果你写多个寄存器,大多数时候你只关心顺序,而不关心写入生效的确切时刻。因此,如果您将逻辑放入芯片,并在每次写入时在时钟域上进行同步,您将为每次外围访问支付罚款。在最后有一个DMB只解决了一个暂停的问题。请注意,我问这个问题是因为我看到的所有示例代码都没有在uu disable_irq()和u enable_irq()之前使用DBM。所以我想知道它是否应该在那里?我也想知道是什么