2024-07-17 01:36 PM
We are using two STM32 platforms, one is running STM32H735RGV6 and the other is running STM32F103C8T6, they are connected by a single wire and connecting as UART Half Duplex.
Note that we did make it work in a UART in full duplex mode for STM32F103C8T6 previously without any problem using another platform.
The STM32H735RGV6 is transmitting messages as expected, we do not know it by seeing bytes using a logic analyzer, and we do not know if it can receive yet, and it is configured as this:
=======
huart7.Instance = UART7;
huart7.Init.BaudRate = 19200;
huart7.Init.WordLength = UART_WORDLENGTH_8B;
huart7.Init.StopBits = UART_STOPBITS_1;
huart7.Init.Parity = UART_PARITY_NONE;
huart7.Init.Mode = UART_MODE_TX_RX;
huart7.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart7.Init.OverSampling = UART_OVERSAMPLING_16;
huart7.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
huart7.Init.ClockPrescaler = UART_PRESCALER_DIV1;
huart7.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
if (HAL_HalfDuplex_Init(&huart7) != HAL_OK)
{
error_handler();
}
if (HAL_UARTEx_SetTxFifoThreshold(&huart7, UART_TXFIFO_THRESHOLD_1_8) != HAL_OK)
{
error_handler();
}
if (HAL_UARTEx_SetRxFifoThreshold(&huart7, UART_RXFIFO_THRESHOLD_1_8) != HAL_OK)
{
error_handler();
}
if (HAL_UARTEx_DisableFifoMode(&huart7) != HAL_OK)
{
error_handler();
}
if (HAL_HalfDuplex_EnableReceiver(&huart7) != HAL_OK)
{
error_handler();
}
=======
if(huart->Instance==UART7)
{
/* USER CODE BEGIN UART7_MspInit 0 */
/* USER CODE END UART7_MspInit 0 */
/** Initializes the peripherals clock
*/
PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_UART7;
PeriphClkInitStruct.Usart234578ClockSelection = RCC_USART234578CLKSOURCE_D2PCLK1;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
{
error_handler();
}
/* Peripheral clock enable */
__HAL_RCC_UART7_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
/**UART7 GPIO Configuration
PA15(JTDI) ------> UART7_TX
*/
GPIO_InitStruct.Pin = UART7_HD_TO_FOX_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF11_UART7;
HAL_GPIO_Init(UART7_HD_TO_FOX_GPIO_Port, &GPIO_InitStruct);
/* UART7 DMA Init */
/* UART7_RX Init */
hdma_uart7_rx.Instance = DMA1_Stream7;
hdma_uart7_rx.Init.Request = DMA_REQUEST_UART7_RX;
hdma_uart7_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_uart7_rx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_uart7_rx.Init.MemInc = DMA_MINC_ENABLE;
hdma_uart7_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_uart7_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_uart7_rx.Init.Mode = DMA_NORMAL;
hdma_uart7_rx.Init.Priority = DMA_PRIORITY_LOW;
hdma_uart7_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
if (HAL_DMA_Init(&hdma_uart7_rx) != HAL_OK)
{
error_handler();
}
__HAL_LINKDMA(huart,hdmarx,hdma_uart7_rx);
/* UART7_TX Init */
hdma_uart7_tx.Instance = DMA2_Stream0;
hdma_uart7_tx.Init.Request = DMA_REQUEST_UART7_TX;
hdma_uart7_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
hdma_uart7_tx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_uart7_tx.Init.MemInc = DMA_MINC_ENABLE;
hdma_uart7_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_uart7_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_uart7_tx.Init.Mode = DMA_NORMAL;
hdma_uart7_tx.Init.Priority = DMA_PRIORITY_LOW;
hdma_uart7_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
if (HAL_DMA_Init(&hdma_uart7_tx) != HAL_OK)
{
error_handler();
}
__HAL_LINKDMA(huart,hdmatx,hdma_uart7_tx);
/* UART7 interrupt Init */
HAL_NVIC_SetPriority(UART7_IRQn, 5, 0);
HAL_NVIC_EnableIRQ(UART7_IRQn);
/* USER CODE BEGIN UART7_MspInit 1 */
/* USER CODE END UART7_MspInit 1 */
}
=======
Sending like this:
if (HAL_HalfDuplex_EnableTransmitter(&huart7) != HAL_OK)
{
error_handler();
}
HAL_StatusTypeDef ret = HAL_UART_Transmit_DMA(&huart7, pData, size);
The STM32F103C8T6 is not receiving or transmitting messages, we tried a few variation of the configuration, but we cannot get it to work and only getting into worst condition. So, here is the best configuration according to us:
huart2.Instance = USART2;
huart2.Init.BaudRate = 19200;
huart2.Init.WordLength = UART_WORDLENGTH_8B;
huart2.Init.StopBits = UART_STOPBITS_1;
huart2.Init.Parity = UART_PARITY_NONE;
huart2.Init.Mode = UART_MODE_TX_RX;
huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart2.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_HalfDuplex_Init(&huart2) != HAL_OK)
{
error_handler();
}
if (HAL_HalfDuplex_EnableReceiver(&huart2) != HAL_OK)
{
error_handler();
}
=======
if(uartHandle->Instance==USART2)
{
/* USER CODE BEGIN USART2_MspInit 0 */
/* USER CODE END USART2_MspInit 0 */
/* USART2 clock enable */
__HAL_RCC_USART2_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
/**USART2 GPIO Configuration
PA2 ------> USART2_TX
PA3 ------> USART2_RX
*/
GPIO_InitStruct.Pin = USART2_HF_TO_PA_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(USART2_HF_TO_PA_GPIO_Port, &GPIO_InitStruct);
GPIO_InitStruct.Pin = USART2_HF_TO_PA_Pin2;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(USART2_HF_TO_PA_GPIO_Port2, &GPIO_InitStruct);
/* USART2 DMA Init */
/* USART2_RX Init */
hdma_usart2_rx.Instance = DMA1_Channel6;
hdma_usart2_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_usart2_rx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_usart2_rx.Init.MemInc = DMA_MINC_ENABLE;
hdma_usart2_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_usart2_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_usart2_rx.Init.Mode = DMA_NORMAL;
hdma_usart2_rx.Init.Priority = DMA_PRIORITY_LOW;
if (HAL_DMA_Init(&hdma_usart2_rx) != HAL_OK)
{
error_handler();
}
__HAL_LINKDMA(uartHandle,hdmarx,hdma_usart2_rx);
/* USART2_TX Init */
hdma_usart2_tx.Instance = DMA1_Channel7;
hdma_usart2_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
hdma_usart2_tx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_usart2_tx.Init.MemInc = DMA_MINC_ENABLE;
hdma_usart2_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_usart2_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_usart2_tx.Init.Mode = DMA_NORMAL;
hdma_usart2_tx.Init.Priority = DMA_PRIORITY_LOW;
if (HAL_DMA_Init(&hdma_usart2_tx) != HAL_OK)
{
error_handler();
}
__HAL_LINKDMA(uartHandle,hdmatx,hdma_usart2_tx);
/* USART2 interrupt Init */
HAL_NVIC_SetPriority(USART2_IRQn, 5, 0);
HAL_NVIC_EnableIRQ(USART2_IRQn);
/* USER CODE BEGIN USART2_MspInit 1 */
=======
Same code for TX
=======
if (HAL_HalfDuplex_EnableReceiver(&huart2) != HAL_OK)
{
error_handler();
}
HAL_StatusTypeDef ret = HAL_UARTEx_ReceiveToIdle_DMA(&huart2,
&(gRxDataBuffer[gRxDataBufferIndex][0]),
UART_BUFFER_SIZE);
======
HAL_UARTEx_RxEventCallback(), HAL_UART_RxCpltCallback() or HAL_UART_ErrorCallback() are never called.
We would like to know what is wrong into our configuration, on either side?
We noticed that there are no call to HAL_RCCEx_PeriphCLKConfig() for STM32F103C8T6 nor that the field GPIO_InitStruct.Alternate is set when compared to STM32H735RGV6.
We did use STM32CubeIDE, Version: 1.16.0, Build: 21983_20240628_1741 (UTC) to generate both code.
Solved! Go to Solution.
2024-07-22 10:42 AM
Thanks all,
We have found the problem, we were trying to use PIN3 of GPIOA for Half Duplex as it was the RX pin for the Full Duplex, but we need to use the TX pin aka PIN2 of GPIOA in Half Duplex.
On the hardware, for Half Duplex, we need to plug the TX Pin of the STM32F103C8T6 to the TX Pin STM32H735RGV6 rather than, as for Full Duplex, the TX Pin to the RX Pin and the RX Pin to the TX Pin.
Regards
2024-07-19 03:27 AM - edited 2024-07-19 03:36 AM
Hello @SylvainQuaze ,
The following configurations are taken from the example UART_TwoBoards_ComDMA.
Could you please update your code to be aligned with these setting:
/*##-2- Configure peripheral GPIO ##########################################*/
/* UART TX GPIO pin configuration */
GPIO_InitStruct.Pin = USARTx_TX_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(USARTx_TX_GPIO_PORT, &GPIO_InitStruct);
/* UART RX GPIO pin configuration */
GPIO_InitStruct.Pin = USARTx_RX_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
HAL_GPIO_Init(USARTx_RX_GPIO_PORT, &GPIO_InitStruct);
Please refer to the example for more details.
2024-07-19 05:51 AM
Unfortunately, the example you are referring is a full duplex example using HAL_UART_Init() and we have no problem in full duplex mode. We have problem when using half duplex (HAL_HalfDuplex_Init()).
2024-07-19 07:54 AM
Hello @SylvainQuaze,
Could you try with this code attached. I tested it in my side it sent data without issue.
2024-07-22 08:28 AM
Hi sorry for the delay, we were working on a Plan B on Friday, aka UART one direction but configured in Full Duplex on a single wire. Not ideal as one side can not reply.
Now back on making half duplex work.
The transmission in half duplex works fine from the STM32H735RGV6.
GPIO_InitStruct.Pin = GPIO_PIN_15;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF11_UART7;
HAL_GPIO_Init(UART7_HD_TO_FOX_PORT, &GPIO_InitStruct);
But the STM32F103C8T6 is now reporting framing error HAL_UART_ERROR_FE after the transmission of a few frames.
GPIO_InitStruct.Pin = USART2_HF_TO_PA_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(USART2_HF_TO_PA_GPIO_PORT, &GPIO_InitStruct);
Could the usage of the DMA caused the problems?
/* USART2 DMA Init */
/* USART2_RX Init */
hdma_usart2_rx.Instance = DMA1_Channel6;
hdma_usart2_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_usart2_rx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_usart2_rx.Init.MemInc = DMA_MINC_ENABLE;
hdma_usart2_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_usart2_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_usart2_rx.Init.Mode = DMA_NORMAL;
hdma_usart2_rx.Init.Priority = DMA_PRIORITY_VERY_HIGH;
if (HAL_DMA_Init(&hdma_usart2_rx) != HAL_OK)
{
quazeErrorHandler();
}
__HAL_LINKDMA(uartHandle,hdmarx,hdma_usart2_rx);
/* USART2_TX Init */
hdma_usart2_tx.Instance = DMA1_Channel7;
hdma_usart2_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
hdma_usart2_tx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_usart2_tx.Init.MemInc = DMA_MINC_ENABLE;
hdma_usart2_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_usart2_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_usart2_tx.Init.Mode = DMA_NORMAL;
hdma_usart2_tx.Init.Priority = DMA_PRIORITY_LOW;
if (HAL_DMA_Init(&hdma_usart2_tx) != HAL_OK)
{
quazeErrorHandler();
}
__HAL_LINKDMA(uartHandle,hdmatx,hdma_usart2_tx);
2024-07-22 08:51 AM
Framing error presumably coming from the Receive side, should perhaps clear any pending errors before proceeding. There should be an RE (Receive Enable) bit on the USART CR, I'd expect that to gate reception.
Not sure on the Two Wire usage here, surely Half-Duplex can be gated in software by listening vs receiving as two distinct states, and waiting for TC to indicate all the transmission has crossed the wire.
Half-Duplex frequently assumes you're using a single wire, like RS485, and the transmit loops back to the receive side
2024-07-22 09:14 AM
Yes, the Framing error is reported by the Receive side on STM32F103C8T6.
Yes, we are using Half Duplex because we have a single wire to transmit/receive data.
We are calling HAL_HalfDuplex_EnableReceiver() (this should set RE (Receive Enable)) before calling HAL_UARTEx_ReceiveToIdle_IT() or HAL_UARTEx_ReceiveToIdle_DMA(), same framing error with or without DMA.
We are also calling HAL_HalfDuplex_EnableReceiver() and HAL_UARTEx_ReceiveToIdle_X() after transmission in HAL_UART_TxCpltCallback().
Does the hardware wire requires a pull-up/pull-down for Half-Duplex that is not require for Full Duplex? We are using our own hardware.
2024-07-22 10:42 AM
Thanks all,
We have found the problem, we were trying to use PIN3 of GPIOA for Half Duplex as it was the RX pin for the Full Duplex, but we need to use the TX pin aka PIN2 of GPIOA in Half Duplex.
On the hardware, for Half Duplex, we need to plug the TX Pin of the STM32F103C8T6 to the TX Pin STM32H735RGV6 rather than, as for Full Duplex, the TX Pin to the RX Pin and the RX Pin to the TX Pin.
Regards