2025-06-13 7:32 AM
Hello everyone on the forum.
I have created a UART DMA receive program with Nucle-H723.
This time it is working properly, but sometimes it does not work properly.
DMA set up in normal mode on UART4 RX.
DMA initialization function of UART.
void UART_DMA_Init(UART_HandleTypeDef *huart)
{
UART_HandleTypeDef *pHuart = huart;
memset(RxBuf, 0, UART_BUF_LEN);
__HAL_UART_DISABLE_IT(pHuart, UART_IT_PE);
__HAL_UART_DISABLE_IT(pHuart, UART_IT_ERR);
__HAL_UART_ENABLE_IT(pHuart, UART_IT_IDLE);
HAL_UART_Receive_DMA(pHuart, RxBuf, UART_BUF_LEN);
}
UART DMA receive processing function.
void UART_DMA_EventHandler(UART_HandleTypeDef *huart)
{
UART_HandleTypeDef *pHuart = huart;
uint8_t RxData[UART_BUF_LEN];
if(__HAL_UART_GET_FLAG(pHuart, UART_FLAG_IDLE) != RESET)
{
__HAL_UART_CLEAR_IDLEFLAG(pHuart);
HAL_UART_DMAStop(pHuart);
uint8_t RxBufLen = __HAL_DMA_GET_COUNTER(pHuart->hdmarx);
RxBufLen = UART_BUF_LEN - RxBufLen;
RxBufLen = RxBufLen % UART_BUF_LEN;
if(RxBufLen > 0)
{
memcpy(RxData, RxBuf, RxBufLen);
printf(" Rx Len : %d \n", RxBufLen);
}
HAL_UART_Receive_DMA(pHuart, RxBuf, UART_BUF_LEN);
}
}
Initialization process is performed in main.c
MX_GPIO_Init();
MX_DMA_Init();
MX_UART4_Init();
MX_USART3_UART_Init();
UART_DMA_Init(&huart4); // Add function
while (1)
{
}
Receive processing is executed in UART4_IRQHandler of stm32h7xx.c
void UART4_IRQHandler(void)
{
UART_DMA_EventHandler(&huart4); // Add function
HAL_UART_IRQHandler(&huart4);
}
Now, when data is received on UART4, the receiving process will work regardless of the length of the data.
Basically, this works well, but sometimes there is unintended behavior.
Specifically, data is stored after the previously received data, instead of being received from the beginning of the receive buffer.
I checked the register.
Before stopping DMA, CR register is 0x10041F.
After DMA is stopped, the CR register is set to 0x100400.
It does not change from 0x10041F when an abnormality is occurring.
When DMA reception was finally resumed, the CR register was set to 0x10041F and the NDTR register was reset to 0x40.
In case of an error, the NDTR register remains at 0x38, so the reception starts from the continuation of the previous reception.
If the 0-4 bit of the CR register is not cleared when DMA reception is stopped by HAL_UART_DMAStop, should I manually turn off the register?
Anyone can give me some advice.
Please.
2025-06-13 7:44 AM
If IDLE is important to you, use HAL_UARTEx_ReceiveToIdle and implement the HAL_UARTEx_RxEventCallback callback to process the HT/TC and IDLE events.
You're processing the IDLE flag within a DMA interrupt, which doesn't make sense to do. The DMA interrupt is not called when IDLE is asserted.