cancel
Showing results for 
Search instead for 
Did you mean: 

Possible HAL Bug with SDMMC Init clock speeds in HAL_SD_InitCard

Michael_GetElectronic
Associate III

Possible Bug in HAL_SD_InitCard 

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

System Info

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! 

Background

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.

Symptoms 

uSD does not init correctly and does not return card info 

Cause 

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

Conditions to Replicate

Set:

 sdmmc_clk % 400000 != 0

Workaround 

Set:

 

 sdmmc_clk % 400000 == 0

 

Proposed Solution 

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.  

Footnote

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 

 

0 REPLIES 0