2023-10-29 04:38 AM
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?
2023-10-29 07:08 AM - edited 2023-10-29 07:14 AM
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?
2023-10-29 07:18 AM
just search here in forum - see discussion + solution .
2023-10-29 01:16 PM
There is this thread:
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.
2023-10-31 07:50 AM
2023-11-30 05:36 PM
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.
2023-12-01 12:08 AM
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
2023-12-07 09:41 AM
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 */
2023-12-07 09:54 AM
btw
i wrote, you should set a max. clk of 50MHz...
>3. clock smmc with 50MHz , or lower until its working.