STM32 UART + DMA + IDLE中斷使用中的幀錯誤(FE)問題及解決方案
在我調試STM32H7串口空閑中斷DMA接受時遇到了一個bug,這個現象發生在系統剛上電時,有個串口由于幀錯誤FE掛起了中斷,之后在HAL_UART_IRQHandler這個全局中斷處理函數結束后,所有的中斷使能標志位都被清除了,經過反復調試發現以下問題:
- 上電初始化后,串口的 幀錯誤標志(FE) 會被意外觸發,導致系統進入中斷。
- 在中斷處理中,由于 EIE(錯誤中斷使能位) 被清除,導致幀錯誤的處理沒有進入預期的
HAL_UART_ErrorCallback
函數。 - 當 DMA 被停止時,空閑中斷功能(
IDLEIE
)也被清除,后續數據接收無法正常觸發空閑中斷。
這是一個隱藏較深的問題,目前尚無直接的參考案例。
問題分析
通過對 HAL 庫源碼和中斷流程的分析,發現問題的根源如下:
-
幀錯誤(FE)觸發中斷:
-
幀錯誤通常發生在上電階段,可能是由于串口初始化前的干擾或接收了無效數據。
-
幀錯誤會觸發中斷,但由于 HAL 中的錯誤處理邏輯,
UART_EndRxTransfer
會清除EIE
和IDLEIE
,導致后續的錯誤無法觸發中斷。HAL_UART_IRQHandler中的UART_EndRxTransfer函數導致所有中斷使能標志位被清除
進入這個函數的原因是因為我是用DMA來傳輸數據,如果這時候發生了任何錯誤,都會進入這個函數,看看這個函數原型
/*** @brief End ongoing Rx transfer on UART peripheral (following error detection or Reception completion).* @param huart UART handle.* @retval None*/ static void UART_EndRxTransfer(UART_HandleTypeDef *huart) {/* Disable RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts */ATOMIC_CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE_RXFNEIE | USART_CR1_PEIE));ATOMIC_CLEAR_BIT(huart->Instance->CR3, (USART_CR3_EIE | USART_CR3_RXFTIE)
-