1
votes

I am working on a double buffer for the UART on a STM32F processor. The example below adds the data to a buffer every time the UART ISR runs. This buffer is then swapped when the main process wants to pull data off of it.

I am concerned about a possible corner condition. It is possible for the ISR to fire after I have swapped the buffers but before I have reset the receive buffer count. This would mean that my buffer size and count would be out of sync.

What is the best way to handle this corner case?

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 */
    } 
  }
}
1
receivingBuffer should be volatile: It is shared between an ISR and normal code. When you change that, put your compiler warnings to the maximum, because I'm seeing that there will be more than one "discards volatile qualifier". - alx
BTW, when you set your compiler warnings you should also see that main should be int main(void) and the ISR void uart_isr(void) (now it's an implicit int, and it is not returning, so you have some problems) - alx
@CacahueteFrito The example I provided was not supposed to be a rough sketch - user8908459
Your compiler warning should be high as default. So your sketches should at least compile without warnings. If you use GCC or Clang -Wall -Wextra -Werror will block your compilation - alx

1 Answers

4
votes

you need critical section. disable the user interrupt when swapping the buffer.

BTW zeroing is not needed