How to change USART/Serial buffer size for STM32

Hello,
I am using IDE2 and STM32F4 Black Pill and my project is serial output i/o bound as Serial.println is blocking when sending a 200 byte message. How do I change the serial buffer size please?

I know this question has been asked many times as I have spent half a day following the google hits. But none of the threads/videos I have followed seem to work as maybe I am editing the wrong #define in the wrong h file.

I have even tried to edit the core which there seem to be TWO files of same name USBAPI.H @
C:\Program Files (x86)\Arduino\hardware\arduino\avr\cores\arduino
C:\Users\Me\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.8.6\cores\arduino

They contain following:
#ifndef SERIAL_BUFFER_SIZE
#if ((RAMEND - RAMSTART) < 1023)
#define SERIAL_BUFFER_SIZE 16
#else
#define SERIAL_BUFFER_SIZE 64
#endif
#endif
#if (SERIAL_BUFFER_SIZE>256)
#error Please lower the CDC Buffer size
#endif

which I edited to:
#ifndef SERIAL_BUFFER_SIZE
#if ((RAMEND - RAMSTART) < 1023)
#define SERIAL_BUFFER_SIZE 16
#else
#define SERIAL_BUFFER_SIZE 512
#endif
#endif
#if (SERIAL_BUFFER_SIZE>256)
#error Please lower the CDC Buffer size
#endif

After the edit I would expect a compile error as SERIAL_BUFFER_SIZE is too large, but no compile error so I assume they have not changed what I am trying to change which is the STM32 serial buffer size.

Also if I had changed the correct .h correctly Serial.println still blocks?
Send rate is 200 bytes every 100ms at 115200 BitsPerSec

Any help much appreciated imk

That is for AVR processors, not for the STM.

You will have to find similar files for the STM; find the board package that you installed in C:\Users\Me\AppData\Local\Arduino15\packages and work from there.

Thanks for reply.
That's the problem I can't find a .h on the c: disk that contains SERIAL_BUFFER_SIZE other than the two I mentioned maybe SERIAL_BUFFER_SIZE is not the #define in stm32.
Don't know spent hours at it and really confused.

Followed this thread:

and USART_RX_BUF_SIZE is not in any of the .h on my c:

OK, please provide the additional board url that you have used to get the board package installed. I will do a bit of digging and see if I can find it.

Many thanks for reply, below are te links to libraries I have imported:
Many thanks

https://github.com/stm32duino/BoardManagerFiles/raw/main/package_stmicroelectronics_index.json
https://github.com/WeActStudio/ArduinoCore-AT32F4/releases/download/0.0.1/package_at32_index.json
https://raw.githubusercontent.com/WeActStudio/ArduinoCore-AT32F4/main/package_at32_index.json
https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json

Look at HardwareSerial.h :

https://github.com/stm32duino/Arduino_Core_STM32/blob/42efbeb48728748965ce50df1a71e0db259d37da/cores/arduino/HardwareSerial.h#L32-L58

Many thanks for effort, problem solved :slight_smile:

At below path I found HardwareSerial.h and made below change;
Net result is Serial.println blocked before change for about 10mS for 132 bytes and 115200 bps and after change Serial.println blocks for less than 30uS. Project Back on Rails!
Measured on little Hantek DSO2D10, which is finally fixed after latest software upgrade :slight_smile:

Many thanks, Wonderful Christmas and New Year to you and yours, IMK

#ifdef ORG

#if !defined(SERIAL_TX_BUFFER_SIZE)
#define SERIAL_TX_BUFFER_SIZE 64
#endif
#if !defined(SERIAL_RX_BUFFER_SIZE)
#define SERIAL_RX_BUFFER_SIZE 64
#endif
#if (SERIAL_TX_BUFFER_SIZE>256)
typedef uint16_t tx_buffer_index_t;
#else
typedef uint8_t tx_buffer_index_t;
#endif
#if (SERIAL_RX_BUFFER_SIZE>256)
typedef uint16_t rx_buffer_index_t;
#else
typedef uint8_t rx_buffer_index_t;
#endif

#endif // ORG

