【问题标题】:AVR8 Real Time Scheduler, Serial CommunicationAVR8 实时调度器,串行通信
【发布时间】:2014-09-07 23:14:20
【问题描述】:

我目前正在编写一个 ATmega32u4。我已经实现了串行通信,它是使用内置中断实现的,每次在 Rx 引脚上接收到一个字节时都会执行该中断。 Rx 引脚上的字节放置在一个字节缓冲区中,当在 Rx 引脚上接收到另一个字节时,该字节将被替换。这是 atmel 的内置库。

ISR(USART1_RX_vect, ISR_BLOCK)
{
   RingBuffer_Insert(&usart_rx_buffer,UDR1);
}

当在 Rx 引脚上接收到一个字节时,我的代码会执行中断。当接收到一个字节时,这个字节被输入到我的环形缓冲区 uart_rx_buffer 中,稍后会在其中解码。

如果正在执行中断,这会导致在执行 UART 中断之前替换一个字节缓冲区,则该字节将丢失。

这样做的结果是其他中断的执行时间不能超过波特率,否则串行字节丢失。有什么办法可以避免这个问题?

【问题讨论】:

    标签: c real-time avr job-scheduling serial-communication


    【解决方案1】:

    解决这个问题的一种方法是在所有花费超过波特率的中断中使用属性ISR_NOBLOCK,从而使编译器尽早激活中断启用标志。 ISR 并允许 USART1_RX_vect 在其他中断中执行。但是,“应注意避免堆栈溢出,或避免在 AVR 硬件在进入 ISR 之前未清除相应中断标志的情况下无限进入 ISR”。

    我遇到过同样的问题,到目前为止,这是我能想到的最佳解决方案。 不过,我没有使用过,也没有测试过

    编辑:请记住,所有其他中断也可以在使用 ISR_NOBLOCK 属性声明的中断内执行,而不仅仅是您想要的中断。因此,您基本上允许所有中断嵌套在所有中断中,除了 USART1_RX_vect(以及那些用 ISR_BLOCK 声明的中断)。这是这个解决方案的主要问题(除了堆栈溢出问题)。

    【讨论】:

      【解决方案2】:

      这样做的结果是其他中断的执行时间不能超过波特率,否则串行字节会丢失。有什么办法可以避免这个问题?

      你所有的观察都是正确的。虽然允许像 Nuno 的回答中建议的嵌套中断可能会起作用,但通常是您会/应该避免的事情。在任何地方都允许嵌套中断会使代码变得难以预测。

      我会首先尝试优化阻塞 UART 接收 ISR 的中断的执行时间。看看中断优先级。如果有多个中断处于未决状态,它们将按照此优先级执行。如果“总是”有更高级别的中断挂起,这可能会导致较低级别的中断“饥饿”。

      你的波特率是多少?即使在 115200 位/秒的速度下,每个接收字节您也可以执行大约 700 条指令(假设为 8MHz)。 ISR 应尽可能短。如果有一个 ISR 需要很长时间,并且由于某种原因您无法对其进行优化,则可以考虑只允许在该单个 ISR 中嵌套中断(这仅在执行不重要时才可行)。

      如果您使用高波特率,请考虑降低它。 9600 波特通常就足够了,但可能需要异步发送以防止代码阻塞。

      【讨论】:

      • 如果该长中断的执行不是关键的,则不应在中断上下文中完成该任务。在这种情况下,ISR 应该只设置一些在主循环中处理的标志。
      猜你喜欢
      • 2017-05-11
      • 1970-01-01
      • 2018-03-09
      • 2021-12-18
      • 1970-01-01
      • 1970-01-01
      • 2016-08-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多