Skip to main content
Associate II
August 3, 2026
Question

USART issue in loopback mode

  • August 3, 2026
  • 20 replies
  • 76 views

Hi 👋

I have implemented a simple program to send and receive characters over the USART device which works as expected when I connect my MCU up to minicom via usb as in I can see the characters sent by the program getting printed on the console and I can see the characters I type on minicom in the relevant variable in gdb.

Next, I tried connecting the TX and RX pins together to have transmission and reception in loopback mode but that doesn’t seem to work. My program (which does both transmission and reception in simple polling mode) simply gets stuck on the RXNE != 1 loop and never exits that indicating that the RX pin either never receives any data or it never detects a start bit so it just remains at the idle state waiting for that. So, I’m wondering what the reason for this might be..could it be that minicom simply sends the right start bit sequence which the Receiver picks-up? Or something else..?

The program in both cases is exactly the same so the only difference is that in loopback mode the two pins are naturally jumpered.

Also, within the tight loop the USART_SR register has the following (constant) content:

0x40011000:    11000000    00000000    00000000    00000000

 

Any thoughts? I am on an STM32F4 MCU and using the USART1 (if that makes any difference).

 

Thanks!

20 replies

Pavel A.
August 4, 2026

> My program (which does both transmission and reception in simple polling mode) simply gets stuck on the RXNE != 1 loop

Show the actual code.

Do you detect and handle RX overflow (ORE) ?

 

Associate II
August 4, 2026

Thanks for your reply.

Yes, I do - See code below (it’s in Ada but should be fairly straightforward to follow, let me know if not):

 

procedure Receive (C         : out Character ;
                                USART_Reg : USART_Registers.USART_Reg_Acc) is
   begin
      loop
         exit when USART_Reg.USART_SR.RXNE; --   Line 1
         if USART_Reg.USART_SR.ORE then -- Line 2
            --   ORE reset sequence
            declare
               Unused1 : Boolean;
               Unused2 : HAL.UInt9;
            begin
               Unused1 := USART_Reg.USART_SR.PE;
               Unused2 := USART_Reg.USART_DR.DR;
            end;
         end if;
      end loop;
      C := Character'Val (USART_Reg.USART_DR.DR);
   end Receive;

Stepping through in gdb the flow effectively alternates between Line 1 and Line 2 without getting into the if so no overflow seems to be happening.

Pavel A.
August 4, 2026

Wow! Thrilled to see someone actually using Ada :)

Try to move line 1 after the whole block line 2 (check ORE first).

Also, make sure that USART_Reg.USART_SR is read only once. Copy it to a variable before Line 1 and check that variable.

Maybe, a better idea: some USARTs in STM2F4 can be configured to ignore RX overflow so ORE is silently ignored. You should then use a protocol that detects block errors and corrects/retries.

 

David Littell
Senior II
August 4, 2026

I hesitate to mention this because of its obviousness but in this loopback scenario maybe something called Transmit() should be called before Receive()?

Associate II
August 4, 2026

hello 👋 thanks for your reply.

Yeah, the driver logic is actually doing that (please, see screenshot in previous reply).

I am also starting the receiver first followed by the transmitter prior to running the transmit/receive flow:

 

Andrew Neil
Super User
August 5, 2026

I am also starting the receiver first followed by the transmitter prior to running the transmit/receive flow:

 

For that to work, your Start_Receiver would need to be non-blocking …

 

 

A complex system that works is invariably found to have evolved from a simple system that worked.A complex system designed from scratch never works and cannot be patched up to make it work.
David Littell
Senior II
August 4, 2026

Alrighty, let’s look closer at the hardware.  How exactly are you creating your loopback?  Schematic and photos (for ​@Andrew Neil  ;-) will possibly be helpful.

David Littell
Senior II
August 5, 2026

I just re-read an earlier reply (thanks, forum, for still collapsing replies - NOT!) and noticed that the OP said he’s jumpering PA9 and PA10 to create the loopback.  If the MCU’s RX signal is still connected to anything it’ll be forced to the idle state by that device and the MCU’s TX won’t be able to overcome it.  

Associate II
August 5, 2026

hmm..don’t believe the RX pin connected to anything 🤔 it’s just set-up for alternate function, Pull_Up, Speed_50MHz, Push_Pull and it is jumpered to the TX pin via a rather large jumper wire..wonder if that somehow results in a noisy line..

 

Andrew Neil
Super User
August 5, 2026

 I connect my MCU up to minicom via usb as in I can see the characters sent by the program getting printed on the console and I can see the characters I type on minicom in the relevant variable in gdb

Excellent! Too many people miss this basic first step!

 

 I tried connecting the TX and RX pins together to have transmission and reception in loopback mode but that doesn’t seem to work

Suggests a timing problem:  your code can’t cope with receiving immediately after transmitting - or, depending on how you have this structured, can’t cope with receiving during transmission.

 

A simple test might be to set up something on your minicom host which does a software loopback, with an adjustable delay.

Then adjust the delay to see where it fails, and where it works...

A complex system that works is invariably found to have evolved from a simple system that worked.A complex system designed from scratch never works and cannot be patched up to make it work.
Pavel A.
August 5, 2026

> Suggests a timing problem:  your code can’t cope with receiving immediately after transmitting - or, depending on how you have this structured, can’t cope with receiving during transmission.

Loopback should work even in polling mode: wait for TX complete, write a char to DR, then poll for the char ready in RX. Read DR. Repeat.

As ​@FBL advised, better try plain C and/or ST HAL first. For completeness, check for all possible errors (FE).

Does the USART work in normal full-duplex mode or unidirectional? Is your USB adapter RS-232 or RS-485?

 

Associate II
August 5, 2026

better try plain C and/or ST HAL first. For completeness, check for all possible errors (FE).

Cool, I’ll try and do that 👍

Does the USART work in normal full-duplex mode or unidirectional? Is your USB adapter RS-232 or RS-485?

So, using the asynchronous mode (just the TX/RX pins) which I believe is full-duplex? Also using the RS-232 adapter.

ST Technical Moderator
August 5, 2026

Hi ​@sidisyom_s 

Do you reproduce the issue using our HAL? If not, that would be a good first step to isolate the problem from your custom driver implementation.

To give better visibility on the answered topics, please click on "Best answer" on the reply which solved your issue or answered your question.Best regards,FBL
Associate II
August 5, 2026

Will try and do that, thanks 👍