2025-09-29 5:35 PM
Hello wonderful STM community!
I have identified a possible bug in the HAL Layer for the SDMMC peripheral. First time filing a bug report so please let me know if I miss anything import or if I'm completely wrong
MCU: STM32H5
Firmware Package: STM32Cube FW_H5 V1.5.0
Board: Custom
CubeIDE Version: 1.18.1
Please ask if anything else should be included here!
For a (u)SD to init it needs the clock speed to be slowed down to 400 kHz or lower, init commands and are then sent before the clock is then taken back up to speed. See this electrical engineering post for a good explanation and further reading.
uSD does not init correctly and does not return card info
In the file stm32h5xx_hal_sd.c (under HAL Drivers) and the function:
HAL_StatusTypeDef HAL_SD_InitCard(SD_HandleTypeDef *hsd)
There are two relevant lines:
Line 494:
Init.ClockDiv = sdmmc_clk / (2U * SD_INIT_FREQ);
Line 519:
sdmmc_clk = sdmmc_clk / (2U * Init.ClockDiv);
In Line 494 the division will round down which can result in a clockDiv that will clock the SD slightly above the required 400 kHz. See calculations bellow:
sdmmc_clk = 3000000 (3 MHz)
SD_INIT_FREQ = 400000 (400 kHz)
Init.ClockDiv = 3000000 (3 MHz) / (2U * 400000 (400 kHz));
Init.ClockDiv = 3.75 // This will be rounded down to 3
sdmmc_clk = 3000000/ (2U * 3);
sdmmc_clk = 500000 (500 kHz) // Greater then SD_INIT_FREQ of 400 kHz
// If we use the actual ClockDiv of 3.75:
sdmmc_clk = 3000000/ (2U * 3.75);
sdmmc_clk = 400000 (400 kHz) // Matches SD_INIT_FREQ of 400 kHz
Set:
sdmmc_clk % 400000 != 0
Set:
sdmmc_clk % 400000 == 0
if (sdmmc_clk % SD_INIT_FREQ != 0)
Init.ClockDiv = sdmmc_clk / (2U * SD_INIT_FREQ) + 1;
else:
Init.ClockDiv = sdmmc_clk / (2U * SD_INIT_FREQ)
If the clk can't be divided down to 400 kHz with a clockDiv, divide it down as close as possible then to insure the result frequency will be less then 400 kHz add one to the clockDiv so that the sdmmc is clocked down bellow 400 kHz .
If it can be divided down to exactly 400 kHz (preferred) then do so.
Again, I'm a mere second year computer engineer so I might be completely wrong with the above so please bare with me and provide constructive feedback.
Cheers,
Michael
Solved! Go to Solution.
2025-10-08 9:31 AM
Hello Michael,
Good catch! Indeed, the initialization card in the previous version cannot proceed with the sequence initialization for frequencies below or equal to 3 MHz. Therefore, we first need to check if the frequency is below SD_INIT_FREQ.
In this condition, the clock divider should be set to 0. Otherwise, it should be calculated as:
Init.ClockDiv = (sdmmc_clk / (2U * SD_INIT_FREQ)) + 1
The logic can be expressed as:
if (sdmmc_clk = < SD_INIT_FREQ )
{
Init.ClockDiv = 0U;
}
else
{
Init.ClockDiv = (sdmmc_clk / (2U * SD_INIT_FREQ)) + 1;
}
Br,
Ahmed
2025-10-08 9:31 AM
Hello Michael,
Good catch! Indeed, the initialization card in the previous version cannot proceed with the sequence initialization for frequencies below or equal to 3 MHz. Therefore, we first need to check if the frequency is below SD_INIT_FREQ.
In this condition, the clock divider should be set to 0. Otherwise, it should be calculated as:
Init.ClockDiv = (sdmmc_clk / (2U * SD_INIT_FREQ)) + 1
The logic can be expressed as:
if (sdmmc_clk = < SD_INIT_FREQ )
{
Init.ClockDiv = 0U;
}
else
{
Init.ClockDiv = (sdmmc_clk / (2U * SD_INIT_FREQ)) + 1;
}
Br,
Ahmed
2025-10-08 10:18 AM - edited 2025-10-08 10:36 AM
Hi,
> uSD does not init correctly and does not return card info
yea, this is typical a hardware problem. Not a HAL problem.
The SD-card (every...) can work on this sdmmc interface at 50MHz clock.
And the sdmmc module doing the init for the card, typical at 400kHz itself.
So the (hardware) critical point is: after first communication, the clk speed is switched to full speed,
for the data transfer - This is where the wheat is separated from the chaff.
If the signal has bad CRC at this speed, nothing happens, just error and finish.
+
Just for H563 (i have this) : it worked good with pin setting to medium speed and pullups ON, on all lines;
and at first only use 1bit mode, its more tolerant to reflections etc on the line.
Try...