cancel
Showing results for 
Search instead for 
Did you mean: 

4 bit SDIO doesn't work although 1 bit SDIO works SDCARD

con3
Senior
Posted on January 18, 2018 at 14:37

Hey everyone,

I have a quick question concerning the 4 bit sdio sdcard implementation. The 1 bit sdio seems to work perfectly. I have absolutely no issues, although when implementing 4 bit it completely bugs out. Are there any lower level files that the 4 bit uses that the 1 bit doesn't? According to me they should use the same lower level functions and therefore both should work? My question is pretty much do they use the same lower level functions or are there separate functions for each implementation..?

Thanks in advance

#stm32-f7 #sdcard

Note: this post was migrated and contained many threaded conversations, some content may be missing.
15 REPLIES 15
Posted on January 18, 2018 at 16:48

The SDIO/SDMMC drivers should handle this seamlessly. The physical interface is reliant on correct connectivity, and will likely have issues if the data bits skew with respect to each other, or lack pull-up at the card. If you have ringing on the signals you might want to consider series resistors also.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Mario Popovic_2
Associate II
Posted on January 19, 2018 at 08:49

Hello,

Have you tried to setting the Pull-up on the GPIO Pins for the SD interface? I had simmilar problem on STM32F767 and this helped.

Regards,

Mario

Posted on January 20, 2018 at 12:45

Its odd, because I set it to 4 bit sdio in cube, but I still only see D0 doing anything with an oscilloscope. all lines have the required pullups, etc.

Posted on January 20, 2018 at 12:46

I have pullups on all the lines. It works, although I can only see D0 doing anything. All the other data lines are dead. I used cube to set it to 4 bit sdio

Posted on January 20, 2018 at 12:57

Have you tried to debug through the driver to see exactly where it gets stuck? Are you using FATFs? Which part are you using?

The reason you see only D0 doing something is because on reset the SD card is in 1bit mode over which it then needs to be configured in 4-bit mode. This would imply that setting it to work in 4-bit mode is not working. Mabe the SDIO clk is too high?

Regards

Posted on January 20, 2018 at 13:00

Could you please maybe post the portion of code that cube generates that does this? I can't seem to find it.

The clock seems to be sub 400 khz until it finishes initializing and it starts writing, then it shifts to 24 Mhz

Posted on January 20, 2018 at 13:09

It's located in stm32f4xx_hal_sd.c and it's called from BSP_SD_Init in bsp_driver_sd.c

/**

* @brief Enables wide bus operation for the requested card if supported by

* card.

* @param hsd Pointer to SD handle

* @param WideMode Specifies the SD card wide bus mode

* This parameter can be one of the following values:

* @arg SDIO_BUS_WIDE_8B: 8-bit data transfer

* @arg SDIO_BUS_WIDE_4B: 4-bit data transfer

* @arg SDIO_BUS_WIDE_1B: 1-bit data transfer

* @retval HAL status

*/

HAL_StatusTypeDef HAL_SD_ConfigWideBusOperation(SD_HandleTypeDef *hsd, uint32_t WideMode)

{

SDIO_InitTypeDef Init;

uint32_t errorstate = HAL_SD_ERROR_NONE;

/* Check the parameters */

assert_param(IS_SDIO_BUS_WIDE(WideMode));

/* Chnage Satte */

hsd->State = HAL_SD_STATE_BUSY;

if(hsd->SdCard.CardType != CARD_SECURED)

{

if(WideMode == SDIO_BUS_WIDE_8B)

{

hsd->ErrorCode |= HAL_SD_ERROR_UNSUPPORTED_FEATURE;

}

else if(WideMode == SDIO_BUS_WIDE_4B)

{

errorstate = SD_WideBus_Enable(hsd);

hsd->ErrorCode |= errorstate;

}

else if(WideMode == SDIO_BUS_WIDE_1B)

{

errorstate = SD_WideBus_Disable(hsd);

hsd->ErrorCode |= errorstate;

}

else

{

/* WideMode is not a valid argument*/

hsd->ErrorCode |= HAL_SD_ERROR_PARAM;

}

}

else

{

/* MMC Card does not support this feature */

hsd->ErrorCode |= HAL_SD_ERROR_UNSUPPORTED_FEATURE;

}

if(hsd->ErrorCode != HAL_SD_ERROR_NONE)

{

/* Clear all the static flags */

__HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS);

hsd->State = HAL_SD_STATE_READY;

return HAL_ERROR;

}

