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

6 REPLIES 6
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".
CYH
Associate II

Hi @TDK ,

Yes, I also did ask about "Failed to start reception".

I am just also wondering whether the RTS/CTS control also have the issue.

I understand that when send TX data, the line could be low.

However, the issue is that even today I did not intend to send the UART command, the RTS still remain low, is this normal?

I was expecting there could be the status change which there is UART command be sent.
But...... it keep stay low, the pulse in beginning just caused when the system reboot....

 

Thanks,
CY

TDK
Super User

I'm not seeing any issues with the signals you present.

> I was expecting there could be the status change which there is UART command be sent.

Why? There is no reason to expect this.

 

I don't understand the obsession with the RTS/CTS signals. If you are having functionality issues with the device, debug those directly.

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

Hi @TDK ,

I just modify the code, and just could saw the RTS/CTS signal change when sending TX data as below

CYH_0-1749548745845.png

When it send twice, it would show like the pattern below, it seems reasonable?

CYH_1-1749548804971.png

But..... now it show the differnt error with UART error: 0x00000008 whenever the "Transfer completed callback" finished.

 

Below is the modify code of UART callback function

void send_uart_command(uint8_t *pData, uint16_t size)
{
    if (HAL_UART_Transmit_IT(&hlpuart3, pData, size) != HAL_OK)
    {
        printf("Failed to send command\r\n");
    }
}

void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
	printf("Transfer completed callback\r\n");
}

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
  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);
    }
}

And below is the function whenever click button to send UART data

void button_pressed(void)
{
   uint8_t cmd_a[]={0x11, 0x22, 0x33, 0x44, 0x55};
   send_uart_command(cmd_a, sizeof(cmd_a));
   HAL_Delay(10);
   HAL_UART_Receive_IT(&hlpuart3, rx_data, sizeof(rx_data));
}

Do you have any suggestions to help me fix the issue?

 

Besides that, regard to the UART communication pattern, I was looking to achived like below, which was set CTS/RTS as default high instead of low, and it would also just switch to low status when data exchanged be required.

CYH_2-1749550371728.png

However, I am not sure how to modify MX_LPUART3_UART_Init to cover this.....

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 */

}

 

Thanks,
CY