补偿ARM中断的延迟?

时间:2012-09-11 13:40:13

标签: arm counter interrupt stm32 low-latency

我正在研究STM32F4 CPU上的一个项目,产生信号。

我在STM32上有CPU时钟(没有预分频器)的通用定时器,在溢出时触发中断,然后用GPIO产生周期信号。

我需要在非常精确的时间触发GPIO(基本上低至一个CPU周期精度)。通过设置优先级和放大,我已设法将此抖动降低到+ -5个周期。 al,但这个抖动存在,取决于CPU正在做什么。

我需要补偿这几个周期的抖动。只要我在精确的时间切换GPIO,添加几个周期就不会有问题。

我的想法是读取计数器的当前值,并且有一个FIXED_NUMBER-CURRENT_VALUE时间的活动循环,确保我会在精确的时间退出循环。

然而,在C中做一个简单的循环 - 一个FOR循环,或一个while(counter->值< TARGET)不起作用,因为它ADDS抖动而不是减少它。

我做错了什么/天真?我应该在集会中这样做吗?怎么会与C不同(我检查了用GCC进行反汇编以检查循环是不是已经优化了,也没有打到内存?)

(我确保使用空的,非优化但不会击中内存循环体)

编辑:在AVR上看到这个例子(我知道的更稳定)参见示例http://lucidscience.com/pro-vga%20video%20generator-7.aspx(搜索“jitter”)

edit2 :我在程序集中尝试了一个简单的循环,例如(r0是我的计数器,等待的循环次数,在寄存器中)

loop : SUBS r0,#1 ; tried with 2 also
       BGE loop

并且,如果没有它,抖动会更好。

总结起来,我已经知道我应该延迟多少。我只需要一种方法让代码分支在一个案例中可靠地消耗N个循环而在另一个案例中可以消耗M.不幸的是,单独的分支似乎不起作用,因为管道补充似乎似乎采取可靠的循环次数,并且条件表达式也不是因为它们总是采用相同的循环次数(有时无所事事。)

从RAM而不是闪存运行会提高一致性吗? (NB stm32f4有一个flash预取..)

2 个答案:

答案 0 :(得分:7)

(具有讽刺意味的是,关于减少响应延迟的问题需要三年才能得到答案。)

+/- 5个周期听起来非常熟悉。在中断调度期间,您可能会遇到等待状态访问Flash控制器。

在中断调度期间,CPU需要做三件事:

  1. 加载向量表条目。
  2. 加载中断例程的初始代码。
  3. 将一些寄存器写入堆栈。
  4. 如果矢量表和/或中断例程代码在Flash中,则项目1和2中的提取将转到Flash。当以最高额定速度(高达168MHz)运行CPU时,访问Flash需要五种等待状态。这意味着对Flash的访问可能需要1或6个周期,具体取决于所请求的数据是否在Flash缓存中。如果你看到完全 0或5个周期的延迟,这可能是罪魁祸首。通过将ISR代码和向量表移动到RAM中,可以轻松解决此问题。你也可以修复"它通过禁用Flash缓存,这将导致Flash访问可预测的缓慢。

    有一个偷偷摸摸的因素可能也在咬你:如果代码被中断也使用Flash,那么中断调度可能必须等待 Flash访问完成,假设它错过了缓存。您可以通过将中断的代码移动到RAM中来解决此问题,但此时它开始听起来像Flash中没有任何东西。我可以通过以下方式将代码保存在Flash中。

    最后,还有一个尚未悄悄的事情:如果你有之前可能发生的其他中断你的延迟敏感中断,那么这个中断就有可能由于tail chaining而导致延迟达到-5个周期。

    我对上面列出的第二个问题的解决方案有点奇怪:当发生中断时,确保处理器处于空闲状态,即不接受另一个中断或从Flash获取。我这样做的方法是配置一个较低优先级的中断,以便在我的延迟敏感中断(使用定时器)之前到达; ISR只执行等待中断指令wfi

    这些是可以克服的问题。我不同意你需要放弃C并用汇编语言写的评论者;我的m4vgalib系统几乎不包含汇编语言,抖动很低。

    我在one section of an article on my blog中更详细地讨论了这些相同的问题和我的解决方案。

答案 1 :(得分:0)

悬崖是正确的,没有办法在具有中断,闪存等待状态和管道的CPU内核上达到单个CPU周期精度。 AFAIK,有点奇怪的视差“螺旋桨”是为数不多的“高性能” MCU核心,可以保证周期时间一致性,因为它不支持中断(而是“旋转”访问集线器中的8个核心)之一。 >