cancel
Showing results for 
Search instead for 
Did you mean: 

STM32U5 UART - loopback test

daniellages
Visitor

Hi! I have a STM32U585 board and I'm trying to make a UART loopback test. I tried two different modes:

  • Asynchronous (Full-Duplex) - wire between the TX and RX
  • Single-Wire (Half-Duplex) - wire looping to itself

Both worked in similar ways. I successfully was able to handle 1 byte, so this is the code that worked fine

/* USER CODE BEGIN PV */
uint8_t tx = 0;
uint8_t rx = 0;
/* USER CODE END PV */

and inside the main function I had

while(1)
{
    printf("Sending byte: %d\r\n", tx);
    HAL_UART_Transmit(&huart3, &tx, 1, HAL_MAX_DELAY);

    HAL_UART_Receive(&huart3, &rx, 1, HAL_MAX_DELAY);
    printf("Received byte: %d\r\n", rx);

    tx++;
    HAL_Delay(1000);
}

I could see in the terminal that it was successfully incrementing both tx and rx variables.

 

Now, it all went wrong when I tried to use an array instead of a single byte. This is what I tried:

/* USER CODE BEGIN PV */
uint8_t tx[4] = {0x55, 0x12, 0x00, 0xFF};
uint8_t rx[4] = {0};
/* USER CODE END PV */

and the main function had

while(1)
{
    printf("Sending bytes:\r\n");
    for(int i=0; i<4; i++)
        printf("  0x%02X", tx[i]);
    printf("\r\n");

    HAL_UART_Transmit(&huart3, tx, 4, HAL_MAX_DELAY);

    HAL_UART_Receive(&huart3, rx, 4, HAL_MAX_DELAY);

    printf("Received bytes:\r\n");
    for(int i=0; i<4; i++)
        printf("  0x%02X", rx[i]);
    printf("\r\n");

    tx[2]++;
    HAL_Delay(2000);
}

From this in the terminal shows that it got stuck at HAL_UART_Transmit(), this was the full output

    Sending bytes:  0x55 0x12 0x00 0xFF

 

By running it in debug mode I was able to realize that it got stuck on this while loop inside the stm32u5xx_hal_uart.c

HAL_StatusTypeDef UART_WaitOnFlagUntilTimeout(UART_HandleTypeDef *huart, uint32_t Flag, FlagStatus status, uint32_t Tickstart, uint32_t Timeout)
{
    /* Wait until flag is set */
    while ((__HAL_UART_GET_FLAG(huart, Flag) ? SET : RESET) == Status)
    {
    ...

Can anyone help me out? Is there any info about my test that you need me to provide?

Thanks in advance!

2 REPLIES 2

There's no buffer depth, so don't use blocking functions.

At a polling/loop level you could check for TXE and RXNE flags in the status register and advance your transmit and receive buffer pointers.

Or look to use HAL_UART_ReceiveIT to capture reception as it occurs.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Karl Yamashita
Principal

Don't use HAL_MAX_DELAY. That is ~49 days before it'll timeout. For 4 bytes, 100ms will suffice. That why it seems like you're stuck in the UART_WaitOnFlagUntilTimeout function

 

You should always read the return status when using HAL_UART_Transmit and HAL_UART_Receive.

You should get either HAL_ERROR, HAL_OK, HAL_BUSY or HAL_TIMEOUT returned. In your case it'll probably be HAL_TIMEOUT

 

HAL_StatusTypeDef hal_status;
 
hal_status = HAL_UART_Transmit(&huart3, tx, 4, 100); // same for HAL_UART_Receive
if(hal_status != HAL_OK)
{
	if(hal_status == HAL_TIMEOUT)
	{
		// do something
	}
	else if(hal_status == HAL_BUSY)
	{
		// do something
	}
	else if(hal_status == HAL_ERROR)
	{
		// do something
	}
	return;// do not continue, until errors fixed
}
// continue

 

Don't worry, I won't byte.
TimerCallback tutorial! | UART and DMA Idle tutorial!

If you find my solution useful, please click the Accept as Solution so others see the solution.