else

{

/* Configure the SDIO peripheral */

Init.ClockEdge = hsd->Init.ClockEdge;

Init.ClockBypass = hsd->Init.ClockBypass;

Init.ClockPowerSave = hsd->Init.ClockPowerSave;

Init.BusWide = WideMode;

Init.HardwareFlowControl = hsd->Init.HardwareFlowControl;

Init.ClockDiv = hsd->Init.ClockDiv;

SDIO_Init(hsd->Instance, Init);

}

/* Change State */

hsd->State = HAL_SD_STATE_READY;

return HAL_OK;

}
Mohammad A
Senior
Posted on January 20, 2018 at 14:39

Don't touch the code generated by cubemx, just lower the sd clock. That should be enough, at least for me it solved this issue.

Posted on January 20, 2018 at 13:51

So first thing I've noticed is that Cube generates code that defaults to SDMMC_BUS_WIDE_1B

I manually changed this to 4B?

static void MX_SDMMC1_SD_Init(void)

{

  hsd1.Instance = SDMMC1;

  hsd1.Init.ClockEdge = SDMMC_CLOCK_EDGE_RISING;

  hsd1.Init.ClockBypass = SDMMC_CLOCK_BYPASS_DISABLE;

  hsd1.Init.ClockPowerSave = SDMMC_CLOCK_POWER_SAVE_DISABLE;

  hsd1.Init.BusWide = SDMMC_BUS_WIDE_4B;

  hsd1.Init.HardwareFlowControl = SDMMC_HARDWARE_FLOW_CONTROL_DISABLE;

  hsd1.Init.ClockDiv = 0;

}

Secondly I can't find any call to HAL_StatusTypeDef HAL_SD_ConfigWideBusOperation(SD_HandleTypeDef *hsd, uint32_t WideMode) anywhere in my workspace.

It doesn't seem like the generated code calls it. it asserts 1B and continues. BSP_SD_Init looks like this:

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_SD_NOT_PRESENT;

  }

  /* HAL SD initialization */

  sd_state = HAL_SD_Init(&hsd1);

  return sd_state;

}

HAL_StatusTypeDef HAL_SD_Init(SD_HandleTypeDef *hsd) looks like this:

HAL_StatusTypeDef HAL_SD_Init(SD_HandleTypeDef *hsd)

{

  /* Check the SD handle allocation */

  if(hsd == NULL)

  {

    return HAL_ERROR;

  }

  /* Check the parameters */

  assert_param(IS_SDMMC_ALL_INSTANCE(hsd->Instance));

  assert_param(IS_SDMMC_CLOCK_EDGE(hsd->Init.ClockEdge));

  assert_param(IS_SDMMC_CLOCK_BYPASS(hsd->Init.ClockBypass));

  assert_param(IS_SDMMC_CLOCK_POWER_SAVE(hsd->Init.ClockPowerSave));

  assert_param(IS_SDMMC_BUS_WIDE(hsd->Init.BusWide));

  assert_param(IS_SDMMC_HARDWARE_FLOW_CONTROL(hsd->Init.HardwareFlowControl));

  assert_param(IS_SDMMC_CLKDIV(hsd->Init.ClockDiv));

  if(hsd->State == HAL_SD_STATE_RESET)

  {

    /* Allocate lock resource and initialize it */

    hsd->Lock = HAL_UNLOCKED;

    /* Init the low level hardware : GPIO, CLOCK, CORTEX...etc */

    HAL_SD_MspInit(hsd);

  }

  hsd->State = HAL_SD_STATE_BUSY;

  /* Initialize the Card parameters */

  HAL_SD_InitCard(hsd);

  /* Initialize the error code */

  hsd->ErrorCode = HAL_DMA_ERROR_NONE;

 

  /* Initialize the SD operation */

  hsd->Context = SD_CONTEXT_NONE;

                                                                                     

  /* Initialize the SD state */

  hsd->State = HAL_SD_STATE_READY;

  return HAL_OK;

}

I could go deeper, although I did check and atollic also ran through the project and couldn't find a call to it. Where should this function be called?

Thanks for all the help thus far, I appreciate it.