cancel
Showing results for 
Search instead for 
Did you mean: 

STM32U0 using LPUART with Hardware Flow Control

CYH
Associate II

Hi,

I would like to use LPUART3 to proceed the UART communication with hardware control flow enable.
However, I found that when the Send_UART_DATA  there indeed has TX signal from LA, but CTS/RTS hasn't changed, only when system reset, those two pins just could get the status changed.

CYH_0-1749486512885.png

Here is the configuration of MX_LPUART3_UART_Init()

static void MX_LPUART3_UART_Init(void)
{
  /* USER CODE BEGIN LPUART3_Init 0 */
  // Enable LPUART3 clock
  __HAL_RCC_LPUART3_CLK_ENABLE();
  //Enable GPIOB clock
  __HAL_RCC_GPIOB_CLK_ENABLE();
  /* USER CODE END LPUART3_Init 0 */

  /* USER CODE BEGIN LPUART3_Init 1 */
  // Enable NVIC interrupt for LPUART3
  HAL_NVIC_SetPriority(LPUART3_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(LPUART3_IRQn);

  GPIO_InitTypeDef GPIO_InitStruct = {0};
  /*Configure LPUART pins : UART communication */
  // RTS/CTS pins
  GPIO_InitStruct.Pin = GPIO_PIN_4 | GPIO_PIN_5;
  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  GPIO_InitStruct.Alternate = GPIO_AF6_LPUART3;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

  // TX/RX pins
  GPIO_InitStruct.Pin = GPIO_PIN_6 | GPIO_PIN_7;
  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  GPIO_InitStruct.Alternate = GPIO_AF6_LPUART3;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
  /* USER CODE END LPUART3_Init 1 */
  
  hlpuart3.Instance = LPUART3;
  hlpuart3.Init.BaudRate = 57600;
  hlpuart3.Init.WordLength = UART_WORDLENGTH_8B;
  hlpuart3.Init.StopBits = UART_STOPBITS_1;
  hlpuart3.Init.Parity = UART_PARITY_NONE;
  hlpuart3.Init.Mode = UART_MODE_TX_RX;
  hlpuart3.Init.HwFlowCtl = UART_HWCONTROL_RTS_CTS;
  hlpuart3.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
  hlpuart3.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
  hlpuart3.FifoMode = UART_FIFOMODE_DISABLE;
  if (HAL_UART_Init(&hlpuart3) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_UARTEx_SetTxFifoThreshold(&hlpuart3, UART_TXFIFO_THRESHOLD_1_8) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_UARTEx_SetRxFifoThreshold(&hlpuart3, UART_RXFIFO_THRESHOLD_1_8) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_UARTEx_DisableFifoMode(&hlpuart3) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN LPUART3_Init 2 */

  /* USER CODE END LPUART3_Init 2 */
}

 And below is the code of sending UART data in main()

uint8_t cmd_a[]={0x11, 0x22, 0x33, 0x44, 0x55};
if (HAL_UART_Transmit_IT(&hlpuart3,cmd_a, sizeof(cmd_a)) != HAL_OK) {
    printf("Failed to send command\r\n");
}

And the related callback

void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
	/* Prevent unused argument(s) compilation warning */
	  //UNUSED(huart);

	/* NOTE : This function should not be modified, when the callback is needed,
           the HAL_UART_TxCpltCallback can be implemented in the user file.	 */
	uart_transfer=false;
	printf("Transfer completed callback\r\n");

	if (HAL_UART_Receive_IT(&hlpuart3, rx_data, sizeof(rx_data)) != HAL_OK) {
	    printf("Failed to start reception\r\n");
	} else {
	    printf("Started reception successfully\r\n");
	}
}

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
  /* Prevent unused argument(s) compilation warning */
  //UNUSED(huart);

  /* NOTE : This function should not be modified, when the callback is needed,
            the HAL_UART_RxCpltCallback can be implemented in the user file.
   */
  if (huart->Instance == LPUART3)
     {
         printf("Rx Transfer completed callback\r\n");

         // Print received bytes (assuming ASCII or printable format)
         printf("Received data: ");
         for (int i = 0; i < sizeof(rx_data); i++) {
             printf("%02X ", rx_data[i]); // Print in hex format
         }
         printf("\r\n");

         // Optionally, restart reception if expecting continuous data
         if (HAL_UART_Receive_IT(&hlpuart3, rx_data, sizeof(rx_data)) != HAL_OK) {
             printf("Failed to restart reception\r\n");
         }
     }
}

