cancel
Showing results for 
Search instead for 
Did you mean: 

CubeMX generates bad code for UART in half duplex

danmcb
Associate II

hello,

I am working on a design using MB1684 with STM32C011 as target. I configured UART2 as half duplex, TX only, so that I could use it for debugging, and I discovered that CubMX generates code which causes the board to hang, because it waits for both TX and RX sides to be ready. It is necessary to manually correct the generated code to have a working board.

Below is the generated code and the correction:

 

 

static void MX_USART2_UART_Init(void)
{

  /* USER CODE BEGIN USART2_Init 0 */

  /* USER CODE END USART2_Init 0 */

  LL_USART_InitTypeDef USART_InitStruct = {0};

  LL_GPIO_InitTypeDef GPIO_InitStruct = {0};

  /* Peripheral clock enable */
  LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_USART2);

  LL_IOP_GRP1_EnableClock(LL_IOP_GRP1_PERIPH_GPIOA);
  /**USART2 GPIO Configuration
  PA2   ------> USART2_TX
  */
  GPIO_InitStruct.Pin = DBG_UART_Pin;
  GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
  GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_LOW;
  GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_OPENDRAIN;
  GPIO_InitStruct.Pull = LL_GPIO_PULL_UP;
  GPIO_InitStruct.Alternate = LL_GPIO_AF_1;
  LL_GPIO_Init(DBG_UART_GPIO_Port, &GPIO_InitStruct);

  /* USER CODE BEGIN USART2_Init 1 */

  /* USER CODE END USART2_Init 1 */
  USART_InitStruct.PrescalerValue = LL_USART_PRESCALER_DIV1;
  USART_InitStruct.BaudRate = 19200;
  USART_InitStruct.DataWidth = LL_USART_DATAWIDTH_8B;
  USART_InitStruct.StopBits = LL_USART_STOPBITS_1;
  USART_InitStruct.Parity = LL_USART_PARITY_NONE;
  USART_InitStruct.TransferDirection = LL_USART_DIRECTION_TX;
  USART_InitStruct.OverSampling = LL_USART_OVERSAMPLING_16;
  LL_USART_Init(USART2, &USART_InitStruct);
  LL_USART_ConfigHalfDuplexMode(USART2);

  /* USER CODE BEGIN WKUPType USART2 */

  /* USER CODE END WKUPType USART2 */

  LL_USART_Enable(USART2);

  /* Polling USART2 initialisation */
  //while((!(LL_USART_IsActiveFlag_TEACK(USART2))) || (!(LL_USART_IsActiveFlag_REACK(USART2))))
  //{
  //}
  /* USER CODE BEGIN USART2_Init 2 */
  // the generated code in half duplex mode has a bug, it waits for a receive flag which is never set
  // below is the corrected version (original is commented out directly above)
  while(!(LL_USART_IsActiveFlag_TEACK(USART2)))
  {
  }
  /* USER CODE END USART2_Init 2 */

}

 

 

it is quite annoying as it is necessary to do this every time you re-generate the code. ST Employees please confirm that this is a bug, not some misconfiguration on my part? Thank you.

 

1 REPLY 1

For F0, the Cube-generated initialisation code leaves both TX and RX enabled - which is clearly not valid for half duplex.

I found that simply disabling RX allowed TX to work:

 

// The Generated initialisation code for USART2 (the Debug UART) leaves both
// transmitter & receiver enabled!
// As it's single-wire half-duplex, this is clearly not a valid state!
// Disable the receiver.
#if 0
    HAL_HalfDuplex_EnableTransmitter(&DBG_UART_HANDLE); // also disables receiver
#else
    LL_USART_DisableDirectionRx( DBG_UART_HANDLE.Instance );
#endif

 

I did that in my user code - so it doesn't get lost every time you re-generate the code.

 

PS:

Found it:

https://community.st.com/t5/stm32-mcus-embedded-software/stm32f0-uart-single-wire-half-duplex-incorrect-initialisation/m-p/579699