cancel
Showing results for 
Search instead for 
Did you mean: 

STM32H743XI SDMMC1 SD Card - HAL_SD_ERROR_UNSUPPORTED_FEATURE

LB.2
Associate II

Hello,

I'm currently facing an issue with a basic project to setup the SDMMC1 peripheral where the function HAL_SD_Init() fails. The issue is happening inside HAL_SD_Init(), in SD_PowerON(), where it always returns HAL_SD_ERROR_UNSUPPORTED_FEATURE.

0693W00000Y8g2QQAR.png 

I'm using a custom board with the STM32H743XI MCU with an external clock of 26MHz and the STM32CubeH7_FW_H7_V1.11.0 package.

Please find below a picture of the STM32CubeMX Clock configuration:

0693W00000Y8g0PQAR.png0693W00000Y8g0jQAB.pngHere is the code that setup the clock:

void hw_port_clock_init(void)
{
    hw_clock_system_clock_init();
    hw_clock_init_peripheral_clocks();
}
static void hw_clock_system_clock_init(void)
{
    RCC_OscInitTypeDef RCC_OscInitStruct = { 0 };
    RCC_ClkInitTypeDef RCC_ClkInitStruct = { 0 };
 
    // Supply configuration update enable
    HAL_PWREx_ConfigSupply(PWR_LDO_SUPPLY);
 
    // Configure the main internal regulator output voltage
    __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
    while(!__HAL_PWR_GET_FLAG(PWR_FLAG_VOSRDY))
    {
    }
 
    __HAL_RCC_SYSCFG_CLK_ENABLE();
 
    __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE0);
    while(!__HAL_PWR_GET_FLAG(PWR_FLAG_VOSRDY))
    {
    }
 
    // Initializes the RCC Oscillators according to the specified parameters in the 
    RCC_OscInitTypeDef structure.
    RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
    RCC_OscInitStruct.HSEState = RCC_HSE_ON;
    RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
    RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
    RCC_OscInitStruct.PLL.PLLM = 13;
    RCC_OscInitStruct.PLL.PLLN = 480;
    RCC_OscInitStruct.PLL.PLLP = 2;
    RCC_OscInitStruct.PLL.PLLQ = 24;
    RCC_OscInitStruct.PLL.PLLR = 2;
    RCC_OscInitStruct.PLL.PLLRGE = RCC_PLL1VCIRANGE_1;
    RCC_OscInitStruct.PLL.PLLVCOSEL = RCC_PLL1VCOWIDE;
    RCC_OscInitStruct.PLL.PLLFRACN = 0;
    assert_param(HAL_RCC_OscConfig(&RCC_OscInitStruct) == HAL_OK);
 
    // Initializes the CPU, AHB and APB buses clocks
    RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_PCLK1 |
                                  RCC_CLOCKTYPE_PCLK2 | RCC_CLOCKTYPE_D3PCLK1 |
                                  RCC_CLOCKTYPE_D1PCLK1;
    RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
    RCC_ClkInitStruct.SYSCLKDivider = RCC_SYSCLK_DIV1;
    RCC_ClkInitStruct.AHBCLKDivider = RCC_HCLK_DIV2;
    RCC_ClkInitStruct.APB3CLKDivider = RCC_APB3_DIV2;
    RCC_ClkInitStruct.APB1CLKDivider = RCC_APB1_DIV2;
    RCC_ClkInitStruct.APB2CLKDivider = RCC_APB2_DIV2;
    RCC_ClkInitStruct.APB4CLKDivider = RCC_APB4_DIV2;
 
    assert_param(HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) == HAL_OK);
}
static void hw_clock_init_peripheral_clocks(void)
{
    RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = { 0 };
    PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SDMMC;
    PeriphClkInitStruct.SdmmcClockSelection = RCC_SDMMCCLKSOURCE_PLL;
    assert_param(HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) == HAL_OK);
 
    // Enable GPIOs clock
    __HAL_RCC_GPIOB_CLK_ENABLE();
    __HAL_RCC_GPIOC_CLK_ENABLE();
    __HAL_RCC_GPIOD_CLK_ENABLE();
    __HAL_RCC_GPIOF_CLK_ENABLE();
    __HAL_RCC_GPIOH_CLK_ENABLE();
 
    // Enable SDIO clock
    __HAL_RCC_SDMMC1_CLK_ENABLE();
}

Ans here is the SDMMC1 init code (4bits wide bus):

