首页 > 解决方案 > 启用外设定时器和定时器实际开始计数之间是否有延迟?这是什么延迟,是什么原因造成的?

问题描述

我正在尝试配置一个计时器(TIM9)及其中断处理程序以单步执行程序。我的方法是先中断第一条指令,然后在中断处理程序中配置定时器,使其在从 ISR 返回后立即触发中断。

现在,我仍在尝试正确迈出第一步。

这是我现在正在使用的示例代码。我已将定时器配置为在其计数器等于某个比较值时生成中断。我将比较值设置为 1,以便代码在定时器的 1 个周期后被中断。根据参考手册,计数器在设置启用位后开始计数 1 个周期,所以我添加了一个 NOP。

  /*
   * TIM9 is configured to generate an interrupt when counter s equal to compare value
   */
  TIM9->CCR1 = 1;           // set compare 1 value to 1
  TIM9->CR1 |= 1;           // enable TIM9
  __ISB();                  // flush pipeline
  __asm volatile ("NOP");   // from reference manual: counter starts counting 1 cycle after setting CEN bit
  __asm volatile("MOV r8, #1 \n\t"); // expect to interrupt this instruction
  __asm volatile("MOV r8, #2 \n\t");
  __asm volatile("MOV r8, #3 \n\t");
  __asm volatile("MOV r8, #4 \n\t");

为了验证正确的指令是否被中断,我在进入中断处理程序后使用 GDB 检查寄存器 r8 的内容,我发现它实际上等于 6。这意味着延迟比 1 个周期长得多,或者我我只是错过了一些东西。

我可以简单地在第一条 MOV 指令之前添加 5 条 NOP 指令,以便在正确的时间发生中断,但我不明白为什么这是必要的。据我所知,我现在拥有的代码应该在第一条 MOV 指令期间产生一个中断。

为什么我会出现这种行为?为什么在启用定时器和产生中断之间似乎有这么长的延迟?

这可能是因为计数器值等于比较值与实际产生中断之间存在延迟吗?

或者这可能与管道的工作方式有关?

我已将定时器的预分频器设置为 0,并且没有发生内部时钟分频,因此定时器应该与系统时钟具有相同的频率。

标签: armstm32cortex-m

解决方案


我不知道你为什么要检查它。它按预期工作。

  1. NOP 是添加延迟的最坏方法。它与 8 位 AVR 的 NOP 不同。它会立即从管道中冲出,并且只能用作填充。
  2. CEN 之后的 1 个时钟表示一个定时器时钟,而不是 HCLK 时钟(它们可以相同)
  3. CCRx = 1 表示两个时钟。
  4. 如果您从 FLASH 运行 - 添加等待状态
  5. 管道执行状态不容易确定。被中断的实际指令不一定是您实际认为的指令。中断的时间是确定的,而不是实际的指令。

推荐阅读