cancel
Showing results for 
Search instead for 
Did you mean: 

SDIO 4 bit mode with STM32CubeMX

djhtml
Associate II

I would like to use SDIO with 4 bit mode with FatFS. I use STM32F429I Discovery board and I wired a micro SD card board to it. The SD card is a 16 GB SanDisk Ultra A1 card formatted to FAT32.

This is the micro SD card board: https://image.dhgate.com/0x0s/f2-albu-g4-M01-BC-F9-rBVaEVmcHSeAdh6CAAKj2N4sVnA447.jpg/3-3v-5v-micro-sd-tf-card-reader-module-spi.jpg all lines are pulled up to 3V with 10k res (even the CLK).

Version of STM32CubeMX is 4.26.1, firmware version is STM32Cube FW_F4 V1.21.0, I use Atollic TrueSTUDIO 9.0.0 and FatFS version is R0.12c.

If I generate SDIO with 1 bit mode with CubeMX it works fine, I can read, write the card.

When I generate SDIO with 4 bit mode it is not working. Function 'f_mount' is returning with error code: 13 which is 'FR_NO_FILESYSTEM'. But there is a working file system on the card, I can use it with PC and it works with 1 bit SDIO mode also.

This is the relevant part of the code (all other part is generated with CubeMX):

// ...
 
uint8_t myWrite[30] = "TEST STRING";
uint8_t myRead[30];
 
// ...
 
int main(void)
{
	
	// ...
	
	printf("Start!\r\n");
 
	FATFS myFAT;
	FIL myFile;
	UINT byteCount;
 
	printf("path: '%s'\r\n", SDPath);
 
	FRESULT fRet = 0;
 
	fRet = f_mount(&myFAT, SDPath, 1);
	if(fRet == FR_OK){
		f_open(&myFile, "test.txt", FA_WRITE | FA_CREATE_ALWAYS);
		f_write(&myFile, myWrite, 30, &byteCount);
		f_close(&myFile);
 
		f_open(&myFile, "test.txt", FA_READ);
		f_read(&myFile, myRead, 5, &byteCount);
		f_close(&myFile);
	}else{
		printf("mount fail :(\r\n");
		printf("err. code: %d\r\n", fRet);
	}
	
	// ...
	
	while (1)
	{
		// ...
	}
}

The same code works if I generate SDIO 1 bit mode with CubeMX, but I get the above mentioned 'FR_NO_FILESYSTEM' error with 4 bit SDIO mode.

Please help me how can I solve this.

Thank you in advance!

28 REPLIES 28

If you have overly aggressive slew-rate settings on the GPIO pins you might want to back them off.

You might consider series resistors.

The SDIO is sensitive to bit skewing between the pins, make sure the trace lengths are equivalent.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

hmm, i just found out that 2GB SD card is working in 4 bit mode, 4GB or even higher isn´t. Any ideas how to solve that?

Is this with custom hardware?

What are we working with here?​

Most everything should support 25 MHz, current microsd should support 50 MHz.

Got external pullups on data and cmd pins?​

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
DOsbo
Senior

Hi Guys,

My experience with SDIO is probably not relevant to your micros, but it might help anyone using the STM32H7 evaluation board. My problems revolved around the DMA transfer to the SD card. I was constantly getting DMA Tx Underruns. That forced me to slow the SD Clock to less than 20MHz. Even though that ridiculously slow speed avoided the underruns, I noticed the DMA was just transferring zeros instead of real data. That issue manifested as a FR_NO_FILESYSTEM because it failed to write the boot sector in the previous step.

The solution was to move the DMA buffers to the internal SRAM section (located at 0x24000000 on STM32H7) and disable the cache for that region. The buffers include the FATFS structure passed to f_mount() and the buffer passed to f_mkfs(). I suspect the buffer passed to f_write() and f_read() should also be located there if they are large. Once I made that change I was able to increase the SD clock to a more respectable 100MHz.

I still don't know why the other RAMs (DTCMRAM, RAM_D2, RAM_D3 and external SDRAM) didn't work with the DMA. It's probably something to do with the infinitely complex internal bus structure.

Here's one for the gurus: Why does the BSD SD example not call HAL_SD_ConfigSpeedBusOperation(), but it calls HAL_SD_ConfigWideBusOperation() twice? Methinks something is not quite right with HAL_SD_Init(), but who cares - it works (usually).

Cheers,

David

I am using a micro SD breakoutboard with external pull ups, STM32F401RE nucleo board and I tried different micro SD cards.

2GB is working without a problem in 4 bit mode. But all the others, 4GB,8GB,... aren´t working. Whether they are not getting mounted or if they get mounted the write functions doesn´t work....