void hw_port_sd_init(void)
{
/** SDMMC1 GPIO Configuration
    PC8     ------> SDMMC1_D0
    PC9     ------> SDMMC1_D1
    PC10    ------> SDMMC1_D2
    PC11    ------> SDMMC1_D3
    PC12    ------> SDMMC1_CK
    PD2     ------> SDMMC1_CMD
*/
    GPIO_InitTypeDef gpio_init_structure = { 0 };
 
    gpio_init_structure.Pin = GPIO_MICROSD_D0_PIN | GPIO_MICROSD_D1_PIN | GPIO_MICROSD_D2_PIN |
                              GPIO_MICROSD_D3_PIN | GPIO_MICROSD_CLK_PIN;
    gpio_init_structure.Mode = GPIO_MODE_AF_PP;
    gpio_init_structure.Pull = GPIO_NOPULL;
    gpio_init_structure.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    gpio_init_structure.Alternate = GPIO_AF12_SDIO1;
    HAL_GPIO_Init(GPIOC, &gpio_init_structure);
 
    gpio_init_structure.Pin = GPIO_MICROSD_CMD_PIN;
    gpio_init_structure.Mode = GPIO_MODE_AF_PP;
    gpio_init_structure.Pull = GPIO_NOPULL;
    gpio_init_structure.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    gpio_init_structure.Alternate = GPIO_MICROSD_CMD_AF;
    HAL_GPIO_Init(GPIO_MICROSD_CMD_PORT, &gpio_init_structure);
 
    __HAL_RCC_SDMMC1_FORCE_RESET();
    __HAL_RCC_SDMMC1_RELEASE_RESET();
 
    g_sd_handle.Instance = SDMMC1;
    g_sd_handle.Init.ClockEdge = SDMMC_CLOCK_EDGE_RISING;
    g_sd_handle.Init.ClockPowerSave = SDMMC_CLOCK_POWER_SAVE_DISABLE;
    g_sd_handle.Init.BusWide = SDMMC_BUS_WIDE_4B;
    g_sd_handle.Init.HardwareFlowControl = SDMMC_HARDWARE_FLOW_CONTROL_DISABLE;
    g_sd_handle.Init.ClockDiv = 0;
    assert_param(HAL_SD_Init(&g_sd_handle) == HAL_OK);
 
    // NVIC configuration for SDMMC1 interrupt
    HAL_NVIC_SetPriority(SDMMC1_IRQn, 5, 0);
    HAL_NVIC_EnableIRQ(SDMMC1_IRQn);
}

The parameter USE_SD_TRANSCEIVER from stm32h7xx_hal_conf.h is set to 0.

Does anyone experienced this issue before ? Any help would be appreciated.

Many Thanks!

LB

1 ACCEPTED SOLUTION

Accepted Solutions
LB.2
Associate II

Hi all,

Sorry for this late update...

Thanks for you help!

I managed to solve my problem, which was ultimately not related to the HAL library.

Basically, on the custom board I'm using, I have to enable the 5V power supply via a GPIO. This 5V is necessary for the SD card to function. So without enabling 5V on my system, the SD card will not work.

I had correctly activated it just before initializing the HAL SD, but it seems that a delay is needed between the two to allow the 5v to stabilize throughout the custom board.

HAL_Init();
 
hw_port_clock_init();
hw_port_gpio_init();
 
// Enable 5V critical needed for the SD card
hw_port_gpio_pwr_5v_critical_enable();
while(hw_port_gpio_get_5v_critical_pg_state() == 0)
{
}
// This delay is necessary to allow 5v to stabilise throughout the system.
// We have seen that without this delay, the initialization of the SD fails
HAL_Delay(5);
 
// SD card must be plugged in !!!
assert_param(hw_port_gpio_is_sd_detected());
hw_port_sd_init();

The funny thing is that I already waited for the PGOOD pin of the 5V regulator to be HIGH before initializing the HAL SD but that was not enough, the 5ms delay is necessary.

In conclusion, this problem was not related to the HAL library but specific to the custom board I use.

cheers,

LB

View solution in original post

7 REPLIES 7
LB.2
Associate II

I dug a little deeper and found that if I increase the delay that is done just before SD_PowerON(), it works fine.

Where the issue is located: HAL_SD_Init() -> HAL_SD_InitCard()

HAL_StatusTypeDef HAL_SD_InitCard(SD_HandleTypeDef *hsd)
{
  uint32_t errorstate;
  SD_InitTypeDef Init;
  uint32_t sdmmc_clk;
 
  /* Default SDMMC peripheral configuration for SD card initialization */
  Init.ClockEdge           = SDMMC_CLOCK_EDGE_RISING;
  Init.ClockPowerSave      = SDMMC_CLOCK_POWER_SAVE_DISABLE;
  Init.BusWide             = SDMMC_BUS_WIDE_1B;
  Init.HardwareFlowControl = SDMMC_HARDWARE_FLOW_CONTROL_DISABLE;
 
  /* Init Clock should be less or equal to 400Khz*/
  sdmmc_clk     = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SDMMC);
  if (sdmmc_clk == 0U)
  {
    hsd->State = HAL_SD_STATE_READY;
    hsd->ErrorCode = SDMMC_ERROR_INVALID_PARAMETER;
    return HAL_ERROR;
  }
  Init.ClockDiv = sdmmc_clk / (2U * SD_INIT_FREQ);
 
  /* Initialize SDMMC peripheral interface with default configuration */
  (void)SDMMC_Init(hsd->Instance, Init);
 
  /* Set Power State to ON */
  (void)SDMMC_PowerState_ON(hsd->Instance);
 
  /* wait 74 Cycles: required power up waiting time before starting
     the SD initialization sequence */
  if (Init.ClockDiv != 0U)
  {
    sdmmc_clk = sdmmc_clk / (2U * Init.ClockDiv);
  }
 
  if (sdmmc_clk != 0U)
  {
    HAL_Delay(1U + (74U * 1000U / (sdmmc_clk)));
  }
 
  /* Identify card operating voltage */
  errorstate = SD_PowerON(hsd);
  if (errorstate != HAL_SD_ERROR_NONE)
  {
    hsd->State = HAL_SD_STATE_READY;
    hsd->ErrorCode |= errorstate;
    return HAL_ERROR;
  }
