Software Serial RX not working on Nucleo-L4R5ZI

I’m working on getting Software Serial working on an L4R5ZI nucleo devboard, and running into a few issues. Transmitting data works perfectly using <SoftwareSerial.h>, but receiving is not working for me.
When I switch the device to using HardwareSerial and change its port to the RX for UART3 for example, everything works just fine, it’s only when I switch to softwareserial where I have issues.

While the nucleo board has plenty of hardware serial options, I will not have those available to me in the final design since we will be using a STM32L412k instead of a STM32L4R5Z.

The applicable parts of my code:

#include "SoftwareSerial.h"
SoftwareSerial Sensor1Serial(D4, SENSOR_NULL_PIN); // the MCU does not need to transmit anything over UART so passing null as TX pin. I have tested with an actual pin here, still no luck on receiving on the devboard

while(!Sensor1Serial.available()) { } 
while(Sensor1Serial.available()) {
  data += (char);
  if( == kEndOfDataStream) { // 0x0D signifies end of data

Platform.ini for reference:

platform = ststm32
board = nucleo_l4r5zi
framework = arduino
lib_deps = 
	adafruit/Adafruit INA219@^1.1.1
	adafruit/Adafruit Si7021 Library@^1.4.0
	stm32duino/STM32duino Low Power@^1.1.0
	stm32duino/STM32duino RTC@^1.1.0
build_flags =

Does your codesnippet also not work in the Arduino IDE when using GitHub - stm32duino/Arduino_Core_STM32: STM32 core support for Arduino?

Not quite sure what you mean - I’ve been using the VSCode extension for building/uploading.
Everything builds/uploads fine, but the first while loops forever when Sensor1Serial is type SoftwareSerial.

I want to make sure that the problem you’re seeing is not specific to PlatformIO, but to the STM32Duino Arduino core (in which case it’s an immediate bug report to the Arduino core and not here at PlatformIO). You should grab the Arduino IDE 1.8.16 as normal at, install the STM32Duino core, select the same board you selected in PlatformIO and give it the exact same code snippet you gave PlatformIO, then upload and test.

Gotcha. I’ll give that a shot tomorrow and reply again with the results.

In case you haven’t resolved this yet …

My first suspect would be the pin choice. You use “D4” for RX. As a test, you could remove anything attached, set that pin up as digital output, make it blink slowly, and verify with an LED or voltmeter.

Pin names can be very confusing across the STM32 / Arduino / PlatformIO worlds - “D4” is most likely an Arduino designation, whereas “PD4” is an STM32 GPIO name. They differ. Another pin number interpretation difference could be between h/w and s/w serial.

And lastly: I suspect that SoftwareSerial relies on EXTI pin interrupts, so the question is whether SoftwareSerial supports (and properly configures) that on the particular pin you’re using.

No luck running with the Arduino IDE.

As for your suggestion @jcw - D4 appears to be functioning properly as both a simple digital output and input. Do you think that it could just be D4 specifically and it would make sense to go through a few other GPIO to attempt to find one that works? Or do you have a recommendation for which ones to try?

Per page 35, the “D4” pin is PF14. The L4R5ZI variant cpp file correctly declares the the 5th entry (D0… D4) to be PF14.

So the usage of D4 or PF14 in the code should be exactly interchangable.

I’m not sure whether there’s a technical liminitation regarding the EXTI on PF14, which would map to EXTI14. Maybe it’s already occupied by some other code in the sketch or in framework code which you don’t see? If I remember STM32 hardware restrictions correctly, any Px14 pin (PA14, PB14, …) will occupy the EXTI14 peripheral (when using GPIO interrupts), and thus using attachInterrupt() etc on any of those pins might interfer with the ability to do a software-serial RX on PF14.

The piece of code you’re testing only creates the software serial devices and prints all received characters out to the main serial?

If yes, you have a minimal example that demonstrates the problem. Since the here-used SoftwareSerial library code resides within STM32Duino, please open a bug report there per Sign in to GitHub · GitHub.

There is a bit of other stuff in the program still - I’ll get it down to a minimal example and submit a report if there’s still an issue.

Should have gone to a minimal program sooner. Getting the expected data back. Here’s that code:

#include <Arduino.h>
#include <SoftwareSerial.h>

SoftwareSerial sensorSerial(D4, NULL);

void setup() {
  // put your setup code here, to run once:

void loop() {
  // put your main code here, to run repeatedly:
  while(!sensorSerial.available()) {

  while(sensorSerial.available()) {

So I’m guessing this is pointing to that there is something else in my existing firmware causing a conflict of some sort or disabling the EXTI somehow. I’m currently using pins D1 (PD8), D0 (PD9), PC12, PD2, PA11, PA12, PA0, PA1, PB1, PB4, PB5, PB6, and PB7.

Mhm NULL is not a good argument in this since it will evaluate to numeric 0 which is interpreted as the zeroeth pin, so PD9, which is used as you say… The macros used here by their logic support -1 as a value, which will evalute to NC (not connected) in functions used later. Does it make a difference if you write -1 instead of NULL in the sketch that is non working? Does it make a difference if you use D4 as both TX & RX pin in the constructor?

Gotcha. I just tried using -1 in the working minimal program and RX on sensorSerial no longer worked as expected. Defining both TX and RX also caused the RX to not work.

SoftwareSerial sensorSerial(D4, -1);
SoftwareSerial sensorSerial(D4, D4);

I’ll give it a shot in the main program.

With this configuration it might need an additional sensorSerial.listen(); call before usage?

Hm yeah actually it wouldn’t really like NC as the value later down and throw an error :confused:

1 Like

Whee, Max digs in deep and gets results, as usual … :slight_smile:
That was my next thought: a conflicting EXTI config elsewhere.
So IMO it’s either a that, or the Tx NULL/-1 choice - or both.
Perhaps you can pick two other pins (even if Tx never sends).
Note that s/w-based serial Rx is quite tricky, in terms of IRQs & timing.

Update from trying it in the main program:

I think you’ve narrowed it down correctly - when I changed PD9 which was in use to another pin, now
SoftwareSerial sensorSerial(D4, NULL); works correctly. But as you said this prevents the use of PD9. I’ll find some pins that won’t be in use and give it a shot.

Using pins PE12, PE14, and PE15 as TX pins, I am receiving data on my RX pins in the main firmware. Everything is fully working now.

I second this - Max you’re amazing! Thanks for all your help guys.