Showing results for 
Search instead for 
Did you mean: 

UART CTS signal stuck at high after framing error

Associate III

Hi all.

We are using a bidirectional UART with hardware-flow control lines (RTS/CTS) between two microcontrollers.

One of the controllers (A) is an STM32H7, the other controller's type (B) should not be relevant. I write this from the perspective of A.

A's peripheral is configured with the correct baudate, word configuration and 16x oversampling.

We're using STM32 HAL drivers and initially configure the UART as follows:


HAL_UART_Init( &mUartHandle );
HAL_UARTEx_SetTxFifoThreshold( &mUartHandle, UART_TXFIFO_THRESHOLD_1_8 );
HAL_UARTEx_SetRxFifoThreshold( &mUartHandle, UART_RXFIFO_THRESHOLD_1_8 );
HAL_UARTEx_DisableFifoMode( &mUartHandle );
HAL_UART_RegisterCallback( &mUartHandle, HAL_UART_TX_COMPLETE_CB_ID, &TxCompleteCallback );
HAL_UART_RegisterCallback( &mUartHandle, HAL_UART_RX_COMPLETE_CB_ID, &RxCompleteCallback );
HAL_UART_RegisterCallback( &mUartHandle, HAL_UART_ERROR_CB_ID, &ErrorCallback );
HAL_UART_RegisterRxEventCallback( &mUartHandle, &RxEventCallback );

(where mUartHandle is basicaly of type UART_HandleTypeDef)


Please note that this is only a snippet to demonstrate our function calls as return values are handled in our code.

So far, so good - communication has been working so far.


A new requirement in our project is that A now needs to control the reset line of B during runtime for multiple times.

This introduces a new challenge:

Assume UART of A is already configured, B is kept in reset (by A, reset line B_nRST is active low). While B is in reset, its TX line is not at the usual UART idle high level but at low level. A controls B out of reset. It takes some time until B comes out of reset and finally pulls its TX line to UART idle high level.


Afterwards, B transmits data and A controls its CTS line as expected. The bigger picture:


Let's zoom to the very end. After exchanging some data, A will put B back to reset (zoomed in at the end of the previous screenshot):


It can be seen that after having pulled the reset line low, that B's TX line falls from UART idle high level to low.


Having B's UART TX line low leads to framing errors in A's UART peripheral in the RX path. (That spike in the CTS signal may be an artifact that originates from A UART de-initialization.)


B is kept in reset for a while. Before starting another phase of UART communication, B is pulled out of reset again and the procedure is expected to repeat, but I only see two "unexpected" cases:


Case 1) A's CTS line is permanently pulled high after A has received the first byte from B so that B will stop sending any furhter data:



Case 2) A's CTS line is permanently pulled high from the very beginning:



Cases 1 and 2 may stem from two different approaches when trying to re-initialize A's UART peripheral.


TL;DR: My core questions are:

  1. How do I properly handle UART framing errors using HAL?
  2. How do I properly re-initialize UART peripheral using HAL?
  3. How can I get a "normal" behaviour of the CTS line after UART re-initialization?


What I've tried so far:


For "de-init" of A's UART after reset of B:

  • Call HAL_UART_DeInit(&mUartHandle)
  • Additionally call HAL_UART_Abort( &mUartHandle ) before HAL_UART_DeInit().

For "re-init" of A's UART after pulling B out of reset:

  • Call HAL_UART_Init( &mUartHandle ) or
  • Will HAL_UART_DeInit render mUartHandle unusable (reset value?) for another call of HAL_UART_Init() and I need to overwrite the values in the struct or use Call HAL_UART_Init( copyOfInitialConfiguration )? Couldn't get it working.
  • __HAL_UART_CLEAR_FEFLAG( &mUartHandle ) before HAL_UART_Init()
  • Do I need to repeat calls to HAL_UARTEx_*Fifo*(), HAL_UART_Register*Callback() from the initial configuration (shown above) for every re-configuration or are those "settings" preserved in the HAL instance?


As an alternate approach I see a way to prevent framing errors coming from B's resets (from A's perspective again):

  1. configure A_RX (aka B_TX) as GPIO input line
  2. get B out of reset (A_RX will be low)
  3. wait until A_RX has reached idle high level (edge detection by interrupt or busy-waiting)
  4. re-configure A_RX as UART RX line (respectively the whole UART peripheral)

However, I don't know if this approach is a good way - it seems more tedious and error-prone and the UART may still be not re-configured properly.

Your help is very much appreciated!