...
}

The first steps of the HAL_SD_InitCard() must be performed with a clock that is less than or equal to 400Khz. My SDMMC clock is configured to 40Mhz so the code inside HAL_SD_InitCard() divide it to match the 400Khz requirements.

Init.ClockDiv = sdmmc_clk / (2U * SD_INIT_FREQ);

Init.ClockDiv = 40000000 / (2 * 400000) = 50

sdmmc_clk = sdmmc_clk / (2U * Init.ClockDiv);

sdmmc_clk = 40000000 / (2 * 50) = 400000

HAL_Delay(1U + (74U * 1000U / (sdmmc_clk)));

HAL_Delay(1 + (74 * 1000 / 400000))

=> HAL_Delay(1.185)

But a delay of 1.185ms seems too low and makes the SD_PowerON() function fail.

Obviously touching this delay and the code inside the stm32 hal library is not a solution, so I don't know what I could change in the application to make it work.

AScha.3
Chief III

on my H743 board here i use this setting :

0693W00000Y8lNdQAJ.png0693W00000Y8lOCQAZ.png0693W00000Y8lOWQAZ.png 

0693W00000Y8lOgQAJ.png0693W00000Y8lP0QAJ.pngtry this settings. there never was a startup problem; just "very high" port speed may not work, try medium or high.

If you feel a post has answered your question, please click "Accept as Solution".

hi,

same issue with maine for controller-STM32H723VGT6.

After a deeply study ,i also found issue with sd card initialization on the level of.....

 if (hsd->SdCard.CardVersion == CARD_V2_X)

 {

  /* SEND CMD55 APP_CMD with RCA as 0 */

  errorstate = SDMMC_CmdAppCommand(hsd->Instance, 0);

  if (errorstate != HAL_SD_ERROR_NONE)

  {

   return HAL_SD_ERROR_UNSUPPORTED_FEATURE;

  }

 }

please share the solution ,how you have been resolved .

https://community.st.com/s/question/0D53W00000QvljESAR/4-bit-sdio-sd-card-sdmmc-issue-on-nucleoh723zg-stm32h723zg-stm32h7

LB.2
Associate II

Hi all,

Sorry for this late update...

Thanks for you help!

I managed to solve my problem, which was ultimately not related to the HAL library.

Basically, on the custom board I'm using, I have to enable the 5V power supply via a GPIO. This 5V is necessary for the SD card to function. So without enabling 5V on my system, the SD card will not work.

I had correctly activated it just before initializing the HAL SD, but it seems that a delay is needed between the two to allow the 5v to stabilize throughout the custom board.

HAL_Init();
 
hw_port_clock_init();
hw_port_gpio_init();
 
// Enable 5V critical needed for the SD card
hw_port_gpio_pwr_5v_critical_enable();
while(hw_port_gpio_get_5v_critical_pg_state() == 0)
{
}
// This delay is necessary to allow 5v to stabilise throughout the system.
// We have seen that without this delay, the initialization of the SD fails
HAL_Delay(5);
 
// SD card must be plugged in !!!
assert_param(hw_port_gpio_is_sd_detected());
hw_port_sd_init();

The funny thing is that I already waited for the PGOOD pin of the 5V regulator to be HIGH before initializing the HAL SD but that was not enough, the 5ms delay is necessary.

In conclusion, this problem was not related to the HAL library but specific to the custom board I use.

cheers,

LB

hi,

i have some query, please come in your Message Box.

Thanking you

N$8130
Associate II

hi LB.2 (Community Member)

we have some doubt,please need your help.

Please Clear the function ....

  1. hw_port_gpio_pwr_5v_critical_enable();
  2. Have you used level shifter(USE_SD_TRANSCEIVER ) for MicroSD Card Communuication.

which level shifter ic you have used.

please share connection diagram also,if it possible.

thanking you

N$8130
Associate II

Hi @Loïc B​ ,

Please check your message box,i need your help.

we are still waiting of your response!

Thanking you