2025-11-07 7:50 AM - last edited on 2025-11-07 7:59 AM by Andrew Neil
hello
when i use UART Idle interupt with DMA on STM32H743XIH6 chip,i found ,the interupt function will run imediatly when HAL_UARTEx_ReceiveToIdle_DMA(&huart2, (uint8_t *)Uart2RxBuffer, 50)run,and this is my core code
MPU_Config();
// SCB_EnableICache();
// SCB_EnableDCache();
HAL_Init();
SystemClock_Config();
PeriphCommonClock_Config();
delay_init();
__HAL_RCC_BKPRAM_CLK_ENABLE();
HAL_PWR_EnableBkUpAccess();
MX_GPIO_Init();
User_GPIO_Init();
MX_DMA_Init();
MX_USART2_UART_Init();
HAL_UARTEx_ReceiveToIdle_DMA(&huart2, (uint8_t *)Uart2RxBuffer, 50);
///////////////////////////////////////////////////////////////////////////
UART_HandleTypeDef huart2;
DMA_HandleTypeDef hdma_usart2_rx;
/* USART2 init function */
void MX_USART2_UART_Init(void)
{
huart2.Instance = USART2;
huart2.Init.BaudRate = 115200;
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;
huart2.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
huart2.Init.ClockPrescaler = UART_PRESCALER_DIV1;
huart2.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
if (HAL_UART_Init(&huart2) != HAL_OK)
{
Error_Handler(__LINE__,__FILE__);
}
if (HAL_UARTEx_SetTxFifoThreshold(&huart2, UART_TXFIFO_THRESHOLD_1_8) != HAL_OK)
{
Error_Handler(__LINE__,__FILE__);
}
if (HAL_UARTEx_SetRxFifoThreshold(&huart2, UART_RXFIFO_THRESHOLD_1_8) != HAL_OK)
{
Error_Handler(__LINE__,__FILE__);
}
if (HAL_UARTEx_DisableFifoMode(&huart2) != HAL_OK)
{
Error_Handler(__LINE__,__FILE__);
}
/* USER CODE BEGIN USART2_Init 2 */
/* USER CODE END USART2_Init 2 */
}
void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
if(uartHandle->Instance==USART2)
{
PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_USART2;
PeriphClkInitStruct.Usart234578ClockSelection = RCC_USART234578CLKSOURCE_D2PCLK1;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
{
Error_Handler(__LINE__,__FILE__);
}
/* USART2 clock enable */
__HAL_RCC_USART2_CLK_ENABLE();
__HAL_RCC_GPIOD_CLK_ENABLE();
/**USART2 GPIO Configuration
PD5 ------> USART2_TX
PD6 ------> USART2_RX
*/
GPIO_InitStruct.Pin = GPIO_PIN_5|GPIO_PIN_6;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_MEDIUM;
GPIO_InitStruct.Alternate = GPIO_AF7_USART2;
HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
/* USART2 DMA Init */
/* USART2_RX Init */
hdma_usart2_rx.Instance = DMA1_Stream6;
hdma_usart2_rx.Init.Request = DMA_REQUEST_USART2_RX;
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_CIRCULAR;
hdma_usart2_rx.Init.Priority = DMA_PRIORITY_LOW;
hdma_usart2_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
if (HAL_DMA_Init(&hdma_usart2_rx) != HAL_OK)
{
Error_Handler(__LINE__,__FILE__);
}
__HAL_LINKDMA(uartHandle,hdmarx,hdma_usart2_rx);
HAL_NVIC_SetPriority(USART2_IRQn, 5, 0);
HAL_NVIC_EnableIRQ(USART2_IRQn);
}
}
void HAL_UART_MspDeInit(UART_HandleTypeDef* uartHandle)
{
if(uartHandle->Instance==USART2)
{
__HAL_RCC_USART2_CLK_DISABLE();
/**USART2 GPIO Configuration
PD5 ------> USART2_TX
PD6 ------> USART2_RX
*/
HAL_GPIO_DeInit(GPIOD, GPIO_PIN_5|GPIO_PIN_6);
HAL_DMA_DeInit(uartHandle->hdmarx);
HAL_NVIC_DisableIRQ(USART2_IRQn);
}
}
extern volatile uint8_t Uart2RxBuffer[50];
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
if(huart->Instance==USART2)
{
if(HAL_UART_RXEVENT_IDLE == HAL_UARTEx_GetRxEventType(huart))
{
printf("HAL_UART2_RXEVENT_IDLE:\r\n");
}
printf("HAL_UART2Ex_RxEventCallback:\r\n");
for(uint8_t i=0;i<50;i++)
{
printf("%c",Uart2RxBuffer[i]);
}
printf("(%d)\r\n",Size);
}
}
when power on or reset,the code that
HAL_UART2_RXEVENT_IDLE:
HAL_UART2Ex_RxEventCallback:
(50)
happen,and then i send "123456789"many times,it runs normal,why chip power on or reset it interupt imediatly,and size equals to HAL_UARTEx_ReceiveToIdle_DMA config size
Edited to apply source code formatting - please see How to insert source code for future reference.
2025-11-07 8:32 AM
It doesn't do this for me with a clean project, default settings, using the latest library.
Try using a weak pullup on the RX line.
Include the full compileable project if you can. Gotta be something in there to explain it. Nothing wrong with the code presented as far as I can see.
2025-11-07 9:01 AM
2025-11-07 10:59 AM
With STM32H7 you most likely want to enable RTO (receive timeout) rather than the idle event.
Why the idle event can occur immediately? Because the receiver is idle. Use the RTO.
2025-11-15 7:25 PM
I am having what seems to be the same problem using the NUCLEO-H723ZG. The first DMA capture works properly and the IDLE interrupt fires which causes HAL_UARTEx_RxEventCallback() to be called where I call HAL_UARTEx_ReceiveToIdle_DMA() to initiate the next receive. After I send it another string it appears that an interrupt would occur, but no interrupt happens. These are the registers when I halt it after sending it the second string:
huart3->Instance->CR1 volatile uint32_t 0x1d (Hex)
huart3->Instance->CR2 volatile uint32_t 0x0 (Hex)
huart3->Instance->CR3 volatile uint32_t 0xa0002041 (Hex)
huart3->Instance->ISR volatile uint32_t 0x6010d0 (Hex)
Note that the idle interrupt bit is set, and the idle interrupt is enabled. HAL_UARTEx_ReceiveToIdle_DMA() clears the idle interrupt flag from the first string which was sent and correctly handled. This looks like perhaps a problem with the chip to me. Baud rate is 115200, CPU 400MHz. I did have this working earlier with the CPU at 550MHz.