cancel
Showing results for 
Search instead for 
Did you mean: 

SDCARD does not work with 4bits wide bus

JBond.1
Senior

Hi I have STM32F407 and after updating STM32CubeMX 6.6.1 -> 6.9.2 I faced the same issue with SD card:
https://community.st.com/t5/stm32cubemx-mcus/sdcard-does-not-work-fr-not-ready-when-migrating-from-fw-f4-v1/m-p/115499#M3876

It seems that with previous version we were working with 1bit wide bus even if we set 4bit wide bus. Although GPIOS were set for 4bits (SDIO_D0, SDIO_D1, SDIO_D2, SDIO_D3).


So after upgrading it changed to 4bits wide bus, but now we get `FR_NOT_READY`, `HAL_SD_ERROR_REQUEST_NOT_APPLICABLE`

/* If requested card supports wide bus operation */
  if((scr[1U] & SDMMC_WIDE_BUS_SUPPORT) != SDMMC_ALLZERO)
  {
    //...
    return HAL_SD_ERROR_NONE;
  }
  else
  {
    return HAL_SD_ERROR_REQUEST_NOT_APPLICABLE;
  }

 

How do I fix this and make SD card work with 4bits wide bus?

8 REPLIES 8
JBond.1
Senior

I think STM32CubeMX has introduced a bug?

Initialization needs to be done with 1B and after that it should switch to 4B mode?

 

static void MX_SDIO_SD_Init(void)
{

  /* USER CODE BEGIN SDIO_Init 0 */

  /* USER CODE END SDIO_Init 0 */

  /* USER CODE BEGIN SDIO_Init 1 */

  /* USER CODE END SDIO_Init 1 */
  hsd.Instance = SDIO;
  hsd.Init.ClockEdge = SDIO_CLOCK_EDGE_RISING;
  hsd.Init.ClockBypass = SDIO_CLOCK_BYPASS_DISABLE;
  hsd.Init.ClockPowerSave = SDIO_CLOCK_POWER_SAVE_DISABLE;
  hsd.Init.BusWide = SDIO_BUS_WIDE_4B; // Initialization needs to be done with 1B?
  hsd.Init.HardwareFlowControl = SDIO_HARDWARE_FLOW_CONTROL_DISABLE;
  hsd.Init.ClockDiv = 12;
  /* USER CODE BEGIN SDIO_Init 2 */
  hsd.Init.BusWide = SDIO_BUS_WIDE_1B; // FIX?
  /* USER CODE END SDIO_Init 2 */

}

 

Now we need to override `hsd.Init.BusWide = SDIO_BUS_WIDE_1B;` for initialization to use 1bit and after initialization it switches to 4bit, no?

 

__weak uint8_t BSP_SD_Init(void)
{
  uint8_t sd_state = MSD_OK;
  /* Check if the SD card is plugged in the slot */
  if (BSP_SD_IsDetected() != SD_PRESENT)
  {
    return MSD_ERROR;
  }
  /* HAL SD initialization */
  sd_state = HAL_SD_Init(&hsd);
  /* Configure SD Bus width (4 bits mode selected) */
  if (sd_state == MSD_OK)
  {
    /* Enable wide operation */
    if (HAL_SD_ConfigWideBusOperation(&hsd, SDIO_BUS_WIDE_4B) != HAL_OK)
    {
      sd_state = MSD_ERROR;
    }
  }

  return sd_state;
}

 

Can STM32CubeMX team comment on this?

So STM32CubeMX 6.6.1 was correct and new versions have introduced a bug?

just search here in forum - see discussion + solution .

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

There is this thread:

https://community.st.com/t5/stm32cubemx-mcus/sdcard-does-not-work-fr-not-ready-when-migrating-from-fw-f4-v1/td-p/115499

But it looks like the ST member who responded doesn't realize how SD works and thinks the change was a fix, rather than a bug/regression. So good luck with that.

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

Hello @JBond.1 @TDK @AScha.3 

Thank you all  for your detailed explanation , and it's thanks to your contribution  that we're going to have a more mature version of MX.

An internal ticket is raised to dev team in order to fix this issue asap .

Internal ticket number: 155983 

 

Ghofrane

 

It does not work for me too.

My experience is the following: HAL_SD_Init() is being called twice. The first time is from MX_SDMMC1_SD_Init(). This time, SD_WideBus_Enable() works fine and returns HAL_SD_ERROR_NONE:

Thread #1 [main] 1 [core: 0] (Suspended : Breakpoint)
        SD_WideBus_Enable() at stm32h7xx_hal_sd.c:3,473 0x800bd84
        HAL_SD_ConfigWideBusOperation() at stm32h7xx_hal_sd.c:2,423 0x800b66c
        HAL_SD_Init() at stm32h7xx_hal_sd.c:433 0x800a94e
        MX_SDMMC1_SD_Init() at main.c:399 0x8000c8c
        main() at main.c:157 0x80008a8

The second time, it is called from BSP_SD_Init():

