on
2021-09-24
12:17 AM
- edited on
2024-06-04
04:57 AM
by
Laurids_PETERSE
Data logging applications require storing large amounts of data over a period of time. SD cards are a convenient solution for storing data and many STM32 products include the proper hardware interface. Using a standard file system to write data on an SD card ensures that the data is easily accessible on another device or computer. Adding a file system along with an SD card driver is easy to do using the various ST tools available for the STM32 family of microcontrollers.
This article shows you how to create a file system on a SD card using STM32 and ST Toolsets.
STM32 Discovery Kits as well as evaluation boards include an SD card socket. While this example uses the STM32F746G-DISCO board, any other STM32 board with an SD card socket can be used along with appropriate changes made in the software configuration for a different target board.
We will use pre-set peripheral configuration from the board configuration file.
SDMMC is a peripheral that can be used to interface to a SD card.
FatFs is an open-source file system middleware. This is integrated in STM32 Cube Libraries.
This will permit to achieve best performance.
/* USER CODE BEGIN 1 */
FRESULT res; /* FatFs function common result code */
uint32_t byteswritten, bytesread; /* File write/read counts */
uint8_t wtext[] = "STM32 FATFS works great!"; /* File write buffer */
uint8_t rtext[_MAX_SS];/* File read buffer */
/* USER CODE END 1 */
...
/* USER CODE BEGIN 2 */
if(f_mount(&SDFatFS, (TCHAR const*)SDPath, 0) != FR_OK)
{
Error_Handler();
}
else
{
if(f_mkfs((TCHAR const*)SDPath, FM_ANY, 0, rtext, sizeof(rtext)) != FR_OK)
{
Error_Handler();
}
else
{
//Open file for writing (Create)
if(f_open(&SDFile, "STM32.TXT", FA_CREATE_ALWAYS | FA_WRITE) != FR_OK)
{
Error_Handler();
}
else
{
//Write to the text file
res = f_write(&SDFile, wtext, strlen((char *)wtext), (void *)&byteswritten);
if((byteswritten == 0) || (res != FR_OK))
{
Error_Handler();
}
else
{
f_close(&SDFile);
}
}
}
}
f_mount(&SDFatFS, (TCHAR const*)NULL, 0);
/* USER CODE END 2 */
When the code is executed, the SD card will be formatted and a file will be written, you can check the content with an SD card reader.
Here is a video that explains how to create a File System on SD card using STM32CubeIDE as explained in this article.
STM32 – Creating a File System on a SD card - YouTube
Has anyone tried this code on a STM32L471RGT6? It doesn't appear to work and fails at line if(f_mkfs((TCHAR const*)SDPath, FM_ANY, 0, rtext, sizeof(rtext)) != FR_OK
Thanks in advance
I'm using a different board and connector. My connector's detect switch is active high. I had to change this line of code in fatfs_platform.c from "RESET" to "SET".
if(HAL_GPIO_ReadPin(SD_DETECT_GPIO_PORT, SD_DETECT_PIN) != GPIO_PIN_SET)
This has to be changed to set anytime the ioc file is updated.
Also, try setting the SDMMC clock divide factor to something greater than 0. 0x80 for example. ioc configuration, SDMMC1, Parameters tab.
Hi,
I am using the same dev board. Followed all the steps above. My STCubeIDE version is 1.11.2. Program gets stuck at:
if(f_mkfs((TCHAR const*)SDPath, FM_ANY, 0, rtext, sizeof(rtext)) != FR_OK)
{
Error_Handler();
}
with "FR_NOT_READY"
checked and rechecked again, used various SDCards but same.
Any advice is appreciated.
Thanks,
Tim
Made it work with couple of modifications:
1- Moved variables to global
move
"
/* USER CODE BEGIN 1 */
FRESULT res; /* FatFs function common result code */
uint32_t byteswritten, bytesread; /* File write/read counts */
uint8_t wtext[] = "STM32 FATFS works great!"; /* File write buffer */
uint8_t rtext[_MAX_SS];/* File read buffer */
/* USER CODE END 1 */
"
to
"
* USER CODE BEGIN PV */
FRESULT res; /* FatFs function common result code */
uint32_t byteswritten, bytesread; /* File write/read counts */
uint8_t wtext[] = "STM32 FATFS cali666siy great!"; /* File write buffer */
uint8_t rtext[_MAX_SS];/* File read buffer */
/* USER CODE END PV */
"
2- Changed 4B wide operation to 1B operation in "MX_SDMMC1_SD_Init()"
static void MX_SDMMC1_SD_Init(void)
{
/* USER CODE BEGIN SDMMC1_Init 0 */
/* USER CODE END SDMMC1_Init 0 */
/* USER CODE BEGIN SDMMC1_Init 1 */
/* USER CODE END SDMMC1_Init 1 */
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_1B; //Start with 1B instead 4B. Later "SD_Widebus_Enable" command makes it 4B
hsd1.Init.HardwareFlowControl = SDMMC_HARDWARE_FLOW_CONTROL_DISABLE;
hsd1.Init.ClockDiv = 0;
/* USER CODE BEGIN SDMMC1_Init 2 */
/* USER CODE END SDMMC1_Init 2 */
}
now it works OK. Tested with 4GB and 16GB FAT32 formatted uSD cards
Tim
Thank's for your advice, now my SD Card program works fine.
My code does not work, I even moved some variables to global, still not working. Please help me out. My hardware PCB uses a 4-bit wide bus, and my SD Card is FAT32 8GB. It only works upto f_mount() which returns FR_OK, but after that, the f_open returns FR_DISK_ERR.
I had the same problem with f_mount(). I use the same solution as described by JBond.1
https://community.st.com/t5/stm32cubemx-mcus/sdcard-does-not-work-with-4bits-wide-bus/td-p/602607
It works fine! You don't need to do the steps described by TKana.1
I use STM32CubeIDE Version: 1.13.2 and STM32CubeF4 Firmware Package V1.27.0 / 11-February-2022
Hello, Can anyone Tell me is it mandatory to Format a new SD Card before writing or Reading data in STM32 MCU. Currently I am facing an issue wherein whenever I try to write data into a new non-formatted SD Card, It gives me an error but whenever I try to write data into a SD card using a card reader, it gets written. Thanks for help in advance.
Hi,
>is it mandatory to Format a new SD Card
NO! You should never format a new sd-card, because they are format to the optimum for that card.
So format -especially as first action on a new system- might with good chance destroy the card or at least make it worse (getting slower) . Especially on new, big (> 32GB) cards in exfat format.
Also dont write - until mount, open directory and reading files working perfect. Then can try write something.
Like others it failed at f_mkfs. I watched the video for this guide...
https://www.youtube.com/watch?v=I9KDN1o6924
...and there is a step missing from this written guide. The missing step, as shown in the video, is to add the DMA Rx and Tx..
Since adding the dma rx/tx and changing the SD mode from 4 bit wide to 1 bit, it now works.
For some reason it does not work in SD mode 4 bit wide
I had the same problems. I couldn't not to get it working in 4bit mode but I got it working in 1 bit mode.
Actually when I tried older version of CubeMX the 4bit mode works. I think there is bug in latest CubeMX.
I got this reply from STM32 tech support
On December 4, 2023 at 2:34 PM
It turned out to be a problem on CubeMX code generation that we cannot configure SDMMC and the FatFS at the same time. This will be fixed in the next release of CubeMX.
I tried new chip and the same problem. I set up 1bit mode in CubeMX, I moved to:
/* USER CODE BEGIN 0 */
FRESULT res; /* FatFs function common result code */
uint32_t byteswritten, bytesread; /* File write/read counts */
uint8_t wtext[] = "new file test"; /* File write buffer */
uint8_t rtext[_MAX_SS];/* File read buffer */
/* USER CODE END 0 */
If you do not have PIN detect for SD card connected change this line change it in fatfs_platform.c
Here is a small update. I tired to setup in SD 4 bits in CubeMX and of course it did not work. New customs another board with STM32H7A3ZIT6. I generated the code anyway and made some custom changes. I initialize it first in 1 bit mode. Then in 4 bit and it worked. DMA setting did not have any influence if it works or nor. My SD card works with speed up to 64 MHz, setup the clock in CubeMX. Also make sure the settings in
static void MX_SDMMC2_SD_Init(void)
{
/* USER CODE BEGIN SDMMC2_Init 0 */
hsd2.Instance = SDMMC2;
hsd2.Init.ClockEdge = SDMMC_CLOCK_EDGE_RISING;
hsd2.Init.ClockPowerSave = SDMMC_CLOCK_POWER_SAVE_DISABLE;
hsd2.Init.BusWide = SDMMC_BUS_WIDE_1B;
/* USER CODE END SDMMC2_Init 0 */
/* USER CODE BEGIN SDMMC2_Init 1 */
/* USER CODE END SDMMC2_Init 1 */
hsd2.Instance = SDMMC2;
hsd2.Init.ClockEdge = SDMMC_CLOCK_EDGE_RISING;
hsd2.Init.ClockPowerSave = SDMMC_CLOCK_POWER_SAVE_DISABLE;
hsd2.Init.BusWide = SDMMC_BUS_WIDE_4B;
hsd2.Init.HardwareFlowControl = SDMMC_HARDWARE_FLOW_CONTROL_DISABLE;
hsd2.Init.ClockDiv = 0;
/* USER CODE BEGIN SDMMC2_Init 2 */
/* USER CODE END SDMMC2_Init 2 */
}
here are also fatfs settings which work for me
I have on H743VI SD-card running with no problems (in 4 bit mode, 50MHz clock) :
/* USER CODE END SDMMC1_Init 1 */
hsd1.Instance = SDMMC1;
hsd1.Init.ClockEdge = SDMMC_CLOCK_EDGE_RISING;
hsd1.Init.ClockPowerSave = SDMMC_CLOCK_POWER_SAVE_ENABLE;
hsd1.Init.BusWide = SDMMC_BUS_WIDE_4B;
hsd1.Init.HardwareFlowControl = SDMMC_HARDWARE_FLOW_CONTROL_ENABLE;
hsd1.Init.ClockDiv = 1;
/* USER CODE BEGIN SDMMC1_Init 2 */
if (HAL_SD_Init(&hsd1) != HAL_OK)
{
Error_Handler();
}
/* USER CODE END SDMMC1_Init 2 */
STM32Cube FW_H7 V1.10.0
Had similar issue on STM32F746G-Disco EVB. Changing SDMMC_BUS_WIDE_4B to SDMMC_BUS_WIDE_1B resolved the issue
STM32CubeIDE Version: 1.13.2 Build: 18220_20230914_1601
Same here with STM32F446.
I fixed the SDIO bug by adding the following line:
static void MX_SDIO_SD_Init(void)
{
...
/* USER CODE BEGIN SDIO_Init 2 */
hsd.Init.BusWide = SDIO_BUS_WIDE_1B; //add this line, so that the automatic code generetation with STM32CubeIDE does not override the configuration
/* USER CODE END SDIO_Init 2 */
}
As proposed here SDCARD does not work (FR_NOT_READY) when migrating from FW_F4 V1.27.0 to newer FW_F4 V1.27.1