首页 文章

补偿ARM中断的延迟?

提问于
浏览
3

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

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

我需要在非常精确的时间触发GPIO(基本上低至一个CPU周期精度) . 我已设法通过设置优先级等来将此抖动减少到-5个周期,但这种抖动存在,具体取决于CPU的工作情况 .

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

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

然而,在C中做一个简单的循环 - 一个FOR循环,或一个while(counter-> value <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预取..)

1 回答

  • 5

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

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

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

    • 加载向量表条目 .

    • 加载中断例程的初始代码 .

    • 将一些寄存器写入堆栈 .

    如果向量表和/或中断例程代码在Flash中,则项目1和2中的提取将转到Flash . 当以最高额定速度(高达168MHz)运行CPU时,访问Flash需要五种等待状态 . 这意味着对Flash的访问可能需要1或6个周期,具体取决于所请求的数据是否在Flash缓存中 . 如果你看到正好有0或5个周期的延迟,这可能是罪魁祸首 . 通过将ISR代码和向量表移动到RAM中,可以轻松解决此问题 . 您也可以通过禁用Flash缓存来实现它,这将导致Flash访问速度可预测地很慢 .

    有一个潜行因素可能也在咬你:如果被中断的代码也使用Flash,中断调度可能必须等待其Flash访问完成,假设它错过了缓存 . 您可以通过将中断的代码移动到RAM中来解决这个问题,但此时它是一种将代码保存在Flash中的方法,我在下面提到过 .

    最后,还有一个比较狡猾的事情:如果你在延迟敏感中断之前有其他可能发生的中断,那么由于tail chaining,该中断有可能达到-5个周期的延迟 .

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

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

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

相关问题