启用外设定时器和定时器实际开始计数之间是不是有延迟?这是啥延迟,是啥原因造成的?

Posted

技术标签:

【中文标题】启用外设定时器和定时器实际开始计数之间是不是有延迟?这是啥延迟,是啥原因造成的?【英文标题】:Is there a delay between enabling a peripheral timer and the timer actually starting its count? What is this delay and what causes it?启用外设定时器和定时器实际开始计数之间是否有延迟?这是什么延迟,是什么原因造成的? 【发布时间】:2021-04-06 00:57:30 【问题描述】:

我正在尝试配置一个计时器 (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,并且没有发生内部时钟分频,因此定时器应该与系统时钟具有相同的频率。

【问题讨论】:

写入是一劳永逸的,从手臂远端的第一个总线控制器,它可能需要一个以上的时钟才能到达计时器以执行写入,同时手臂继续。并且处理器、总线和外围设备都可以以不同的时钟速率运行,从而使 cpu 时钟的数量比其他事务更快。然后可以将计时器配置为使用不同的时钟运行它是否运行比处理器慢的时钟。 这是流水线的,所以你不能假设一条指令需要一个时钟,不要误解任何 arm doc 中的任何时间。这是从闪存中获取的,很可能会增加更多潜在的延迟。在这种情况下,没有理由假设中断时间是确定的。如果您没有进行其他更改并且没有任何并行的内容,那么即使不太可能重复也是可能的,但是您可以进行微小的更改,包括以相同的顺序使用相同的机器代码并更改可重复的结果(相同的时钟,相同的所有其他内容) , 例如用半字改变对齐方式) 即使总线和外围设备在同一个时钟上,系统也会出现延迟。例如,创建一个写入控制寄存器的循环执行几千次并使用 systick 计时。如果您想避免分支的管道效应,请展开一些。 stm32s千差万别,一般指定芯片,arm,cortex-m,stm32,tim9,都太宽泛了 您是否保留了 r8 以便此代码不会将其丢弃? 【参考方案1】:

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

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

【讨论】:

这一切都是正确的。房间里的大象是 OP 的第一句话:“我正在尝试配置一个计时器 (TIM9) 及其中断处理程序以单步执行程序”。正如这个答案清楚地表明,你不能。

以上是关于启用外设定时器和定时器实际开始计数之间是不是有延迟?这是啥延迟,是啥原因造成的?的主要内容,如果未能解决你的问题,请参考以下文章

倒计时计时器,在实际时间前 2 秒计数

使用系统定时器SysTick实现精确延时微秒和毫秒函数

STM32的滴答定时器的计数到0时标志位置1,需要软件清除标志位吗!,还是硬件自动清除

CC2530定时器

nrf51822-硬件-定时器/计数器TIMER(IK-51822DK开发套件)

SysTick系统定时器(功能框图和优先级配置)