#if !defined(SERIAL_TX_BUFFER_SIZE)
#define SERIAL_TX_BUFFER_SIZE 256
#endif
#if !defined(SERIAL_RX_BUFFER_SIZE)
#define SERIAL_RX_BUFFER_SIZE 64
#endif
#if (SERIAL_TX_BUFFER_SIZE>256)
typedef uint16_t tx_buffer_index_t;
#else
typedef uint8_t tx_buffer_index_t;
#endif
#if (SERIAL_RX_BUFFER_SIZE>256)
typedef uint16_t rx_buffer_index_t;
#else
typedef uint8_t rx_buffer_index_t;
#endif
C:\Users\Me\AppData\Local\Arduino15\packages\STMicroelectronics\hardware\stm32\2.6.0\cores\arduino

1 Like

Just a warning: when updating the board package, that file will be overwritten.

And a better approach might be to store data in a buffer and play it out in a non-blocking way using Serial.availableForWrite() - Arduino Reference.

Your right and this is worry; and why I have made BIG note for my self.
That said I'll take look at availiableforwrite() and how I send all this data.
As maybe better to break it up into smaller packets and let the scheduler send chucks at regular intervals. Project is autonomous robot's that sends three of VL53L5CX data back to the host app (via an ESP NOW WiFi Modem) that runs in a PC using Neural Network to send steering commands.

Do you use availiableforwrite() during startup to get max msg size or is it a dynamic function that returns available space to send At This Time. Hence get buffer ready and poll availiableforwrite() until available space ?

It's dynamic. You check if there is enough space in the buffer before you print. In the below function printIt(), each time there is space in the underlaying software buffer, on or more characters are added to it from the text that you pass.

You can compile it with the #define to see that a blocking serial print affects the bwod() or without the #define to see that printIt() does not affect the bwod().

Tested on a 328P based board.

char text[1000];

#define BLOCKING

void setup()
{
  Serial.begin(2400);
  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, LOW);

  for (uint16_t cnt = 0; cnt < sizeof(text) - 1; cnt++)
  {
    text[cnt] = '0';
  }
  // last character will be a '1'
  text[998] = '1';

  int x = Serial.availableForWrite();
  Serial.print(F("The Tx buffer is "));
  Serial.print(x);
  Serial.println(F(" bytes"));

  delay(2000);
}

char buf[64];

void loop()
{
#ifdef BLOCKING
  Serial.println(text);
#else
  static bool isComplete = false;
  if (isComplete == false)
  {
    isComplete = printIt(text, strlen(text));
  }
  else
  {
    Serial.println();
    isComplete = false;
  }

#endif
  bwod();
}


bool printIt(char *t, uint16_t numChars)
{
  static uint16_t index;

  while (Serial.availableForWrite())
  {
    Serial.print(t[index++]);
    if (index >= numChars)
    {
      index = 0;
      return true;
    }
  }
  return false;
}

void bwod()
{
  static uint32_t lastUpdateTime;
  static uint8_t ledState = LOW;

  if (millis() - lastUpdateTime >= 150)
  {
    lastUpdateTime = millis();
    if (ledState == LOW)
      ledState = HIGH;
    else
      ledState = LOW;

    digitalWrite(LED_BUILTIN, ledState);
  }
}

Each time that printIt() returns true, it indicates that the full message was transmitted and you can transmit another message.

Notes:

  1. The baudrate of 2400 was choosen so it takes a while to transmit the full message (approx. 4 seconds).
  2. I don't know anything about your requirements and so on so can't further advise.

Many thanks for the code sample, it is most helpful.
Now I have given this 64 byte limit and my local editing of the #define buffer size much thought.
And I think I am going to revert back to the original 64 byte ARDUINO standard buffer size.
How I am planning on send large messages is basically to send them using available serial space similar to your solution. My current thinking is such. I will define a large buffer say 512 bytes and use it like a ring buffer that is accessed by two functions a writer and a reader. the writer is called by a number of functions in the app that need to send to serial port x . this writer take what the calling function wants to send and writes it into the ring buffer, hence several functions can call the writer and deposit short messages without being block. The reader is called frequently in the main loop and does similar to your sample inasmuch as it serial.print's what it can then exits. This I won't run into issues if I build for different platforms AVR/ESP etc and I'll have a serial buffer/sender module that I can reuse for other arduino apps. many thanks to all for all the input and a happy Christmas to you and yours :slight_smile: IMK

I did not implement a ring buffer because I did not know your exact requirements. Enjoy in implementing it.

If your problem is solved, you can mark de most useful reply as solved using the "solution" button under it. That way, others know that a solution is provided.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.