STM32 阻塞延迟与中断禁用不一致

STM32 blocking delays not consistent with interrupts disabled

我 运行 在 STM32F0xx micro 上,我有以下代码,它使用阻塞延迟简单地切换引脚(是的,我知道阻塞延迟很糟糕,这里没有指出)。

uint32_t ticks = 0;
// Disable interrupts
__disable_irq();
for (int bit = 0; bit < 10; bit++) {
  // Toggle pin high
  WritePin(GPIO_PIN_SET);
  ticks = 500;
  while (ticks--) {
    __NOP();
  }
  // Toggle pin low
  WritePin(GPIO_PIN_RESET);
  ticks = 500;
  while (ticks--) {
    __NOP();
  }
  // Repeat
  WritePin(GPIO_PIN_SET);
  ticks = 500;
  while (ticks--) {
    __NOP();
  }
  WritePin(GPIO_PIN_RESET);
  ticks = 500;
  while (ticks--) {
    __NOP();
  }
}
__enable_irq();

我禁用中断以确保此时没有其他事情发生。当我观察这些波形时,我看到了 10 个时钟周期;然而,这些波形的周期并不完全匹配。所有偶波形 (0,2,4,6,8) 具有相同的周期,所有奇波形 (1,3,5,7,9) 具有相同的周期,但偶波形和奇波形相差很大(%12)。偶数波形与 for 循环中的第一个延迟切换相关,奇数与第二个延迟切换相关。我不知道为什么这些时间会有所不同。有人对此有任何见解吗?

请参阅有关 NOP 在 ARM Cortex-M0 内核上的文档:

http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0497a/CHDJJGFB.html

Operation

NOP performs no operation and is not guaranteed to be time consuming. The processor might remove it from the pipeline before it reaches the execution stage.

Use NOP for padding, for example to place the subsequent instructions on a 64-bit boundary.

为此,您必须添加其他变化因素,如管道重新填充(由于分支)和闪存 wait-states(变化,因为不同循环中的指令块可能无法针对闪存加速器完美对齐)。

执行精确延迟的唯一可靠方法是使用计时器。