Bug Summary
HAL_SD_IRQHandler never reaches its error branch when a data error occurs
during an interrupt-mode transfer, causing the SD interrupt to refire forever
and lock up the system.
Detailed Description
In stm32h7xx_hal_sd.c, HAL_SD_IRQHandler() tests its conditions in a single
if / else if chain, and the FIFO branches come before the error branch:
void HAL_SD_IRQHandler(SD_HandleTypeDef *hsd)
{
/* Check for SDMMC interrupt flags */
if ((__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_RXFIFOHF) != RESET) && ((context & SD_CONTEXT_IT) != 0U))
{
SD_Read_IT(hsd);
}
...
else if ((__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_TXFIFOHE) != RESET) && ((context & SD_CONTEXT_IT) != 0U))
{
SD_Write_IT(hsd);
}
...
else if (__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_DCRCFAIL | SDMMC_FLAG_DTIMEOUT |
SDMMC_FLAG_RXOVERR | SDMMC_FLAG_TXUNDERR) != RESET)
{
/* error handling: never reached in the scenario below */
}
}
TXFIFOHE and RXFIFOHF are level-triggered status flags that cannot be
cleared by software — they only change when the FIFO is drained or filled. If a
data error (TXUNDERR, RXOVERR, DCRCFAIL, DTIMEOUT) occurs while such a
flag is asserted, the handler keeps taking the FIFO branch, the error branch is
never evaluated, the error flags are never cleared, and the interrupt refires
immediately and indefinitely.
A second, related problem: when the error branch does run, its
__HAL_SD_DISABLE_IT() mask does not include SDMMC_IT_TXFIFOHE /
SDMMC_IT_RXFIFOHF, so the IRQ line can remain asserted even after the error is
handled.
How it was observed. An SD card stopped accepting data mid-write (a physical
card fault; only a power cycle recovers it). The resulting TXUNDERR left
TXFIFOHE asserted and the board became completely unresponsive: the ISR
starved every thread, so networking and the console died while interrupts kept
firing. Diagnosed via SWD — the CPU was permanently inside HAL_SD_IRQHandler.
Suggested fix, which has been running in our firmware since 2026-07-10
(including a 10-minute stress test writing 512 KB blocks continuously while
acquiring sensor data, with no regression):
- skip the FIFO branches while any data error flag is pending, so the error
branch becomes reachable;
- add
SDMMC_IT_TXFIFOHE / SDMMC_IT_RXFIFOHF to the disable mask on the
error path.
The patch is proposed to the Zephyr HAL mirror as a temporary fix in
zephyrproject-rtos/hal_stm32#395, whose maintainer asked that the issue be
reported here first.
Note on other series. The same if / else if ordering is present in the
HAL_SD_IRQHandler of the STM32F7, H5, H7RS, L4, L5, MP13, MP2, N6, U3 and U5
drivers. I could only test on STM32H7.
Expected Behavior
A data error during an interrupt-mode transfer is handled: the error flags are cleared, the interrupts are disabled, and the transfer is aborted with the error reported to the application.
Actual Behavior
The error branch is never reached; the interrupt refires forever and starves the entire system, which requires a reset to recover.
Environment
STM32H747I-DISCO (STM32H747XI, Cortex-M7), STM32CubeH7 v1.12.1, SDMMC1 in interrupt mode (not IDMA), GCC (Zephyr SDK), Zephyr RTOS 4.4.1.
Severity
Critical
Bug Summary
HAL_SD_IRQHandlernever reaches its error branch when a data error occursduring an interrupt-mode transfer, causing the SD interrupt to refire forever
and lock up the system.
Detailed Description
In
stm32h7xx_hal_sd.c,HAL_SD_IRQHandler()tests its conditions in a singleif / else ifchain, and the FIFO branches come before the error branch:TXFIFOHEandRXFIFOHFare level-triggered status flags that cannot becleared by software — they only change when the FIFO is drained or filled. If a
data error (
TXUNDERR,RXOVERR,DCRCFAIL,DTIMEOUT) occurs while such aflag is asserted, the handler keeps taking the FIFO branch, the error branch is
never evaluated, the error flags are never cleared, and the interrupt refires
immediately and indefinitely.
A second, related problem: when the error branch does run, its
__HAL_SD_DISABLE_IT()mask does not includeSDMMC_IT_TXFIFOHE/SDMMC_IT_RXFIFOHF, so the IRQ line can remain asserted even after the error ishandled.
How it was observed. An SD card stopped accepting data mid-write (a physical
card fault; only a power cycle recovers it). The resulting
TXUNDERRleftTXFIFOHEasserted and the board became completely unresponsive: the ISRstarved every thread, so networking and the console died while interrupts kept
firing. Diagnosed via SWD — the CPU was permanently inside
HAL_SD_IRQHandler.Suggested fix, which has been running in our firmware since 2026-07-10
(including a 10-minute stress test writing 512 KB blocks continuously while
acquiring sensor data, with no regression):
branch becomes reachable;
SDMMC_IT_TXFIFOHE/SDMMC_IT_RXFIFOHFto the disable mask on theerror path.
The patch is proposed to the Zephyr HAL mirror as a temporary fix in
zephyrproject-rtos/hal_stm32#395, whose maintainer asked that the issue be
reported here first.
Note on other series. The same
if / else ifordering is present in theHAL_SD_IRQHandlerof the STM32F7, H5, H7RS, L4, L5, MP13, MP2, N6, U3 and U5drivers. I could only test on STM32H7.
Expected Behavior
A data error during an interrupt-mode transfer is handled: the error flags are cleared, the interrupts are disabled, and the transfer is aborted with the error reported to the application.
Actual Behavior
The error branch is never reached; the interrupt refires forever and starves the entire system, which requires a reset to recover.
Environment
STM32H747I-DISCO (STM32H747XI, Cortex-M7), STM32CubeH7 v1.12.1, SDMMC1 in interrupt mode (not IDMA), GCC (Zephyr SDK), Zephyr RTOS 4.4.1.
Severity
Critical