cancel
Showing results for 
Search instead for 
Did you mean: 

Running SDIO 4BIT wide mode

wegi01
Associate III

In this movie setup done  SDMMC 4BIT mode selected in CubeMX:

 Setup looks:

01 ST creating filesystem.jpg

 

In the older versions CubeMX like video before generated code for SDMMC or SDIO 4BIT setup looks like:

02 OLD_CUBE_CODE.jpg

 That was confusing and doesn't really running SDIO/SDMMC in 4 bit wide mode.

 

Today Cube generate code with SDMMC_BUS_WIDE_4B parameter BUT this is NOT ENOUGHT to running SDIO/SDMMC in 4 bits wide mode. Here is need a bit magic in a few codelines. 

For setup DISCOVERY F746G:

03 F746SDMMC setup.jpg

 

In the generated code need to add a magic few lines which was selected in the red border:

04 F746SDMMC code.jpg

In the comparision 4bit to 1bit mode was 128ms/510KB read time for 1 bit mode versus 68ms for 4 bit mode.

A little video with 4bit SDMMC work:

For any custom board with STM32F407VET6 was setup:
05 Cube setup F407VE.jpg

The code was very simmilary to previous:

 

06 F407VET6 code.jpg

 

All of this was after my hot dispute with YT streamer called STM32World, where I don't bellieved him about the SDIO 4Bit mode could be really work on the STM32. And hi really proved it can be work after add this magic codelines. A big thanks to him by the way.

 

 

 

1 ACCEPTED SOLUTION

Accepted Solutions
mƎALLEm
ST Employee

Hello @wegi01 and thank you for the sharing.

MX_SDIO_SD_Init() should be generated with hsd.Init.BusWide = SDIO_BUS_WIDE_1B in both cases we choose SDIO Mode option
"SD 4 bits Wide bus" or "SD 1 bit".
Therefore, SDIO_BUS_WIDE_4B needs to be set at the right step : HAL_SD_ConfigWideBusOperation().
In case "SD 4 bits Wide bus" is chosen, the generated MX_SDIO_SD_Init() should follow below steps :
Step 1 - hsd.Init.BusWide set to SDIO_BUS_WIDE_1B just for initialization.
Step 2 - Call HAL_SD_Init(&hsd)
Step 3 - Call HAL_SD_ConfigWideBusOperation(&hsd, SDIO_BUS_WIDE_4B)

###############################################################
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_1B;
hsd.Init.HardwareFlowControl = SDIO_HARDWARE_FLOW_CONTROL_DISABLE;
hsd.Init.ClockDiv = 0;
if (HAL_SD_Init(&hsd) != HAL_OK)
{
Error_Handler();
}
if (HAL_SD_ConfigWideBusOperation(&hsd, SDIO_BUS_WIDE_4B) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN SDIO_Init 2 */

/* USER CODE END SDIO_Init 2 */

}

 

To give better visibility on the answered topics, please click on "Accept as Solution" on the reply which solved your issue or answered your question.

View solution in original post

4 REPLIES 4
mƎALLEm
ST Employee

Hello @wegi01 and thank you for the sharing.

MX_SDIO_SD_Init() should be generated with hsd.Init.BusWide = SDIO_BUS_WIDE_1B in both cases we choose SDIO Mode option
"SD 4 bits Wide bus" or "SD 1 bit".
Therefore, SDIO_BUS_WIDE_4B needs to be set at the right step : HAL_SD_ConfigWideBusOperation().
In case "SD 4 bits Wide bus" is chosen, the generated MX_SDIO_SD_Init() should follow below steps :
Step 1 - hsd.Init.BusWide set to SDIO_BUS_WIDE_1B just for initialization.
Step 2 - Call HAL_SD_Init(&hsd)
Step 3 - Call HAL_SD_ConfigWideBusOperation(&hsd, SDIO_BUS_WIDE_4B)

###############################################################
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_1B;
hsd.Init.HardwareFlowControl = SDIO_HARDWARE_FLOW_CONTROL_DISABLE;
hsd.Init.ClockDiv = 0;
if (HAL_SD_Init(&hsd) != HAL_OK)
{
Error_Handler();
}
if (HAL_SD_ConfigWideBusOperation(&hsd, SDIO_BUS_WIDE_4B) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN SDIO_Init 2 */

/* USER CODE END SDIO_Init 2 */

}

 