void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
{
    if (huart->Instance == LPUART3)
    {
        printf("UART error: 0x%08lx\r\n", huart->ErrorCode);
    }
}

 Here is the IRQ setting

#define LPUART3_IRQn USART4_LPUART3_IRQn
#define LPUART3_IRQHandler USART4_LPUART3_IRQHandler

void USART4_LPUART3_IRQHandler(void)
{
  /* USER CODE BEGIN USART4_LPUART3_IRQn 0 */
	printf("LPUART3 IRQ triggered\r\n");
  /* USER CODE END USART4_LPUART3_IRQn 0 */
  HAL_UART_IRQHandler(&hlpuart3);
  /* USER CODE BEGIN USART4_LPUART3_IRQn 1 */

  /* USER CODE END USART4_LPUART3_IRQn 1 */
}

 

And below is the print out log whenever trying to send the TX data

-First try after reboot---------------

LPUART3 IRQ triggered
LPUART3 IRQ triggered
LPUART3 IRQ triggered
LPUART3 IRQ triggered
LPUART3 IRQ triggered
LPUART3 IRQ triggered
LPUART3 IRQ triggered
Transfer completed callback
Started reception successfully

-2nd try after 1st time---------------

LPUART3 IRQ triggered
LPUART3 IRQ triggered
LPUART3 IRQ triggered
LPUART3 IRQ triggered
LPUART3 IRQ triggered
LPUART3 IRQ triggered
LPUART3 IRQ triggered
Transfer completed callback
Failed to start reception

 

I would like to know whether the setting of configuration is unexpected? If yes, how should I fixed it?

 

Thanks,

CY

3 REPLIES 3
TDK
Super User

> I would like to know whether the setting of configuration is unexpected? If yes, how should I fixed it?

Since RX is still busy, trying to call HAL_UART_Receive_IT again will result in HAL_BUSY. This is expected.

To fix: on call HAL_UART_Receive_IT again after the first operation completes. Remove it from the TX complete callback and call it in the main thread.

If you feel a post has answered your question, please click "Accept as Solution".
CYH
Associate II

Hi @TDK ,

Thank you for your respond.

I just modify the code as below in main.c

if (HAL_UART_Transmit_IT(&hlpuart3,cmd_a, sizeof(cmd_a)) != HAL_OK) {
  printf("Failed to send command\r\n");
}
if (HAL_UART_Receive_IT(&hlpuart3, rx_data, sizeof(rx_data)) != HAL_OK) {
   printf("Failed to start reception\r\n");
   } else {
     printf("Started reception successfully\r\n");
}

 And the TX callback also be modified that remove the Receive_IT

void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
	/* Prevent unused argument(s) compilation warning */
	  //UNUSED(huart);

	/* NOTE : This function should not be modified, when the callback is needed,
           the HAL_UART_TxCpltCallback can be implemented in the user file.	 */
	uart_transfer=false;
	printf("Transfer completed callback\r\n");

	/*if (HAL_UART_Receive_IT(&hlpuart3, rx_data, sizeof(rx_data)) != HAL_OK) {
	    printf("Failed to start reception\r\n");
	} else {
	    printf("Started reception successfully\r\n");
	}*/
}

 However, the result still show the same failed.
I assume that maybe the first issue need to be solve is that the RTS/CTS is not working properly.

CYH_0-1749490420561.png
So far, I still could not observed that there is RTS/CTS signal changed....excpet within reset

TDK
Super User

> I assume that maybe the first issue need to be solve is that the RTS/CTS is not working properly.

What about the RTC/CTS signals are you objecting to? Why do you think they are not working as intended?

The receiver controls RTS. A low signal indicates it's ready to receive. It's low in the plots and you are ready to receive. What's the problem?

CTS is low which indicates sending is allowed. You're sending.

Or am I missing something?

 

I thought you were asking about this in the OP:

> Failed to start reception

If you feel a post has answered your question, please click "Accept as Solution".