【发布时间】: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)和 ISRvoid uart_isr(void)(现在它是一个隐含的int,它不会返回,所以你有一些问题) -
@CacahueteFrito 我提供的例子不应该是一个粗略的草图
-
默认情况下您的编译器警告应该很高。所以你的草图至少应该在没有警告的情况下编译。如果你使用 GCC 或 Clang
-Wall -Wextra -Werror会阻塞你的编译
标签: c buffer interrupt stm32 uart