My current poblem is that it is not possible to write to the sd card. Here is a snippet of code:

void write_to_SD(char myPath[],char myData[],int length)
{
	HAL_UART_Transmit(&huart2, (uint8_t *)"Function: write_to_SD \n\n", (uint16_t) sizeof("Function: write_to_SD \n\n"), 10);
    if(f_mount(&myFAT, "", 1) != FR_OK)
    {
      /* FatFs Initialization Error */
			HAL_UART_Transmit(&huart2, (uint8_t *)"ERROR: SD NOT MOUNTED \n\n", (uint16_t) sizeof("SD NOT MOUNTED \n\n"), 10);
      Error_Handler();
    }
    else
    {  
			HAL_UART_Transmit(&huart2, (uint8_t *)"SD Card mounted \n\n", (uint16_t) sizeof("SD Card mounted \n\n"), 10);
			/*##Create and Open a new text file object with write access #*/
			if(f_open(&myFILE, myPath, FA_CREATE_ALWAYS | FA_WRITE) != FR_OK)
			{
				/* 'STM32.TXT' file Open for write Error */
				HAL_UART_Transmit(&huart2, (uint8_t *)"ERROR: not opened \n\n", (uint16_t) sizeof("ERROR: not opened \n\n"), 10);
				Error_Handler();
			}
			else
			{   
				HAL_UART_Transmit(&huart2, (uint8_t *)"SD Card opened \n\n", (uint16_t) sizeof("SD Card opened \n\n"), 10);
				/*##Write data to the text file*/
				res = f_write(&myFILE, myData, length, (void *)&byteswritten);
				HAL_UART_Transmit(&huart2, (uint8_t *)"File written \n\n", (uint16_t) sizeof("File written \n\n"), 10);
				HAL_Delay(100);
				/*##Close the open text file*/
				if (f_close(&myFILE) != FR_OK )
				{
					HAL_UART_Transmit(&huart2, (uint8_t *)"ERROR: not closed \n\n", (uint16_t) sizeof("ERROR: not closed \n\n"), 10);
					Error_Handler();
				}
				f_mount(0, "", 1);
				HAL_UART_Transmit(&huart2, (uint8_t *)"SD Card closed and unmounted \n\n", (uint16_t) sizeof("SD Card closed and unmounted \n\n"), 10);
				myPath=0;
				myData=0;
				if((byteswritten == 0) || (res != FR_OK))
				{
					/* 'STM32.TXT' file Write or EOF Error */
					HAL_UART_Transmit(&huart2, (uint8_t *)"WRITE DOES NOT WORK \n\n", (uint16_t) sizeof("WRITE DOES NOT WORK \n\n"), 10);
					Error_Handler();
				}
			}
		}
}

And here is the output:

Function: write_to_SD
 
SD Card mounted
 
SD Card opened
 
File written
 
ERROR: not closed
 
SD Card closed and unmounted
 
WRITE DOES NOT WORK

Furthermore here is my usb_storage_if.c

Maybe one of you know what i am doing wrong. really appriciate the help

/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : usbd_storage_if.c
  * @version        : v1.0_Cube
  * @brief          : Memory management layer.
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
  * All rights reserved.</center></h2>
  *
  * This software component is licensed by ST under Ultimate Liberty license
  * SLA0044, the "License"; You may not use this file except in compliance with
  * the License. You may obtain a copy of the License at:
  *                             www.st.com/SLA0044
  *
  ******************************************************************************
  */
/* USER CODE END Header */
 
/* Includes ------------------------------------------------------------------*/
#include "usbd_storage_if.h"
 
/* USER CODE BEGIN INCLUDE */
 
#include "bsp_driver_sd.h"
 
 
 
/* USER CODE END INCLUDE */
 
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
 
/* USER CODE BEGIN PV */
/* Private variables ---------------------------------------------------------*/
 
/* USER CODE END PV */
 
