This is a comprehensive guide for STM32 SDIO SD Card Interfacing With FatFS Library. You’ll learn how to use SD Cards with STM32 microcontrollers using the SDIO interface. We’ll create some STM32 SD Card Example Test Projects to verify what we’ll be learning in this tutorial.
Table of Contents
- STM32 SDIO (Secure Digital IO)
- STM32 SDIO SD Card Interfacing
- STM32 SDIO SD Card FatFS Example Project
- STM32 SDIO 4-Bit Example
- Wrap Up
STM32 SDIO (Secure Digital IO)
Some STM32 microcontroller series have an integrated SDIO (SDMMC) hardware peripheral that’s designed specifically to interface SD cards at the maximum speed.
However, SD cards can still be used over SPI communication which is available in all STM32 microcontrollers and pretty much every single microcontroller in the market. We’ve already focused on STM32 SD Card SPI interfacing in this previous tutorial. Therefore, in this tutorial, we’ll shift the attention to using the STM32 SDIO interface for SD Card handling.
STM32 SPI Vs SDIO Vs SDMMC
SPI is a generic serial peripheral interface and can still be used to interface SD cards with low-end microcontrollers at a relatively lower speed of communication and a much simpler software stack. That’s why SPI is the most commonly used interface for SD cards in a lot of projects.
SDIO is a hardware peripheral designed specifically for interfacing (SD Cards, SDIO Cards, and MultiMedia Cards “MMC”) with the APB2 peripheral bus in “some” of the STM32 microcontrollers. Given that it’s dedicated to SD card interfacing, it’s going to be a much faster way of communicating with SD cards (4x the speed you can get with an SPI interface).
SDMMC is a hardware peripheral designed specifically for interfacing (SD memory cards, SDIO cards, and eMMC devices) with the APB2 peripheral bus in “some” of the STM32 microcontrollers. It’s almost identical to the SDIO interface but it supports eMMC devices additionally and can go up to way higher transfer speeds (in 8-Bit mode).
STM32 SDIO Features
- Full compliance with MultiMediaCard (MMC) System Specification Version 4.2. Card support for three different databus modes: 1-bit (default), 4-bit and 8-bit
- Full compatibility with previous versions of MultiMediaCards (backward compatibility)
- Data transfer up to 50 MHz for the 8-bit mode
The SDIO does not have an SPI-compatible communication mode.
STM32 SDIO SD Card Interfacing
In this section, we’ll discuss how to interface STM32 microcontrollers with SD Cards using the SDIO interface.
Preparing The SD Card
Use an SD Card Reader for this step.
Before using your SD card, make sure you’ve Formatted it to the FAT (FAT32/FAT) file system (in your operating system of choice).
STM32 SDIO SD Card Hardware Design
If you’re designing your own STM32-based PCB board project that requires having an SD card memory slot onboard, you’ll need to connect your STM32 SDIO pins to the SD Card slot as shown below.
The GPIO pin (PA8) in the schematic design shown above is used for “SD Card Presence Detection”, and you can read its state in software if needed.
Also keep in mind that all SDIO pins, except the CLK, need to be pulled up either in hardware or in software configurations of the STM32 GPIO pins. While routing the DATA lines during the PCB design, make sure the lines are matched to maximize signal integrity for high-speed communication.
Development Board
For quick prototyping and project idea testing, you can use any STM32 development board that has a target microcontroller with an internal SDIO interface as well as the hardware SD Card socket onboard. For me, I’ve used This STM32F405 Development Board from WeAct. But you can use any other STM32 development board that satisfies those two conditions.
However, if you’ve got an STM32 development board that doesn’t have an SD card slot but its target microcontroller still has an SDIO interface, you can use an SD Card breakout board like this and wire them up together as shown in the schematic diagram shown earlier.
Buy an SD Card SDIO Breakout Board (on Amazon)
STM32 SDIO SD Card FatFS Example Project
In this example project, our ultimate goal is to test the STM32 SDIO interface with an SD Card and also test the functionalities provided by the FatFS library and use it to create a text file, write to it, read the file, modify the existing file, and delete the file. We’ll monitor the progress of this test sequence using USB CDC (VCP) messages printed to the serial monitor on the PC.
SD Card Tests Included in This Project:
- Mount The SD Card
- Find and print the card size & free space
- Create a new Text File
- Write to the text file using the f_puts() function
- Write to the text file using the f_write() function
- Read from the text file using the f_gets() function
- Read from the text file using the f_read() function
- Modify (update) an existing file
- Delete the file
- Unmount the SD Card
Please, follow The step-by-step guide below to create the project, configure the needed hardware peripherals in CubeMX, add the FATFS_SD driver folder, and run the test project on your STM32 dev board.
Step #1
Create a New Project in STM32CubeMX
The first step is to head over to STM32CubeMX, create a new project, enable the SWD (serial wire debug), enable the external HSE oscillator, and configure the RCC clock.
Step #2
Configure 1x USB CDC Device
Enable a USB CDC device to be used as a serial communication with the PC through Windows virtual COM port (VCP). Leave the default settings as is, no need to change them.
Step #3
Configure The SDIO Module To Be Used For SD Card Interfacing
Here, I’m using the SDIO 1-Bit mode while the rest of the settings are left as default.
Make sure that all SDIO GPIO pins are internally, or externally, pulled-up except for the CLK line.
Step #4
Enable The FatFS Library
Edit the library configurations as shown below.
Once you’re done with CubeMX configurations, generate the project code and head over to STM32CubeIDE.
Step #5
Copy The Project’s Code Below into Your Main.c File
Build The Project, Flash The Code To The STM32 Board, and Start Testing!
STM32 SDIO SD Card FatFS Example Code
The Application Code For This Example (main.c)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 |
/* * LAB Name: STM32 SDIO SD Card Interfacing Example * Author: Khaled Magdy * For More Info Visit: www.DeepBlueMbedded.com */ #include "main.h" #include "fatfs.h" #include "usb_device.h" #include "usbd_cdc_if.h" #include <stdio.h> #include <string.h> SD_HandleTypeDef hsd; char TxBuffer[250]; void SystemClock_Config(void); static void MX_GPIO_Init(void); static void MX_SDIO_SD_Init(void); static void SDIO_SDCard_Test(void); static void USB_CDC_Print(char* TxStr) { while(CDC_Transmit_FS((uint8_t*)TxStr, strlen(TxStr)) == USBD_BUSY); } int main(void) { HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_USB_DEVICE_Init(); MX_SDIO_SD_Init(); MX_FATFS_Init(); // Test The SDIO SD Card Interface HAL_Delay(5000); // This delay is not mandatory but it gives me some time to connect the USB cable and open the terminal SDIO_SDCard_Test(); while (1) { // Nothing To Do Here! } } static void SDIO_SDCard_Test(void) { FATFS FatFs; FIL Fil; FRESULT FR_Status; FATFS *FS_Ptr; UINT RWC, WWC; // Read/Write Word Counter DWORD FreeClusters; uint32_t TotalSize, FreeSpace; char RW_Buffer[200]; do { //------------------[ Mount The SD Card ]-------------------- FR_Status = f_mount(&FatFs, SDPath, 1); if (FR_Status != FR_OK) { sprintf(TxBuffer, "Error! While Mounting SD Card, Error Code: (%i)\r\n", FR_Status); USB_CDC_Print(TxBuffer); break; } sprintf(TxBuffer, "SD Card Mounted Successfully! \r\n\n"); USB_CDC_Print(TxBuffer); //------------------[ Get & Print The SD Card Size & Free Space ]-------------------- f_getfree("", &FreeClusters, &FS_Ptr); TotalSize = (uint32_t)((FS_Ptr->n_fatent - 2) * FS_Ptr->csize * 0.5); FreeSpace = (uint32_t)(FreeClusters * FS_Ptr->csize * 0.5); sprintf(TxBuffer, "Total SD Card Size: %lu Bytes\r\n", TotalSize); USB_CDC_Print(TxBuffer); sprintf(TxBuffer, "Free SD Card Space: %lu Bytes\r\n\n", FreeSpace); USB_CDC_Print(TxBuffer); //------------------[ Open A Text File For Write & Write Data ]-------------------- //Open the file FR_Status = f_open(&Fil, "MyTextFile.txt", FA_WRITE | FA_READ | FA_CREATE_ALWAYS); if(FR_Status != FR_OK) { sprintf(TxBuffer, "Error! While Creating/Opening A New Text File, Error Code: (%i)\r\n", FR_Status); USB_CDC_Print(TxBuffer); break; } sprintf(TxBuffer, "Text File Created & Opened! Writing Data To The Text File..\r\n\n"); USB_CDC_Print(TxBuffer); // (1) Write Data To The Text File [ Using f_puts() Function ] f_puts("Hello! From STM32 To SD Card Over SDIO, Using f_puts()\n", &Fil); // (2) Write Data To The Text File [ Using f_write() Function ] strcpy(RW_Buffer, "Hello! From STM32 To SD Card Over SDIO, Using f_write()\r\n"); f_write(&Fil, RW_Buffer, strlen(RW_Buffer), &WWC); // Close The File f_close(&Fil); //------------------[ Open A Text File For Read & Read Its Data ]-------------------- // Open The File FR_Status = f_open(&Fil, "MyTextFile.txt", FA_READ); if(FR_Status != FR_OK) { sprintf(TxBuffer, "Error! While Opening (MyTextFile.txt) File For Read.. \r\n"); USB_CDC_Print(TxBuffer); break; } // (1) Read The Text File's Data [ Using f_gets() Function ] f_gets(RW_Buffer, sizeof(RW_Buffer), &Fil); sprintf(TxBuffer, "Data Read From (MyTextFile.txt) Using f_gets():%s", RW_Buffer); USB_CDC_Print(TxBuffer); // (2) Read The Text File's Data [ Using f_read() Function ] f_read(&Fil, RW_Buffer, f_size(&Fil), &RWC); sprintf(TxBuffer, "Data Read From (MyTextFile.txt) Using f_read():%s", RW_Buffer); USB_CDC_Print(TxBuffer); // Close The File f_close(&Fil); sprintf(TxBuffer, "File Closed! \r\n\n"); USB_CDC_Print(TxBuffer); //------------------[ Open An Existing Text File, Update Its Content, Read It Back ]-------------------- // (1) Open The Existing File For Write (Update) FR_Status = f_open(&Fil, "MyTextFile.txt", FA_OPEN_EXISTING | FA_WRITE); FR_Status = f_lseek(&Fil, f_size(&Fil)); // Move The File Pointer To The EOF (End-Of-File) if(FR_Status != FR_OK) { sprintf(TxBuffer, "Error! While Opening (MyTextFile.txt) File For Update.. \r\n"); USB_CDC_Print(TxBuffer); break; } // (2) Write New Line of Text Data To The File FR_Status = f_puts("This New Line Was Added During File Update!\r\n", &Fil); f_close(&Fil); memset(RW_Buffer,'\0',sizeof(RW_Buffer)); // Clear The Buffer // (3) Read The Contents of The Text File After The Update FR_Status = f_open(&Fil, "MyTextFile.txt", FA_READ); // Open The File For Read f_read(&Fil, RW_Buffer, f_size(&Fil), &RWC); sprintf(TxBuffer, "Data Read From (MyTextFile.txt) After Update:\r\n%s", RW_Buffer); USB_CDC_Print(TxBuffer); f_close(&Fil); //------------------[ Delete The Text File ]-------------------- // Delete The File /* FR_Status = f_unlink(MyTextFile.txt); if (FR_Status != FR_OK){ sprintf(TxBuffer, "Error! While Deleting The (MyTextFile.txt) File.. \r\n"); USC_CDC_Print(TxBuffer); } */ } while(0); //------------------[ Test Complete! Unmount The SD Card ]-------------------- FR_Status = f_mount(NULL, "", 0); if (FR_Status != FR_OK) { sprintf(TxBuffer, "\r\nError! While Un-mounting SD Card, Error Code: (%i)\r\n", FR_Status); USB_CDC_Print(TxBuffer); } else{ sprintf(TxBuffer, "\r\nSD Card Un-mounted Successfully! \r\n"); USB_CDC_Print(TxBuffer); } } |
Test Setup
This is my test setup for this example project. I’m using a 2GB SD card as well as a USB cable to connect the STM32 USB CDC to my PC as a virtual COM port. The SD card socket is already soldered to the bottom of my development board as stated earlier according to the schematic design figure that I did also show earlier in this tutorial. That’s all about it!
Testing Result
Here is the test result that’s printed on the serial monitor.
And this is the content of the SD card after running this example project as shown on my PC file manager.
STM32 SDIO 4-Bit Example
You can use the STM32 SDIO 4-Bit mode by choosing it in the CubeMX configurations as shown below.
Do not forget to activate internal pull-ups for all SDIO lines except for the CLK line (if they are not already externally pulled up in your board hardware schematic design).
You can use the exact same code of the previous example project with no extra changes, only the CubeMX configurations need adjustment and you may also need to reduce the clock speed of SDIO as illustrated hereafter in the following section.
STM32 SDIO Clock Configuration & Divider
The SDIO peripheral uses the 48MHz clock just like the USB and it divides it by 2 (by default) according to the following equation.
SDIO_CK = SDIOCLK / [CLKDIV + 2]
Leaving the CLKDIV factor as 0 will result in an SDIO_CK = 48 / [0 + 2] = 24MHz. Which is the maximum operating speed for the SDIO interface.
You can slow it down by increasing the CLKDIV factor if you’re getting errors while mounting the SD card.
Required Parts For STM32 Examples
All the example Code/LABs/Projects in this STM32 Series of Tutorials are done using the Dev boards & Electronic Parts Below:
QTY. | Component Name | Amazon.com | AliExpress | eBay |
1 | SD Card SDIO Breakout Board | Amazon | AliExpress | eBay |
1 | SD Card Reader (For PC) | Amazon | AliExpress | eBay |
1 | SD Card 8GB | Amazon | AliExpress | eBay |
1 | STM32-F103 BluePill Board (ARM Cortex-M3 @ 72MHz) | Amazon | AliExpress | eBay |
1 | Nucleo-L432KC (ARM Cortex-M4 @ 80MHz) | Amazon | AliExpress | eBay |
1 | ST-Link V2 Debugger | Amazon | AliExpress | eBay |
2 | BreadBoard | Amazon | AliExpress | eBay |
1 | LEDs Kit | Amazon & Amazon | AliExpress | eBay |
1 | Resistors Kit | Amazon & Amazon | AliExpress | eBay |
1 | Capacitors Kit | Amazon & Amazon | AliExpress & AliExpress | eBay & eBay |
1 | Jumper Wires Pack | Amazon & Amazon | AliExpress & AliExpress | eBay & eBay |
1 | Push Buttons | Amazon & Amazon | AliExpress | eBay |
1 | Potentiometers | Amazon | AliExpress | eBay |
1 | Micro USB Cable | Amazon | AliExpress | eBay |
★ Check The Links Below For The Full Course Kit List & LAB Test Equipment Required For Debugging ★
Download Attachments
You can download all attachment files for this Article/Tutorial (project files, schematics, code, etc..) using the link below. Please consider supporting our work through the various support options listed in the link down below. Every small donation helps to keep this website up and running and ultimately supports the whole community.
Wrap Up
In conclusion, we’ve discussed how to interface STM32 microcontrollers with SD Card memory using the SDIO hardware interface with the FatFS firmware library. The provided example project should be a very good starting point for your next STM32 SDIO SD Card interfacing project. You can also explore the other parts of the STM32 SD Card tutorials series for more information about the other STM32 SD Card interfacing options.