【问题标题】:Handling UART ISR during double buffer swap在双缓冲区交换期间处理 UART ISR
【发布时间】:2019-10-01 21:56:14
【问题描述】:

我正在为 STM32F 处理器上的 UART 开发双缓冲区。下面的示例在每次 UART ISR 运行时将数据添加到缓冲区。当主进程想要从中提取数据时,这个缓冲区就会被交换。

我担心可能出现的拐角情况。 ISR 可能会在我交换缓冲区之后但在我重置接收缓冲区计数之前触发。这意味着我的缓冲区大小和计数将不同步。

处理这种极端情况的最佳方法是什么?

uint8_t rxBufferA[MAX_RX_BUFFER_SIZE];
uint8_t rxBufferB[MAX_RX_BUFFER_SIZE];
uint8_t *receivingBuffer;
uint8_t *processingBuffer;
volatile uint32_t rxBufferSize;

uart_isr() {
  receivingBuffer[rxBufferSize++] = RECEIVE_DATA_REGISTER
}


main() {

  receivingBuffer = &rxBufferA;
  processingBuffer = &rxBufferB;

  while(1) {

    if (rxBufferSize > 0) {
      uint32_t i = 0;
      uint8_t *ptemp = receivingBuffer;
      uint8_t bufferSize = 0;

      /* zero out processing buffer */
      memset(processingBuffer, 0, MAX_RX_BUFFER_SIZE);

      /* swap receiving and processing buffers */
      receivingBuffer = processingBuffer
      processingBuffer = ptemp;

      /* WHAT IF THE ISR FIRES HERE??? */         

      /* save off buffer size and reset count */
      bufferSize = rxBufferSize;
      rxBufferSize = 0;

      /* process rx data */
    } 
  }
}

【问题讨论】:

  • receivingBuffer 应该是 volatile:它在 ISR 和普通代码之间共享。当你改变它时,把你的编译器警告调到最大,因为我看到会有不止一个“丢弃易失性限定符”。
  • 顺便说一句,当您设置编译器警告时,您还应该看到 main 应该是 int main(void) 和 ISR void uart_isr(void)(现在它是一个隐含的 int,它不会返回,所以你有一些问题)
  • @CacahueteFrito 我提供的例子不应该是一个粗略的草图
  • 默认情况下您的编译器警告应该很高。所以你的草图至少应该在没有警告的情况下编译。如果你使用 GCC 或 Clang -Wall -Wextra -Werror 会阻塞你的编译

标签: c buffer interrupt stm32 uart


【解决方案1】:

你需要临界区。交换缓冲区时禁用用户中断。

不需要调零

【讨论】:

  • 但后来我遇到了丢失 ISR 和相关数据的极端情况
  • @user8908459 你不会错过的。它将一直等到您再次启用它。
猜你喜欢
  • 2022-01-03
  • 1970-01-01
  • 2014-08-29
  • 2019-07-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-04
  • 2021-06-16
相关资源
最近更新 更多