/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
  * @brief Usb device.
  * @{
  */
 
/** @defgroup USBD_STORAGE
  * @brief Usb mass storage device module
  * @{
  */
 
/** @defgroup USBD_STORAGE_Private_TypesDefinitions
  * @brief Private types.
  * @{
  */
 
/* USER CODE BEGIN PRIVATE_TYPES */
 
/* USER CODE END PRIVATE_TYPES */
 
/**
  * @}
  */
 
/** @defgroup USBD_STORAGE_Private_Defines
  * @brief Private defines.
  * @{
  */
 
 
/* USER CODE BEGIN PRIVATE_DEFINES */
 
 
#define STORAGE_SD_CARD_CAPACITY				(7721713664) //SD 8GB auf 4GBFAT
 
// 8GB ohne partitionierung??mit FAT32
 
//#define STORAGE_SD_CARD_CAPACITY				(3669753856) //SD 16GB auf 4GB
//#define STORAGE_SD_CARD_CAPACITY				(2025652224) //SD 2GB FAT
//#define STORAGE_SD_CARD_CAPACITY				(1932476992) //SD 2GB FAT32
 
#define STORAGE_LUN_NBR                  1  
#define STORAGE_BLK_SIZ                  4096
#define STORAGE_BLK_NBR                  STORAGE_SD_CARD_CAPACITY/STORAGE_BLK_SIZ 
/* USER CODE END PRIVATE_DEFINES */
 
/**
  * @}
  */
 
/** @defgroup USBD_STORAGE_Private_Macros
  * @brief Private macros.
  * @{
  */
 
/* USER CODE BEGIN PRIVATE_MACRO */
 
/* USER CODE END PRIVATE_MACRO */
 
/**
  * @}
  */
 
/** @defgroup USBD_STORAGE_Private_Variables
  * @brief Private variables.
  * @{
  */
 
/* USER CODE BEGIN INQUIRY_DATA_FS */
/** USB Mass storage Standard Inquiry Data. */
const int8_t STORAGE_Inquirydata_FS[] = {/* 36 */
  
  /* LUN 0 */
  0x00,
  0x80,
  0x02,
  0x02,
  (STANDARD_INQUIRY_DATA_LEN - 5),
  0x00,
  0x00,	
  0x00,
  'S', 'T', 'M', ' ', ' ', ' ', ' ', ' ', /* Manufacturer : 8 bytes */
  'P', 'r', 'o', 'd', 'u', 'c', 't', ' ', /* Product      : 16 Bytes */
  ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
  '0', '.', '0' ,'1'                      /* Version      : 4 Bytes */
}; 
/* USER CODE END INQUIRY_DATA_FS */
 
/* USER CODE BEGIN PRIVATE_VARIABLES */
 
/* USER CODE END PRIVATE_VARIABLES */
 
/**
  * @}
  */
 
/** @defgroup USBD_STORAGE_Exported_Variables
  * @brief Public variables.
  * @{
  */
 
extern USBD_HandleTypeDef hUsbDeviceFS;
 
/* USER CODE BEGIN EXPORTED_VARIABLES */
extern SD_HandleTypeDef hsd;
extern UART_HandleTypeDef huart2;
/* USER CODE END EXPORTED_VARIABLES */
 
/**
  * @}
  */
 
/** @defgroup USBD_STORAGE_Private_FunctionPrototypes
  * @brief Private functions declaration.
  * @{
  */
 
static int8_t STORAGE_Init_FS(uint8_t lun);
static int8_t STORAGE_GetCapacity_FS(uint8_t lun, uint32_t *block_num, uint16_t *block_size);
static int8_t STORAGE_IsReady_FS(uint8_t lun);
static int8_t STORAGE_IsWriteProtected_FS(uint8_t lun);
static int8_t STORAGE_Read_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len);
static int8_t STORAGE_Write_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len);
static int8_t STORAGE_GetMaxLun_FS(void);
 
/* USER CODE BEGIN PRIVATE_FUNCTIONS_DECLARATION */
 
/* USER CODE END PRIVATE_FUNCTIONS_DECLARATION */
 
/**
  * @}
  */
 
USBD_StorageTypeDef USBD_Storage_Interface_fops_FS =
{
  STORAGE_Init_FS,
  STORAGE_GetCapacity_FS,
  STORAGE_IsReady_FS,
  STORAGE_IsWriteProtected_FS,
  STORAGE_Read_FS,
  STORAGE_Write_FS,
  STORAGE_GetMaxLun_FS,
  (int8_t *)STORAGE_Inquirydata_FS
};
 
/* Private functions ---------------------------------------------------------*/
/**
  * @brief  Initializes over USB FS IP
  * @param  lun:
  * @retval USBD_OK if all operations are OK else USBD_FAIL
  */
int8_t STORAGE_Init_FS(uint8_t lun)
{
  /* USER CODE BEGIN 2 */
	//MX_SDIO_SD_Init();
  //BSP_SD_Init();
	
  return 0;
  /* USER CODE END 2 */
}
 
/**
  * @brief  .
  * @param  lun: .
  * @param  block_num: .
  * @param  block_size: .
  * @retval USBD_OK if all operations are OK else USBD_FAIL
  */
