2021-12-31 02:32 AM
Dear all,
This is my first time using UART, sorry if the question is not relevant.
I configured through the Device Configuration Tool the initial code for a STM32H745, in which I use the UART 1 with interrupt.
Everything works fine for several hours, even a whole day, then suddenly the UART 1 transmits but does not receive.
I analyzed the SFR files and I noticed that the only anomalous thing is the EIE bit of CR3 which instead of being at 1 is at 0.
I don't understand how I can go about handling this thing, I have implemented an ErrorCallback but without resolving.
I understand that the information I have given you is limited, but I ask you for help at least to get out of the situation when it happens.
I enclose part of the code concerned
Thank you in advance
main.c:
MX_USART1_UART_Init();
---------------------------------
usart.c:
#include "usart.h"
UART_HandleTypeDef huart1;
void MX_USART1_UART_Init(void)
{
huart1.Instance = USART1;
huart1.Init.BaudRate = 115200;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
huart1.Init.Mode = UART_MODE_TX_RX;
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
huart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
huart1.Init.ClockPrescaler = UART_PRESCALER_DIV1;
huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
if (HAL_UART_Init(&huart1) != HAL_OK)
{
Error_Handler();
}
if (HAL_UARTEx_SetTxFifoThreshold(&huart1, UART_TXFIFO_THRESHOLD_1_8) != HAL_OK)
{
Error_Handler();
}
if (HAL_UARTEx_SetRxFifoThreshold(&huart1, UART_RXFIFO_THRESHOLD_1_8) != HAL_OK)
{
Error_Handler();
}
if (HAL_UARTEx_DisableFifoMode(&huart1) != HAL_OK)
{
Error_Handler();
}
}
void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
if(uartHandle->Instance==USART1)
{
/** Initializes the peripherals clock
*/
PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_USART1;
PeriphClkInitStruct.Usart16ClockSelection = RCC_USART16CLKSOURCE_D2PCLK2;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
{
Error_Handler();
}
/* USART1 clock enable */
__HAL_RCC_USART1_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
/**USART1 GPIO Configuration
PB6 ------> USART1_TX
PB7 ------> USART1_RX
*/
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_AF7_USART1;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/* USART1 interrupt Init */
HAL_NVIC_SetPriority(USART1_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(USART1_IRQn);
}
}
void HAL_UART_MspDeInit(UART_HandleTypeDef* uartHandle)
{
if(uartHandle->Instance==USART1)
{
__HAL_RCC_USART1_CLK_DISABLE();
/**USART1 GPIO Configuration
PB6 ------> USART1_TX
PB7 ------> USART1_RX
*/
HAL_GPIO_DeInit(GPIOB, GPIO_PIN_6|GPIO_PIN_7);
HAL_NVIC_DisableIRQ(USART1_IRQn);
}
}
------------------------
comm.cabs
COMM_DATA commData;
void COMM_ErrorCallback(UART_HandleTypeDef *huart)
{
uint32_t errore;
errore = HAL_UART_GetError(huart);
__HAL_UART_CLEAR_OREFLAG(huart);
__HAL_UART_CLEAR_NEFLAG(huart);
__HAL_UART_CLEAR_FEFLAG(huart);
__HAL_UART_DISABLE_IT(huart, UART_IT_ERR);
if(huart->Instance == UART_MODEM_INSTANCE)
{
HAL_UART_Receive_IT(UART_MODEM_HANDLE, (uint8_t*) &commData.modemRxChar, 1);
MONITOR_printf("%s %u\r\n","ERROR UART",errore);
}
}
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if(huart->Instance == UART_MODEM_INSTANCE)
{
COMM_WriteCodaRx(UART_MODEM_ID, commData.modemRxChar);
HAL_UART_Receive_IT(UART_MODEM_HANDLE, (uint8_t*) &commData.modemRxChar, 1);
}
}
void COMM_ModemInitialize(void)
{
MX_USART1_UART_Init();
commData.pntWrCodaTx[UART_MODEM_ID] = 0;
commData.pntRdCodaTx[UART_MODEM_ID] = 0;
commData.runTx[UART_MODEM_ID] = 0;
commData.pntWrCodaRx[UART_MODEM_ID] = 0;
commData.pntRdCodaRx[UART_MODEM_ID] = 0;
HAL_UART_Receive_IT(UART_MODEM_HANDLE, (uint8_t*) &commData.modemRxChar, 1);
}
2021-12-31 05:08 AM
This looks like RX overrun condition. The ST "HAL" library does not handle it well, even with error callbacks.
You'll have to detect it and clear, otherwise RX will be blocked.
See this issue https://github.com/STMicroelectronics/stm32h7xx_hal_driver/issues/17
(I don't quite understand their proposed workaround, the issue is not closed, maybe they still are pondering on it).
Anyway, HAL_UART_Receive_IT with size 1 is a bad idea, very prone to the overrun.
2022-01-01 11:07 AM
Thanks Pavel,
now i am doing some tests in debugger mode, and if the problem occurs, i will store all the values of the registers of the UART to try to understand better.
In any case, to restore operation, without making a total reset, it is sufficient to execute MX_USART1_UART_Init (); (see above) ?
Forward what do you mean when you write "HAL_UART_Receive_IT with size 1 is a bad idea .." do you think you should handle the whole byte (8)?
Could the problem occur the same way or am I wrong?
Thank you
2022-01-04 06:30 AM
Hi @DFont.1
> i will store all the values of the registers of the UART to try to understand better.
Only remember that reading RX data register is destructive and can cause Heisen-bugs.
> what do you mean when you write "HAL_UART_Receive_IT with size 1 is a bad idea .."
Review the source of HAL_UART_Receive_IT, you will see that it enables RX interrupt before receive and disables it upon exit.
This causes windows of time when the RX interrupt is disabled, so this is prone to both overrun and loss of data. (with any buffer size, but especially 1).
Instead consider continuous receive using circular DMA
or self-made UART interrupt handler (and enable the UART FIFO of STM32H7).