To give better visibility on the answered topics, please click on "Accept as Solution" on the reply which solved your issue or answered your question.

Here we can find kilometers threads about doesn't working SDIO 4Bits mode, with speculations about electricals problems, ringing, crosstalking, to hard or to weak pull up ressistors and so on. And don't notice any one of example which could be working. 

Shared code from ST movie which I linking before have SDIO_BUS_WIDE_1B setup parameter and 4bits GPIO initialization what with today knowledge we can think this is properly BUT on the next code doesn't invoke HAL_SD_ConfigWideBusOperation(&hsd, SDIO_BUS_WIDE_4B) . That's mean SDMMC interface was running in 1 bit mode instead as choosed 4 bit mode.

 

Now the code generated for choose SDIO/SDMMC 4BIT looks like:

for STM32F103ZET6

void MX_SDIO_SD_Init(void)
{ // for F103ZET6 SDIO init 4bit mode generated fro STM32CubeIDE 1.17.0
//...
/* 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; //!!!!!!!!!!!!!!!!!!!!
  hsd.Init.HardwareFlowControl = SDIO_HARDWARE_FLOW_CONTROL_DISABLE;
  hsd.Init.ClockDiv = 3;
  /* USER CODE BEGIN SDIO_Init 2 */

 

for STM32F407VET6

static void MX_SDIO_SD_Init(void)
{// for F407VET6 SDIO init 4bit mode generated fro STM32CubeIDE 1.17.0
//...
  /* USER CODE END SDIO_Init 1 */
  hsd.Instance = SDIO;
  hsd.Init.ClockEdge = SDIO_CLOCK_EDGE_RISING;
  hsd.Init.ClockBypass = SDIO_CLOCK_BYPASS_ENABLE;
  hsd.Init.ClockPowerSave = SDIO_CLOCK_POWER_SAVE_DISABLE;
  hsd.Init.BusWide = SDIO_BUS_WIDE_4B; //!!!!!!!!!!!!!!!!!!!!!!!
  hsd.Init.HardwareFlowControl = SDIO_HARDWARE_FLOW_CONTROL_DISABLE;
  hsd.Init.ClockDiv = 0;
  /* USER CODE BEGIN SDIO_Init 2 */

 

For STM32F746G DISCO

static void MX_SDMMC1_SD_Init(void)
{ // for F746G DISCO SDIO init 4bit mode generated fro STM32CubeIDE 1.17.0
//...
  /* USER CODE END SDMMC1_Init 1 */
  hsd1.Instance = SDMMC1;
  hsd1.Init.ClockEdge = SDMMC_CLOCK_EDGE_RISING;
  hsd1.Init.ClockBypass = SDMMC_CLOCK_BYPASS_ENABLE;
  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;
  /* USER CODE BEGIN SDMMC1_Init 2 */

 

All examples got setup 4bit parameter SDIO_BUS_WIDE_4B in the initialization code, and not any one generated example doesn't include somethink like that:

 

  /* USER CODE BEGIN SDIO_Init 2 */
  hsd.Init.BusWide = SDIO_BUS_WIDE_1B;
  if (HAL_SD_Init(&hsd) != HAL_OK) { while(1); }
  if (HAL_SD_ConfigWideBusOperation(&hsd, SDIO_BUS_WIDE_4B) != HAL_OK) { while(1); }
  /* USER CODE END SDIO_Init 2 */

So withot this SDIO interface and program which invoke SDIO/SDMMC simply HANGS.

 

And in very firstly user MUST KNOW about hi need to use this additional configuration code and which one functions should be invoke when CubeIDE/CubeMX don't generate from self all working code without supplementary code.

 

That's why I'd create this thread bcos as before ^^ 

 

 

 

mƎALLEm
ST Employee

As I said you need to configure the SDIO in 1 bit in the CubeMx even for 4-bit mode then add the code of 4-bit in the user code.

To give better visibility on the answered topics, please click on "Accept as Solution" on the reply which solved your issue or answered your question.

@mƎALLEm m - don't change facts and history. We have post order here an I said this before and show what is need to do for running SDIO 4Bit mode. From threads beginning from 2018/19 you didn't gave solution but you gave today repeat after me and and you try to convince me that you gave me an acceptable solution which I brought here.