Formatted printing in circular buffer

I am writing inline code for STM32F3 mc (STM32F3-Discovery). I need to output some data to UART, and I use DMA for this, since it allows me to focus on reading sensors and processing data, rather than waiting for the byte to complete. However, the problem is that I need to combine:

  • Formatted output (i.e. some of printf)
  • Multiple consecutive prints (which occurred before the previous print ended)

So, I am thinking of a circular buffer. But I don’t think I know how to make sprintf respect the end of the buffer and continue writing to the beginning of the buffer. I can, of course, create another temporary buffer, print it and copy it byte-by-bye, but it does not look elegant to me.

+5
source share
2 answers

One solution might be to implement your own sprintf, which can work with ring buffers. Unfortunately, this will not help you solve a more basic problem: what would you do if your ringbuffer is full and you call sprintf?

If your memory situation can afford it, I would suggest a different solution for this problem:

The idea is based on two linked buffer lists (one list for free buffers, one list - transfer queue). The buffers are the same size, so they can store the worst case string. The buffers create a simple heap where allocation / deallocation selects or captures an element from either a free or a transfer list.

, , "checkerboarding" . , .

, :

  • .
  • (, sprintf)
  • , ( )

DMA IRQ . , " ", .

, , , / - / -. , , IRQ /.

, .

+2

, , - 2x , . , ( ). - :

void xprintf(const char *format, ...)
{
  int written;
  va_list args;
  va_start(args, format);
  written = vsnprintf(buffer, HALF_BUFFER_SIZE, format, args);
  va_end(args);
  if (buffer + written > bufferStart + HALF_BUFFER_SIZE)
  { // time to wrap
    int overflow = (buffer + written) - (bufferStart + HALF_BUFFER_SIZE); 
    memmove(bufferStart, bufferStart + HALF_BUFFER_SIZE, overflow;
    buffer = bufferStart + overflow;
  }
}
+1

All Articles