Thread #1 [main] 1 [core: 0] (Suspended : Breakpoint)
        SD_WideBus_Enable() at stm32h7xx_hal_sd.c:3,473 0x800bd84
        HAL_SD_ConfigWideBusOperation() at stm32h7xx_hal_sd.c:2,423 0x800b66c
        HAL_SD_Init() at stm32h7xx_hal_sd.c:433 0x800a94e
        BSP_SD_Init() at bsp_driver_sd.c:50 0x800fb16
        SD_initialize() at sd_diskio.c:155 0x800fce6
        disk_initialize() at diskio.c:60 0x800ffd0
        f_mkfs() at ff.c:5,334 0x8012280
        main() at main.c:180 0x800090c

 

This time it fails with HAL_SD_ERROR_REQUEST_NOT_APPLICABLE. It boils down to this code:

/* If requested card supports wide bus operation */
if ((scr[1U] & SDMMC_WIDE_BUS_SUPPORT) != SDMMC_ALLZERO) {
        /* Send CMD55 APP_CMD with argument as card's RCA.*/
        errorstate = SDMMC_CmdAppCommand(hsd->Instance, (uint32_t)(hsd->SdCard.RelCardAdd << 16U));
        if (errorstate != HAL_SD_ERROR_NONE) {
               return errorstate;
        }

        /* Send ACMD6 APP_CMD with argument as 2 for wide bus mode */
        errorstate = SDMMC_CmdBusWidth(hsd->Instance, 2U);
        if (errorstate != HAL_SD_ERROR_NONE) {
               return errorstate;
        }

        return HAL_SD_ERROR_NONE;
} else {
        return HAL_SD_ERROR_REQUEST_NOT_APPLICABLE;
}

 Either HAL_SD_Init() should be an idempotent thing, i.e., it should be possible to call it several times in a row without problems, or care should be taken to call HAL_SD_DeInit() before calling HAL_SD_Init() again. After the first call, something happens and it doesn't return to the initial state.

In order to fix that issue, I have put some code in HAL_SD_MspInit() to poweroff the SD:

void HAL_SD_MspInit(SD_HandleTypeDef *hsd)
{
        GPIO_InitTypeDef GPIO_InitStruct = {0};
        RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
        if (hsd->Instance == SDMMC1) {
        /* USER CODE BEGIN SDMMC1_MspInit 0 */
               (void)SDMMC_PowerState_OFF(hsd->Instance);
        /* USER CODE END SDMMC1_MspInit 0 */
...

Now HAL_SD_Init() works always. But the code fails soon after for the same reason, because BSP_SD_Init() insists on calling HAL_SD_ConfigWideBusOperation(), which effectivelly is called a third time.

 

Currently, I have commented the call to HAL_SD_ConfigWideBusOperation() in BSP_SD_Init(). The f_mkfs() now succeeds, but I still have issues with f_open(). On my next debug session, I hope I can report some success then.

 

Regards,

Marcelo.

1. set 1-bit mode (more easy to begin, less problems with lines/ringing)

2. set port/pins pullup + speed medium

3. clock smmc with 50MHz , or lower until its working.

4. never mkfs !!! no write ! only read at beginning, otherwise good chance to destroy sd-card.

5. use "good" card (and test in PC first, put some file there, to test reading) i use only SanDisk .

6. about init...maybe you have set "too much" : try to set > no function call  to sd_init

AScha3_0-1701418065148.png

 

 

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

Hi,

After some debugging, I found that there is a parameter called SDMMC clock divide factor that defaults to zero. The path to it is Connectivity -> SDMMC1 -> Configuration -> Parameter Settings -> SDMMC clock divide factor. I have set it to 1, which means one half of the kernel clock frequency, and now everything works, even with the triple initialization. I had 200 MHz in the original frequency, so I think this means the controller will operate at 100 MHz.

 

I suggest anyone with a similar problem to test increasing this parameter until the device works, maybe to a binary search, should take less than 10 attempts.

 

By the way, I am using 4 bit mode, so I still hope I can get a good speed from the card. Still, without a level converter circuit to 1.8 Volts, I know it is not possible to go full speed.

 

I did some changes to the original code, which I got from a tutorial video from ST. If anyone is interested, here is the code:

/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_DMA_Init();
MX_MDMA_Init();
MX_ADC3_Init();
MX_TIM1_Init();
MX_USART1_UART_Init();
MX_SDMMC1_SD_Init();
MX_FATFS_Init();
/* USER CODE BEGIN 2 */
...
res = f_mkfs((TCHAR const *)"", FM_ANY, 0, rtext, sizeof rtext);
if (res != FR_OK) {
        Error_Handler();
}
res = f_mount(&SDFatFS, (TCHAR const *)"", 1);
if (res != FR_OK) {
        Error_Handler();
}
// Open file for writing (Create)
res = f_open(&SDFile, "STM32.TXT", FA_CREATE_ALWAYS | FA_WRITE);
if (res != FR_OK) {
        Error_Handler();
}
// Write to the text file
res = f_write(&SDFile, wtext, strlen((char *)wtext), (void *)&bytes_written);
if ((bytes_written == 0) || (res != FR_OK)) {
        Error_Handler();
}
f_close(&SDFile);
/* FS == NULL -> umount */
res = f_mount(NULL, "", 0);
/* USER CODE END 2 */

 

btw

i wrote, you should set a max. clk of 50MHz...

>3. clock smmc with 50MHz , or lower until its working.

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