Arduino_core_stm32: Non-blocking UART

Created on 9 Oct 2019  路  4Comments  路  Source: stm32duino/Arduino_Core_STM32

I stumbled upon a problem that UART transmit operation blocks the whole program execution. AFAIR standard AVR Arduino approach is a non-blocking mode and I think it's the only reasonable way to do this. My STM32H7 would've calculated a hyperspace jump during the time it wastes sending some message ;) So it would be great if the UART code was modified so it works in non-blocking mode.

Answered Question

All 4 comments

Hi @kwastek
in which case you met this issue?
The HardwareSerial is not blocking as it use the HAL_UART_Transmit_IT.
The only way I see you met this is using "printf" which use the blocking HAL_UART_Transmit and used mainly for debug in this core.

Sorry.... The problem is totally on my side.

I noticed it happens in my minimal test code when the time between invoking Serial.println() is smaller that the time required to send the message. So each time the function has to wait for the previous transfer to finish before it can start a new one. Quite obvious but somehow I haven't thought about that...

#if defined STM32H743xx
#define TESTP GPIOC->ODR//
#define TESTB 0     //
#define TESTO A1
#endif

void setup() {
        Serial.begin(115200);
        pinMode(TESTO, OUTPUT);
}


void loop() {
        bitSet(TESTP, TESTB);
        Serial.println("abcdefghijklmnopqrstuvwxyz");
        bitClear(TESTP, TESTB);

        //delay(1); // blocking
        delay(5);   // non-blocking
}

I guess the same problem happens in my actual code because of use of multiple Serial.println calls one after another. So it HAS TO take time before the loop returns to the time sensitive part of the code (rearming timers).

Thank you very much for helping me solve this by assuring me that it SHOULD work correctly, so the problem must be on my side. (I'm totally incapable of wrapping my head around this new cool "polymorphism" thing ;) , so I couldn't just normally trace with Eclipse what function is called and what it looks like under the hood).

I guess it's not a place for such kind of questions, but could you maybe quickly recommend a way to circumvent the annoying Serial.print limitations (like concatenating literals with variables) without piling up the waiting time?

EDIT:
The problem was also occurring (also quite obviously) when a message was bigger than TX buffer size. So I increased SERIAL_TX_BUFFER_SIZE. I hope all this will be useful for some future travelers.

Myabe you can have a look to Streaming library (available thanks libraries manager):
https://github.com/janelia-arduino/Streaming
or using String capabilities.

Example:

#include <Streaming.h>

// the setup routine runs once when you press reset:
void setup() {
  // initialize serial communication at 9600 bits per second:
  Serial.begin(9600);
}

// the loop routine runs over and over again forever:
void loop() {
  String msg = "sensorValue using String\t";
  // print out the value you read:
  Serial << "sensorValue using Streaming\t" << analogRead(A0) << endl;
  Serial.println(String(msg + String(analogRead(A0))));
  delay(1);        // delay in between reads for stability
}

The problem was also occurring (also quite obviously) when a message was bigger than TX buffer size. So I increased SERIAL_TX_BUFFER_SIZE. I hope all this will be useful for some future travelers.

I've added a section in the Wiki

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Jorgen-VikingGod picture Jorgen-VikingGod  路  8Comments

Hoel picture Hoel  路  4Comments

Adminius picture Adminius  路  6Comments

zhaorui4142 picture zhaorui4142  路  4Comments

pawelsky picture pawelsky  路  4Comments