From 9df11f147d1a3b4b3f1eb332a81890274883d5f2 Mon Sep 17 00:00:00 2001 From: Jon Waterschoot Date: Sun, 9 Aug 2026 02:18:44 +0200 Subject: [PATCH] Guard the handle in HAL_UART_ErrorCallback, and disarm the IDLE IRQ MapInstanceToHandle() returns NULL for any instance outside its list of 9 UART/USART peripherals, and f7c63aee writes through that pointer with no null check. The clearing of listener_mode_ also has to undo what DmaListenStart() armed. It enables the IDLE interrupt alongside setting the flag, and UART_IRQHandler acknowledges IDLE only inside its listener_mode_ branch -- ST's HAL does not touch the flag in HAL_UART_RECEPTION_STANDARD mode. So clearing the flag while IDLE stays enabled leaves the flag set with nobody left to clear it, and the UART interrupt re-asserts continuously. DmaListenStop() already disables both together; do the same here. Observed as a UART interrupt storm on hardware running TRS MIDI in continuously: floating-input framing noise starved I2C (OLED, touch) and USB while SAI-DMA audio kept running. --- src/per/uart.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/per/uart.cpp b/src/per/uart.cpp index f8900c06c..93e77ccc8 100644 --- a/src/per/uart.cpp +++ b/src/per/uart.cpp @@ -1104,8 +1104,17 @@ extern "C" void HAL_UART_RxHalfCpltCallback(UART_HandleTypeDef* huart) extern "C" void HAL_UART_ErrorCallback(UART_HandleTypeDef* huart) { - auto* handle = MapInstanceToHandle(huart->Instance); - handle->listener_mode_ = false; + auto* handle = MapInstanceToHandle(huart->Instance); + if(handle && handle->listener_mode_) + { + /** Listening has stopped: report that via IsListening(), and undo the + * IDLE interrupt DmaListenStart() enabled. Leaving IDLE armed while + * listener_mode_ is false means nothing ever clears the flag -- + * UART_IRQHandler only does so inside the listener branch -- and the + * interrupt re-asserts forever. DmaListenStop() disables both. */ + handle->listener_mode_ = false; + __HAL_UART_DISABLE_IT(huart, UART_IT_IDLE); + } UartHandler::Impl::DmaTransferFinished(huart, UartHandler::Result::ERR); }