int8_t STORAGE_GetCapacity_FS(uint8_t lun, uint32_t *block_num, uint16_t *block_size)
{
  /* USER CODE BEGIN 3 */
 
	HAL_SD_CardInfoTypeDef info;
	int8_t ret = -1;  	
	
	  if (BSP_SD_IsDetected() != SD_NOT_PRESENT)
  {
    HAL_SD_GetCardInfo(&hsd,&info);
 
    *block_num = info.LogBlockNbr - 1;
    *block_size = info.LogBlockSize;
    ret = 0;
  }
		
	return ret;
  /* USER CODE END 3 */
}
 
/**
  * @brief  .
  * @param  lun: .
  * @retval USBD_OK if all operations are OK else USBD_FAIL
  */
int8_t STORAGE_IsReady_FS(uint8_t lun)
{
  /* USER CODE BEGIN 4 */
  static int8_t prev_status = 0;
  int8_t ret = -1;
 
  if (BSP_SD_IsDetected() != SD_NOT_PRESENT)
  {
    if (prev_status < 0)
    {
      BSP_SD_Init();
      prev_status = 0;
 
    }
    if (BSP_SD_GetCardState() == SD_TRANSFER_OK)
    {
      ret = 0;
    }
  }
  else if (prev_status == 0)
  {
    prev_status = -1;
  }
  return ret;
 
  /* USER CODE END 4 */
}
 
/**
  * @brief  .
  * @param  lun: .
  * @retval USBD_OK if all operations are OK else USBD_FAIL
  */
int8_t STORAGE_IsWriteProtected_FS(uint8_t lun)
{
  /* USER CODE BEGIN 5 */
  return 0;
  /* USER CODE END 5 */
}
 
/**
  * @brief  .
  * @param  lun: .
  * @retval USBD_OK if all operations are OK else USBD_FAIL
  */
int8_t STORAGE_Read_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len)
{
  /* USER CODE BEGIN 6 */
  int8_t ret = -1;  
  
  if(BSP_SD_IsDetected() != SD_NOT_PRESENT)
  {  
    BSP_SD_ReadBlocks((uint32_t *)buf, blk_addr, blk_len,100);
 
 
    /* Wait until SD card is ready to use for new operation */
    while (BSP_SD_GetCardState() != SD_TRANSFER_OK){}
    ret = 0;
  }
  return ret;
 
  /* USER CODE END 6 */
}
 
/**
  * @brief  .
  * @param  lun: .
  * @retval USBD_OK if all operations are OK else USBD_FAIL
  */
int8_t STORAGE_Write_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len)
{
  /* USER CODE BEGIN 7 */
   int8_t ret = -1;  
  
  if(BSP_SD_IsDetected() != SD_NOT_PRESENT)
  { 
    BSP_SD_WriteBlocks((uint32_t *)buf, blk_addr, blk_len,100);
    
 
    
    /* Wait until SD card is ready to use for new operation */
    while (BSP_SD_GetCardState() != SD_TRANSFER_OK){}
    ret = 0;
  }
  return ret;
  /* USER CODE END 7 */
}
 
/**
  * @brief  .
  * @param  None
  * @retval .
  */
int8_t STORAGE_GetMaxLun_FS(void)
{
  /* USER CODE BEGIN 8 */
  return (STORAGE_LUN_NBR - 1);
  /* USER CODE END 8 */
}
 
/* USER CODE BEGIN PRIVATE_FUNCTIONS_IMPLEMENTATION */
 
/* USER CODE END PRIVATE_FUNCTIONS_IMPLEMENTATION */
 
/**
  * @}
  */
 
/**
  * @}
  */
 
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

MBabu.1
Associate II

I had a similar issue but only if I enable compile optimization. This hinted me to introduce a 1ms sleep between HAL_SD_Init and HAL_SD_ConfigWideBusOperation (also for 4 Bit operation). These functions are called in the STM32 example code of BSP_SD_Init. After a lot of tries this worked like a charm - for release and debug builds.

I am not 100% sure if this might be related to actual hardware issues (delays by RCs, timing delays between the 4 Bit wires, ...) but it is worth a try.

JGarc.5
Associate III

I have a similar problem.

When I use (with all the other settings unchanged) :

1 bit SDIO, I can run the SDIO clock at 24Mhz (SDMMC1 clock at 48MHz, clock divider at 0).

4 bit SDIO, I can run the SDIO clock at 6Mhz (SDMMC1 clock at 48MHz, clock divider at 6).

This is running on a L476RG (nucleo), with system core at 64MHz.

Where is the problem here? Maybe is someting with the routing? (I have not inspected the Dx lines with the oscilloscope)

Any ideas?

I found a solution activating hardware flow control of SDIO within CubeMx