【问题标题】:Choosing between double buffer and ring buffer?在双缓冲区和环形缓冲区之间进行选择?
【发布时间】:2019-07-05 22:35:43
【问题描述】:

我在解码通过微控制器的 UART 发送的数据包时遇到问题(固件需要是裸机,不支持 RTOS)。数据包长 32 个字节,每 10 毫秒发送一次(连续发送,没有任何停止)。

我需要在 ISR 中进行非常少的处理(以保持 ISR 足够短)并在 main() 循环中进行延迟处理。我想到了两种方法- 1. 使用中断安全的环形缓冲区,将 ISR 写入缓冲区并从中读取 main() 循环。头和尾指针被假定为我的体系结构的原子类型,以确保缓冲区是中断安全的。请参阅示例实现 here

  1. 使用双缓冲方案(乒乓缓冲区),其中 main() 循环应在 ISR 写入另一个缓冲区时处理其中一个缓冲区。假设我可以原子地修改指向 ISR 缓冲区的指针,从而避免临界区问题。

UART 能够产生 RX FIFO 非空中断。还提供 DMA 支持。

  1. 这里使用哪种数据结构最合适?
  2. 这里涉及的权衡是什么?

【问题讨论】:

  • 在双缓冲方法中切换缓冲的标准是什么?我猜你有一种“开始数据包”角色可以做到这一点?乍一看,这看起来比没有太多好处的简单环形缓冲区复杂一些。从错过的“数据包开始”中恢复对我来说似乎更困难。
  • 双缓冲区需要 ISR 解码协议和切换缓冲区。相比之下,环形缓冲区不需要 ISR 来解码协议,但某些代码必须从环形的读取端足够快地读取以避免它被填满:该代码通常会将数据复制到另一个缓冲区,解析协议并保留已识别的数据包。 IMO 环形缓冲区对 ISR 的要求较低。

标签: embedded microcontroller circular-buffer double-buffering


【解决方案1】:

双缓冲区只是一种特殊的环形缓冲区,只有两个插槽在生产者和消费者之间交换。如果您的处理时间变化不大,那应该就足够了。如果输入速率或处理时间不同,环形缓冲区可能会有所帮助,但是当处理无法跟上时,您很可能需要一些流量控制来减慢输入速率。

【讨论】:

  • 你能解释一下为什么如果输入速率或处理速率不同,双缓冲不是一个好的选择吗?
  • 如果它们变化得足够大,以至于生产者可以在消费者处理一个槽所需的时间内填满两个槽,那么就没有空闲槽可供使用。
  • 嗯,是的,没错,但最终它可能与您批评环形缓冲区的事情没有什么不同:如果处理跟不上,某些事情就会失败。
  • 环形缓冲区和“双缓冲区”并不像您建议的那样相似。环形缓冲区不需要 ISR 来解码协议,而“双缓冲区”则需要。所以我不会把它当作简单的默认正确答案。
  • 在环形缓冲区中维护单独的读写指针非常简单——ISR只修改写指针,主线只修改读指针。相比之下,切换缓冲区要复杂得多。
猜你喜欢
  • 1970-01-01
  • 2012-04-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-11-07
  • 2018-10-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多