Skip to main content
ANauz.1
Senior
September 18, 2023
Question

SDIO interface not working in 4Bits with STM32F4 Firmware Package

  • September 18, 2023
  • 4 replies
  • 12423 views

Hello,

Working on an STM32F412 µC, with the last F4 firmware package ans last MX

When configuring to use SDIO with 1Bit interface, everything works fine. But when configuring to use a 4bits interface, there is an error 

In BSP_SD_Init(); there is an error when calling HAL_SD_ConfigWideBusOperation()

I have tried to make it work with FreeRTOS and FreeRTOS-Plus-FAT and... it work.

As I do not always want to have project with FreeRTOS, would it be possible to ST to integrate working SD initialisation in 4 bit mode.

Reading the following:

https://community.st.com/t5/stm32-mcus-products/sdio-4-bit-mode-with-stm32cubemx/td-p/406139

https://stackoverflow.com/questions/72984923/stm32f746-sd-card-crc-failing-in-4-bit-mode-but-working-fine-in-1-bit-mode

It seems that the problem is known for a long time, with no solution provided by ST. ST should at least integrate the evolution provide by FreeRTOS to make STM32 firmware package at least work in every mode possible!

It seems unbelievable to me that STM32 FW package do not integrate corrections of problems that are knows for years

Thank you

Regards

 

 

 

 

This topic has been closed for replies.

4 replies

Technical Moderator
September 18, 2023

Hello @ANauz.1 ,

Thank you for your feedback. The issue is tracked since a while (155983) I will keep you updated once the fix is published. For now,  in case we choose SDIO Mode option "SD 4 bits Wide bus" from Cubemx "Pinout & Configuration" interface :

  1. Step 1 - hsd.Init.BusWide set to SDIO_BUS_WIDE_1B just for initialization.
  2. Step 2 - Call HAL_SD_Init(&hsd)
  3. 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 */

}

 I hope this helps!

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.Best regards,FBL
Piranha
Principal III
October 11, 2023

It has been reported at least in January 2015:

https://community.st.com/t5/stm32-mcus-products/sdio-4bit-mode-fatfs-and-stm32cubemx-on-stm32f401-discovery/m-p/442538/highlight/true#M139949

A quote from the next post of that ST employee in that topic is just hilarious:

"STM32CubeMX team are aware of this limitation. Just keep an eye out for the next updates!"

Yeah, just keep an eye out... for 9+ years!

AScha.3
Super User
October 11, 2023

hello @Piranha  ,

i tried using sdio ...many times, now on H563-nucleo board. not working, with setting from Cube.

no surprise for you, i suppose.  9 y are a long time in computer business, new young people now working on this.

so they make things "better", restricting, what silly user can choose : on H563, sdio setting force (no choice) to high speed and no-pull setting of port pins, what is just wrong. I tried, setting to pullup and medium speed -> works.

setting from STM / Cube not working.

AScha3_0-1697056612321.png

and the Azure/rtos + Filex (no more Fatfs to choose ! ) NOT working at all.

I killed Filex, copied (new) Fatfs by Mr. Chang in. this works. with pullup on + medium speed, not with STM settings.

So now i more and more understand, your statements about mental constitution of the programmers involved.

 

"If you feel a post has answered your question, please click ""Accept as Solution""."
tizdipietro
Associate III
October 16, 2023

I spent many hours fixing this issue, you can find a working solution, SDIO 4bit mode with DMA at 12Mhz with detailed instructions on how to set up everything here GitHub Repo

I suggest you carefully read the readme in the repo, everything is explained there.

AScha.3
Super User
October 16, 2023

just what you should add: GPIO settings !

set all pins : pullup on;

and speed : medium or high (depends on chip, to high speed makes reflections/ringing; so lowest possible speed setting is best.)

and clock: (i always use) 100MHz , div 1 ; (gives 50M , typical for standard sd-cards)

and fatfs setting : ( i use) long filenames enable; exfat enable ; ( most new >16GB cards are exfat formatted :) )

"If you feel a post has answered your question, please click ""Accept as Solution""."
Andrew Androsow
Associate II
December 13, 2023

Hello! I had the similar problem. My app (there is not any  FreeRTOS ) works well in 1-bit mode, but in -bit mode not working at all (to be honest - sometimes with very old 1Gb SD card). The wires from SD card to STM32 have  length roughly 50 millimeters. I tried a chunk of  old interface cable from old HDD, but I have not success. Finally I got several simple wires and connect 50Ohm resistors next to the SDIO Card slot in series with each wire (exclude Vss and GND). The interface started works well in 4-bi mode.

MLiak.1
Associate
January 7, 2024

Hello!

1. uSD cards ALWAYS initialize with 1-bit wide bus. Even if card will work in 4-bit wide bus mode.

2.This initialization error (hsd.Init.BusWide = SDIO_BUS_WIDE_4B) has been around from year to year (for more than 4 years!), at least in the F4xx series.

So...

I manually edited this wrong line in the initialization code for a very long time, and in the end I found a fairly elegant solution.

The generated file "sdio.c" has two sections for user code:

 

/* USER CODE BEGIN SDIO_Init 1 */ ... /* USER CODE END SDIO_Init 1 */

 

and

 

/* USER CODE BEGIN SDIO_Init 2 */ ... /* USER CODE END SDIO_Init 2 */

 

After the initialization code has been generated, copy the code to the section

/* USER CODE BEGIN SDIO_Init 1 */, specify the correct bus width for initialization (hsd.Init.BusWide = SDIO_BUS_WIDE_1B;), and add conditional compilation directives.

Result, for example:

 

 

 /* USER CODE BEGIN 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;
 // Corrected bus wide for initialization
 hsd.Init.BusWide = SDIO_BUS_WIDE_1B;
 hsd.Init.HardwareFlowControl = SDIO_HARDWARE_FLOW_CONTROL_DISABLE;
 hsd.Init.ClockDiv = 0;
#define ONLY_USER_INIT // Tired of editing the code every time you change, the line "hsd.Init.BusWide = SDIO_BUS_WIDE_4B;"
#ifndef ONLY_USER_INIT

 /* USER CODE END SDIO_Init 1 */

 // Originally generated code
 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 = 0;

 /* USER CODE BEGIN SDIO_Init 2 */

#endif //ifndef ONLY_USER_INIT

 /* USER CODE END SDIO_Init 2 */

 

 

In the future, when you change anything in the configurator, only the code between the lines

/* USER CODE END SDIO_Init 1 */ and /* USER CODE BEGIN SDIO_Init 2 */ will be changed, and this section of code is excluded from compilation.