HAL Library 20- FATFS for STM32Fxxx

FATFS library (HAL LIB 20) is a “generic” library for all FAT related implementations, such as SDCARD, USB FLASH, SPI FLASH and also SDRAM can be used with proper FAT initialization.

My FATFS library currently supports only SDCARD communication with SDIO (STM32F4xx) or SDMMC (STM32F7xx) or SPI on both families. There is no big difference between them and you can treat them as the same peripheral with only different name.

In case you are interested for FATFS based on STD libraries for F4xx series, check here.


Read more about new HAL libraries


  • Interface to SDCARD using FATFS by Chan, version 0.11
    • Use SDIO for communication
    • Use SPI for communication
  • Support for CARD DETECT pin
  • Interface with USB MSC HOST
  • Interface with SDRAM (Coming)


  • HAL
  • TM
    • STM32Fxxx HAL
    • defines.h
    • FATFS
    • TM SPI when SPI is used as SDCARD interface
    • TM DELAY when SPI is used as SDCARD interface
    • TM GPIO


First a little bit about FATFS library and its configuration. I’ve reconfigure some of default settings for FATFS, which can be set in ffconf.h file for fatfs. Main changes are these:

  1. Dynamic allocation is used when new file should be created. You need at least 512 bytes of free memory in HEAP region for malloc to allocate data, otherwise, f_open function will return FR_NOT_ENOUGH_CORE result. You can force FATFS to use static buffer for all files (not thread safe) or to use stack for files, but you have to increase stack to allow that or you will have stack overflow. Settings can be changed in ffconf.f file from FATFS library.
  2. Instead of numbers for logical drivers (which will come in future with USB and other settings), I’ve configured FATFS in settings for nice logical drives name. So, instead of mount SDCARD with
    1. f_mount(&fatfs, “0:”, 1), you can do it now with
    2. f_mount(&fatfs, “SD:“, 1), which increases transparency between multiple FATFS related low level devices. Other implementations are listed below.
    3. For USB MSC: f_mount(&fatfs, “USBHS:“, 1); for USB HOST in HS mode.
    4. For USB MSC: f_mount(&fatfs, “USBFS:“, 1); for USB HOST in FS mode.
    5. For SDRAM: f_mount(&fatfs, “SDRAM:”, 1); for SDRAM implementation. This option does not work yet.
    6. Check example for more info how to use this aliases.


SDCARD pinout

SDCARD pinout

Library supports 2 modes of communication with SDCARD. First, which is faster and better is SDIO/SDMMC, or second, slower communication with SPI. You can see default pinouts in table below for SDCARD.

NR SDIO Interface SPI Interface
Name STM32Fxxx Description Name STM32Fxxx Description
4-bit 1-bit
1 CD/DAT3 PC11 Connector data line 3 CS PB5 Chip select for SPI
2 CMD PD2 PD2 Command/Response line MOSI PA7 Data input for SPI
4 VDD 3.3V 3.3V 3.3V Power supply VDD 3.3V 3.3V Power supply
5 CLK PC12 PC12 Clock SCK PA5 Clock for SPI
7 DAT0 PC8 PC8 Connector data line 0 MISO PA6 Data output for SPI
8 DAT1 PC9 Connector data line 1
9 DAT2 PC10 Connector data line 2

There is also CARD detect pin on SDCARD connector if you use it. By default, this feature is disabled in library, but can easily be enabled. In case, you want CARD DETECT pin in your project, you can open defines.h file and define your settings for CARD DETECT pin. Default CD pin is PB6 when pin is active, but can easily be changed.

SDIO/SDMMC implementation

Default SDCARD communication is SDIO/SDMMC and is automatically enabled if settings are not overwritten. For getting SDIO/SDMMC properly to work, you have to add these files in your project.

Default mode for SDIO/SDMMC is 4-bit mode, but in case you want to save some GPIO pins, you can use 1-bit also. For configuration, open defines.h file and add/edit settings you need.

SPI implementation

If you need (for come case) SPI implementation instead of SDIO (I don’t prefer SPI when SDIO can be used), you have to manually enable SPI for FATFS. To do this, open defines.h file and add following lines.

To get SPI into working state, you will have to add these files into project.


USB MSC Host is also supported with FATFS. The 2 things are there you need to know in order to use FATFS with MSC host:

  1. You need to add low_level driver, from fatfs/drivers folder, driver is fatfs_usb.c
  2. Check examples for USB MSC Host on Github to see how to use it when you have HS mode and when you have FS mode.

Note: if you won’t include low level driver file, you will not get any compile errors, because I have defined functions for low-level driver with __weak parameter. You will just always get errors from FATFS related functions.

To run USB MSC Host, you will also need my USB library with HOST stack.


Not in working state yet. Coming soon!


Not in working state yet. Coming soon!

Functions and enumerations


Example below is basic and shows how to write data to SDCARD. Example was tested with STM32F7-Discovery board and STM32F429-Discovery board and I got expected result!

In this example, default configuration is used, so:

  • SDIO/SDMMC interface
  • Interface has 4-bit mode
  • Card detect pin is disabled

Project is available on my Github account, download all libraries below.

TM STM32 Libraries

STM32 libraries based on STM32Fxxx HAL drivers.


Owner of this site. Also electronic enthusiasts, web developer, 3D printer fan, handball player and more. Big fan of STM32F4 devices. In anticipation of the new Discovery board for STM32F7 lines.

You may also like...

Read before commenting!

Before you make a new comment, make sure you agree with things listed below:

  • - Read post to make sure if it is already posted what you are asking for,
  • - Make sure you have the latest version of libraries used in your project,
  • - Make a clean and grammatically correct written message,
  • - Report as many details as possible, including what have you done so far,
  • - Do NOT post any code here. Use Pastebin,
  • - Do NOT post any error codes here. Use Pastebin,
  • - Specify STM32Fxxx family and used Discovery/EVAL/Nucleo or custom made board,
  • - Make sure your clock is set correct for PLL,
  • - If you are using my HAL drivers, please check this post how to start.
Comment will be deleted on breaking these rules without notification!
  • Pingback: Library 21- Read SD card with FatFs on STM32F4 - STM32F4 Discovery()

  • Pingback: HAL Library 21- Multi purpose USB library for STM32Fxxx - STM32F4 Discovery()

  • Pingback: All STM32 HAL libraries - STM32F4 Discovery()

  • steevke

    Hello Tilen,

    I was reading through your code as I’m struggling with the sd card implementation of STMCube.

    In your file fatfs_sd_sdio.c line 413


    should probably be

    Best regards


    • Hello steevke,

      tenks for reporting bug. You are right.

      I’ve fixed it. It will be uploaded in next release.

  • Michał Bakuła

    Hi, I have a problem… I keep getting this error:

    tm_stm32_spi.c:484: undefined reference to `HAL_SPI_Init’

    Am I missing something, some libraries? I would be thankfull for any help.


  • Ilya Mordasov

    Thank you for your libraries! I have tried to launch SD card over stdio and spi using your library, but I got some issues.

    I use stm32f4discovery with the stm32f407vg

    I tried both interfaces, stdio and spi

    file FF.c asked me to add ccsbcs.c, because it uses ff_covnert and ff_wtoupper functions, when I added it i got a new issues, that ff_convert and ff_wtoupper have multiple definitions.

    So, I removed ccsbcs.c file, had copied those functions before and Tbl variable definition.

    After that I tried to run this example and did nothing, my debugger showed me that the problem in the next line

    if (f_mount(&FS, “SD:”, 1) == FR_OK)


    printf(“Sd card was init”);




    printf(“Unable to init SD card”);


    it returns nothing, I was trying to use != instead of == and nothing again. My printfs haven’t been showed.

    So, I changed 1 on 0 and got printf(“Sd card was init”)

    if (f_mount(&FS, “SD:”, 0) == FR_OK)

    But there is a strange moment, I think it should work when I set my card into card holder, so even though I don’t have card inside the holder a’m getting the same printf…

    But the next problem is using f_open. I can’t open the file. I was using FA_CREATE_ALWAYS | FA_READ | FA_WRITE instead of previous code but it doesn’t work too…

    I was changing the file’s name which is exactly exists but no good…

    Can you explain me what’s the problem can be?

    • Each fat related function has return value so use this as rederence point to start digging.

      Did you increase heap memory as mentioned in post?

      • Ilya Mordasov

        I’m using Eclipse to work with stm32 and compile it, I have the memory file inside the project, which has the next structure:



        RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K

        CCMRAM (xrw) : ORIGIN = 0x10000000, LENGTH = 64K

        FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 1024K

        FLASHB1 (rx) : ORIGIN = 0x00000000, LENGTH = 0

        EXTMEMB0 (rx) : ORIGIN = 0x00000000, LENGTH = 0

        EXTMEMB1 (rx) : ORIGIN = 0x00000000, LENGTH = 0

        EXTMEMB2 (rx) : ORIGIN = 0x00000000, LENGTH = 0

        EXTMEMB3 (rx) : ORIGIN = 0x00000000, LENGTH = 0

        MEMORY_ARRAY (xrw) : ORIGIN = 0x20002000, LENGTH = 32


        If I understood you correctly, I need increase RAM men up to 255k, is it correct?

        • You need heap memory for malloc. Set at least 1k for start.

          • Ilya Mordasov

            Sorry for my misunderstanding, but could you explain where and how can I set mem heap? I rewatched all my code and IDE settings and didnt find something you have mentioned

    • Teodor Vasile

      Hi, have you already found the solution to your problem? I am asking because I get the same error as you:
      txs in advance for your answer!

      • Why you need ccsbcs….c file in your project? Is it mentioned in post?

        • Teodor Vasile

          it is needed by unicode.c ; should I delete it from unicode then?

          • Teodor Vasile

            Ok, but I am wanting to use the SDIO communication. I’ve removed ccsbc now. So this is what I am getting at this momment:

          • Teodor Vasile

            I made it work now without errors. I have put the declarations of “f_convert” and f_wtoupper” from ccsbc.c into ff.c and then the error dissappeared (attention: ccsbc.c does not belong to the project). As for the other error I have just commented those 2 lines out –> then it has compiled well. Now the problem is that the mounting of the card “f_mount” is not working. I’ve tried to dig in and have observed that it fails at “vol = get_ldnumber(&rp);” –> step into –> “int vol = -1;”
            Any idea?

      • Ilya Mordasov

        I couldn’t use this library, I just init everything with cubemx and fixed some bug where we use 1b instead of 4bits wide. Also I downloaded the latest version of fatfs lib.

  • Teodor Vasile

    Is there anyone who made the HAL libraries work for the SDIO communication.
    I can’t make it work. When debugging I am observing that “errorstate = SD_CMD_RSP_TIMEOUT;” at line 2698 inside of stm32f4xx_hal_sd.c. This leads to the fact that f_mount() is diffenrently than FR_OK in the main.c
    Any idea of what could be bad implemented in my code?

    • What about card wiring?

      • Teodor Vasile

        Wiring should be ok, as long as I was able to make the SD-card work with your “21 Library – Read SD card with FatFs on STM32F4”.

        • Ok, send it so I can take a look.
          On other hand, you can use my project from github and test from there.

          • Teodor Vasile

            I have sent yout the email at your gmail.com adress. I will also take a look at your project from github. txs

  • K.Wanq

    I try the given hal library code and but f_mount() executed incorrectly.

    I am using STM32F411E-DISCO board, which connect to a breakout board for microSD (Detail: http://goo.gl/L1woSK). My microSD card is 2GB.

    The SPI connection between Disco board and breakout board:
    CD — (Not used)
    DO — PA6
    GND — GND
    SCK — PA5
    VCC — 3V
    DI — PA7
    CS — PB5

    The code is built successfully.
    Is there any possible reason cause the fatfs not working?

    • Hi,

      if you just build my library, then library expects SDIO communication.
      Did you setup SPI settings as mentioned on post?

      • K.Wanq

        Yes, I did.
        I used the similar configuration as mentioned.
        #define FATFS_USE_SDIO 0

        #define FATFS_SPI SPI1
        #define FATFS_SPI_PINSPACK TM_SPI_PinsPack_1

        #define FATFS_CS_PORT GPIOB
        #define FATFS_CS_PIN GPIO_PIN_5

        #define STM32F411_DISCOVERY

        • Ok. No, it is not needed to be.

          But anyway, you are second now who said that it does not work so I have to take a deep look again. It worked before.

          • K.Wanq

            Thank you very much.
            It might also be my wiring mistake.
            I will try your “21 Library – Read SD card with FatFs on STM32F4” later, since other user can work with that.

          • mukhe

            I have a similar issue with SPI4.
            Exactly the same
            “f_mount(&FS, “SD:”, 1) return FR_OK, But fres =f_open() failed”

            Tried with multiple sd cards (4, 8,16 Samsung, Sandisk all formatted to FAT32) and different MicroSD card module.
            What was the problem again? wiring? (dont think so), and how did you solve it?

            have done according to the tutorial, turning SDIO off and adding the lines on define.h plus modifying SPI declares in the fatfs_sd.h

            modified all the “../ff.h” to just “ff.h”, compiler knows the directory

          • And I am sure, you did not read this post.

            Instead of direct answer I will give you a clue.
            Get error message from f_open and then go to fatfs and check what this problem means.

            After that, return to this post and read it.

            I’m sure I know what is a problem, just someone did not read entirely this post.

          • mukhe

            Ok I can see what you mean, got the return value 17, turns out it’s the FR_NOT_ENOUGH_CORE. The same thing you mentioned on your tutorial

            “Dynamic allocation is used when new file should be created. You need at least 512 bytes of free memory in HEAP region for malloc to allocate data, otherwise, f_open function will return FR_NOT_ENOUGH_CORE result.”

            I tried looking into this but, I don’t seem to understand how I can increase the HEAP(?) memory. My initial guess was that while formatting I needed to increase the “allocation unit size” to bigger than 512. but that doesn’t seem the case.

            This maybe annoying but would mind giving me a clue on how I can increase the HEAP memory? When I look into it, it does seem like i need to change settings on processor (stm32f429) as well. But not exactly sure what this has got to do with the SD card

          • mukhe

            Ok so I got what you mean, this post is just for people for future reference:

            Here’s the summary:
            SDIO did not work for me, strangely, but will get on that. Changed to SPI and is now working fine

            1)If f_mount return value is 0 but f_open is 17 then
            2) As mentioned on the post it’s FR_NOT_ENOUGH_CORE. Now as the post mentions, need to change the HEAP memory to atleast 512b
            3) the HEAP(?) memory turns out, is not related to SD card at all. It’s the compiler. I am using IAR Workbench and all you have to do is
            Project>Options>Linker>Config(tab)>Edit>Stack/Heap Sizes
            4) My initial value was 0x200 which is 512 but did not work. so placed 0x400 and increased the HEAP(?) by a factor of 2 to 1024
            5) Data write successful!

            thanks for clue!

          • This is really nice to hear.
            I hope you are not angry because I didnt told you directly 🙂

            If sdio did not work, wires can be a problem.

          • mukhe

            Nah no worries, like clues.

            highly unlikely because the development board is highly modular, Open429Z-D and used their own waveshare microsd breakout board. double checked the pcb traces using a multimeter and all’s good.

            It’s not important, time is not mission critical for us because we have all the time we need in space so SPI is ok. Anyways thanks a ton for the libraries! been helping us out a lot!

          • K.Wanq

            Hi, one question.
            Why we don’t need TM_SPI_Init() in this case??

          • It needs it. So maybe I missed it or delete 🙂

          • K.Wanq

            Hi, Thanks.
            But may I know in which part the TM_SPI_Init() is called?
            I couldn’t find it.

          • According to the post settings about SPI configuration, you need to add “fatfs_sd.c/h” files to project. If you open .c file you will find TM_SPI_Init function.

          • K.Wanq

            Thank you. I found it.
            But the code still not working.

          • So I didn’t believe you that code does not work.
            I tried that configration, default pinout as mentioned in post, files in project as mentioned in post with dependant libraries, FATFS_USE_SDIO set to 0 in defines.h and baam..data written on card.

            Btw..I tested 4 cards, one didn’t work, 3 did. 4th card has some problems so make sure your works perfectly.

            All cards were formatted in FAT32.

          • K.Wanq

            Now, I changed from SPI to SDIO 1-bit connection:
            CD — PC11 (f_mount failed if disconnected)
            DO — PC8
            GND — GND
            SCK — PC12
            VCC — 3V
            DI — PD2
            CS — (not used)
            f_mount(&FS, “SD:”, 1) return FR_OK, But fres =f_open() failed.

            I changed
            #defined _USE_LFN 0
            because if it is larger then 0, errors occurred.

            Could it be the reason?

          • Set settings back and increase heap to at least 1k for test.

          • K.Wanq

            Once I changed _USE_LFN –>3
            unicode.c required ccsbcs.c

            I added it but, errors occur:
            – first defined here
            – multiple definition of `ff_convert’ / ‘ff_wtoupper’

          • Funny, why I don’t need it it?
            What else you added to project which is NOT mentined here?

            Send to my email project.

          • K.Wanq

            No, I don’t think I added anything else.

            My email acc is kaewanq@hotmail.com
            I sent my project.

          • K.Wanq

            I met same issue even if i switch to standard peripheral (Library 21)

          • K.Wanq

            I test the return FRESULT of fres=f_open(); one by one.
            I get FRESULT fres == FR_INVALID_NAME;

            PS. I used the exactly same path name “SD:first_file.txt”

          • Quite logical since you disabled long file name support. Short file name you have allow you up to 12 characters (or maybe only 11) so try like that:


            And problem you have is funny. I also saw that you have renamed some include paths for fatfs, I don’t know why would you do that.

          • K.Wanq

            Thank you very much! It works now.
            Sorry for wasting your time. I should understand and study more about fatfs before asking stupid question.

            I renamed them because fatal errors: No such file or directory caused

  • Avihay

    I’m using Chan FatFS with STM32F4 HAL SDIO drivers and with HAL DMA. It works well.
    The problem is HAL_SD_WriteBlocks_DMA() must be followed by HAL_SD_CheckWriteOperation().
    Which means it waits for the DMA to finish writing the block.
    I couldn’t find a way to avoid this wait (It gets stuck).

    Did you manage to use DMA with IT without waiting right after each write ?

    • Dma is used here only for fastest output. Fatfs by chan cant work async, unless you use RTOS.

      • Avihay

        Thanks for the reply.
        Do you know why ?
        Assuming I don’t mind waiting a long period of time between different writes or i don’t mind waiting before write if previous wasn’t finished, is there no way to do so without RTOS ?
        I know that it is possible if you’re writing to SD without FS – simple remove the check.
        Is there another file system source code that can be used for that matter ?

        • Do it with FAT stack and without blocking and without rtos, probably not possible.

          After you write, you must to setsome flags for next write and so on. You cant do this async since is you sometime want to write 2 files same time it will fail.

          What is a time you can wait?

          • Avihay

            I have a device that is writing data to 1 file at a time.
            Currently constant 512Bytes every 50 ms.
            I don’t mind changing the intervals:for example 1K every 100ms.
            I’m using DMA already – just wait for it to finish after every write. each write takes ~1-2ms.
            I prefer to remove the wait.
            My attempt was to move the “Wait for finish” code block to Before the next write, instead of After each write. The result is it gets stuck somewhere inside the chan fatFS functions.

          • Im saving 50kB (multiply of 512bytes) in 25ms so I dont see a problem in writing. Writing is faster than you need.

            Write a large data pack instead. Small data pack is slow.

          • Avihay

            My general loop is 5ms. I can’t allow anything to take longer than 3-4 ms, otherwise it will hold my next iteration. After 3-5MB i save and start the next file.
            According to your measurements, 1k or 2k should take no longer than 1ms.
            I think I had different results and found it to be linear -512=1ms, 5120=10ms. i’ll check again.

            What should be expected times of closing a large file (assuming it has to sync)
            What should be the expected time of open a new file ?
            I found these 2 actions take a long time

          • Ok, if this is a problem, then use one timer (systick) and setup interrupts for it.
            Then do your job inside interrupt and handle your things.
            Each time fill new part in buffer.

            You have 2 buffers, one is currently for filling new data, second is saving to card, both for example
            uint8_t buffer[2][20 * 512]

            Writing single block (512 bytes) to card takes for example 1ms. Writing 10 blocks (10 * 512) bytes would take 3ms for example. There is no linear since writing large amount of data increases bytes per seconds throughput.

            Hope you understand now.

            Closing and opening large files I don’t know what is that time.
            Go to FATFS CHAN web and please read application manual here.


          • Avihay

            Thanks, I already use a double buffer method.
            I’ll try your suggestion of larger writes each time.

  • Jeremy

    I’m trying to get the HAL Fatfs library working using the demo code you have and I have a few issues. First off, for whatever reason, I cannot get the code to compile if I use the TM_FATFS_GetDriveSize function. It keeps saying undefined reference to that function. I have included all the files in my project, and referenced the libraries, I just cannot get it to compile. However, if I comment that out and use an arbitary number instead of CardSize.Total and CardSize.Free, the program compiles and seems to work. I can step through the whole program, it mounts the SD card, it opens the file, it writes to the file, it closes the file, it dismounts the drive. However, if I check the contents of the SD card on my PC it is still empty. No files. The drive is formatted to FAT32 with the default allocation size (4096 bytes I believe is default). Can you help me out here?

    Also, a suggestion: My SD card slot detect pin is active high. So I added to the library another define that allows the user to specify the Detect State (FATFS_DETECT_STATE) in defines.h and defaulted it to 0 in diskio.h for backwards compatibility.

    • Jeremy

      Okay, figured out why it wouldn’t compile with TM_FatFS_GetDriveSize. Once, I encompassed all the function declarations in tm_stm32_fatfs.h with the usual __cplusplus extern “C” conditional defines, it compiled without issue. Could you add this to your library for cpp programs?

      Just need to figure out the FR_DISK_ERR…

    • Hello,

      it is nice that you figure this out. I didn’t know you are using C++ for that. It is also funny that I forgot it here, since I normally add it. I have fixed this now and will upload on next release.

      Disk error means that low level driver failed. Make sure you have correct wiring. According to what you said so far, you are using SDIO? Which STM?

      • Jeremy

        I’m using the stmf407vg and SDIO with card detect as active high on insert. I forget to add the simple things sometimes. I added this in my “edit” below.
        Would it be better if I were to use github to request edits? I’m just not that github savy yet.

        • Technically, I don’t know what is happening here. You can try another card for start.

          Yes, it would be great to make a github pull requests so I can easily merge them.

          • Jeremy

            I have tried two different microsd cards. A 4gb and an 8gb. Both exhibit the same behavior.

            I’ll read up on proper operation on github to do the pull requests.

          • I have successfully read and write to card. Also, you can try my FATFS for test for standard peripheral drivers (lib 21). This works OK for sure as I use it daily.

          • Jeremy

            I originally tried the fatfs from std periph libraries and both cards worked using SPI. However, when I tried to get it to work with SDIO using the same test project (swapping in fatfs_sd_sdio in drivers and changing defines.h) it keeps failing on f_open. Digging deeper, it fails on ff_malloc on the INIT(size) line where size equals 512. Frustrating.

          • Depends on LFN settings. My lib has set in ffconf file to use heap memory as lfn buffer. So increase heap to at least 512bytes.

          • Jeremy

            Could you go into more detail on how to change the heap size? From my digging it looks like it is in the linker using the scatter (.ld) doc? I see in there min_heap_size. Even if I change that to 1024, it doesn’t change anything. I’ve tried following this (http://www.coocox.org/forum/viewtopic.php?f=2&t=917) and it doesn’t work either.

          • Im not using gcc so I dont know how to do it.
            However, you can set another config for use_lfn define in ffconf.h file. Read manual in file how to set it up.

  • Anna Leshinsky

    Hi, What does it mean if f_mount returns FR_INVALID_DRIVE ?

    • Probably something you might want to check on FATFS official page.


      • Anna Leshinsky

        I checked there already (Invalid drive number is specified in the path name. A null pointer is given as the path name. (Related option: _VOLUMES))
        🙁 and googled a lot but don`t understand the reason and where to start fix it…
        Already wired again the card….

        • Please read the error. It says you put null pointer to function f_mount instead of string. How you call f_mount?

          • Anna Leshinsky

            the code is from your example. I entered it to my project but in this part didn`t make changes….
            Very sorry if the question is stupid but I just started learning embedded programming….
            this is a code segment.
            The “if” statement is false… I checked it + returns FR_INVALID_DRIVE

            FATFS FS;
            FIL fil;
            FRESULT fres, res;

            if (f_mount(&FS, “SD:”, 1) == FR_OK) {

            /* Try to open file */

            if ((fres = f_open(&fil, “SD:first_file.txt”, FA_OPEN_ALWAYS | FA_READ | FA_WRITE)) == FR_OK) {

            /* Read SDCARD size */

            TM_FATFS_GetDriveSize(“SD:”, &CardSize);

            /* Format string */

            sprintf(buffer, “Total card size: %u kBytesn”, CardSize.Total);

            /* Write total card size to file */

            f_puts(buffer, &fil);

            /* Format string for free card size */

            sprintf(buffer, “Free card size: %u kBytesn”, CardSize.Free);

            /* Write free card size to file */

            f_puts(buffer, &fil);

            /* Close file */


            /* Turn led ON */


            /* Unmount SDCARD */

            f_mount(NULL, “SD:”, 1);



          • Anna Leshinsky

            After some deep research the f_mount function fails in function get_ldnumber() in ff.c file. the value of ‘vol’ always return -1 no matter the path name I use ….and this is the flag that the pointer is wrong. I followed the function step by step and can`t understand why its occur .
            Hope to your help

          • Did you include my library in project? What if you download project from github and run it from there?

          • Anna Leshinsky

            yes I included your libraries in project that made on Mx-cube and there is only SDIO configs and fatfs…Your project is for discovery F407 I have nucleo F401 and for my regret I can`t try it.

          • Why you cant try it?

          • Anna Leshinsky

            Maybe I have any misunderstanding . I have a nucleo board and your project is for discovery . Can I run it without making changes?

          • If you would open main.c with uvision and even check what it says, you would find out everything. Nucleo works ok

          • Anna Leshinsky

            ok. doing it now

          • Anna Leshinsky

            Thanks! I changed the card and it works!

  • Abhinav Kumar

    I had a small query that can we make a part of internal flash memory(512kb) of STM32f4 discovery board as FatFs? Will this be supported by the MCU ?

    • yes, it will be. You just have to make sure that you set proper location.
      But you should know that FATFS expects sectors of same size. STM32F4 does not have all sectors same size.

      • Abhinav Kumar

        Sector 5 to Sector 9 in STM32F407VGT6 has a uniform size of 128kb.So can we format it for FatFs and use?

        • Yes, you can use.

          • Abhinav Kumar

            can you please point at which location in the above project should i set the proper memory location from Sector 5 to Sector 9.

          • Datasheet. But remember, you need at least for one sector memory size.

          • Abhinav Kumar

            i know the sector address but where should i assign that address in the above project ,I mean which function in the above project.

            Thanks in advance

          • Nowhere. You must build another low level driver.

            But you will be out of ram for sure.

  • Abhinav Kumar

    Hi Majerle,

    The below command mounts the external SD card.
    (f_mount(&FS, “SD:”, 1); here “SD:” refers to the Logical drive number to be mounted/unmounted .
    Is it predefined for SD cards,?what Logical drive number should be given in case I mount an external NOR Flash?

    Thanks in advance.

    • I defined them. To see how you can do it yourself, check fatfs api.

  • Nebojša

    Hi Majerle,
    I found bug in tm_stm32_spi.c. In the beginning, when you define constants, you have wrong value for GPIO_AFx_SPI3. It has to be 0x06 or GPIO_AF6_SPI3.

    • Hi,

      according to datasheet and also according to other code, 0x05 should work too.
      Image below.

      But I will take a look. If I find out that it does not work with 0x05 and does with 0x06, I will change it.

      Thanks for reporting, though.

      • Nebojša

        I forgot to mention, I’m working with STM32F407. It has only 3 SPI.

  • Stefan Huisman


    I used your library using SPI, This works very well. Now I tried to switch to SDIO to improve speed. But I am having problems getting this to work.

    1-bit SDIO works fine but when I try to use 4-bit, it doesn’t work. I checked the dat1,2 and 3. They all seem to send data. I suspect a timing issue because I use wires that might be too long. Maybe I can rule this out by reducing clock speed of the SDIO. Could you tell me how I can do this?

    Kind regards,


    • Hi Stefan,

      wires can definetelly be a problem here.

      Check file “stm32f4xx_sdmmc.h”, define SDIO_TRANSFER_CLK_DIV. Now is set to 0x00, set it to 0x10 for example for start. If it works, decrease this number until it works and you will get minimum prescaler.

      • Stefan Huisman

        You are fast haha. I will try it this evening. Although it is strange that 1-bit does work. But thanks for your quick answer.

      • Stefan Huisman

        Cool, that fixed it. I reduced the clock and it al functions properly. Thank you!!

  • Bilbo


    I’m working on Eclipse and i would like to use the fatfs librairy with HAL drivers to use a SD card (with SPI) on my nulceoF401RE

    So i create a new project using HAL drivers and then i included your files

    I used your main example and modified the define.h to use SPI but i have a lots of errors while trying to compile… it also seems that there is conflict between your files tm_stm32_gpio.h for exemple) and the one i was using with the HAL drives (stm32f4xx_hal_gpio.h)

    Is there something that i missed ?

    attached there is a picture of my errors

    THANK YOU for your help,

    And sry for my english

    • Strange with includes. Something related with include paths in ide.

      • Bilbo

        Thanks for the fast answer
        i will investigate and come back to you

      • Bilbo

        @majerletilen:disqus I’ve done it again but i still have the same issue..
        Everything seems fine except the fatfs_sd.c where all my errors come from..
        I cant figure out which file i didn’t include (if its an inlcude issue)

        What do you thinks about the first error ? Which is about the select function which appears on the screen ?


  • Teodor

    Has anyone experience with PIC32 and the implementation of the SDIO 4-bit mode?

    Thank you very much in advance!

  • Hi Tilen, I was having a strange problem while trying to use f_opendir function. I was getting FR_NOT_ENABLED result. I understood it by myself. I thought there may be someone else also having same trouble and I want to show how to solve that complexity.
    fres = f_opendir(&dir, path);
    If path = “/”, then fres = FR_NOT_ENABLED.
    If path = “USBFS:”, then fres = FR_OK. (because I am using USB FS.)
    I made such a conclusion but i want to ask whether it is right or wrong. path always needs to start with “USBFS:”, “USBHS:” or “SD:”. Am I right?

    • When you used “/” as path parameter, FATFS uses disk number 0. In my library, this is the same as SD:

      USBFS is somewhere else, probably on number 1. Because disk 0 was not enabled, you got FR_NOT_ENABLED error.
      To change that, you have to swap low-level drivers in diskio.c for lookup array.
      Also, ffconf.h has to be changed for drive names.

  • frank

    Hi. For SPI, you show CS PB5 Chip select for SPI, but when I look at the STM32F429 data sheet for my STM32F429I-DISCO board, PB5 shows AF as SPI1_MOSI. I am thinking that the datasheet is wrong, because as you show, PA7 -> SPI1_MOSI, which matches on the data sheet. How do I determine that PB5 is actually SPI1_CS?

    • Not correct. This info about cs pin is when device is spi slave or hardware cs is used. Since in my example i use software spi is can be any pin I want.

      Another thing is that stm32 has pin remapping meaning you can use one peripheral on different pins. Datasheet is not wrong.

  • Stefan

    Hi, I installed the new HAL library from STM. They have a lot of changes in stm32f4xx_hal_sd. Have you a updated fatfs_sd_sdio.h/c?

  • michael

    Hi. I’ve had some problems with this project.When I compile it for STM32F7DISCOVERY no problem but when I tried for the STM32F4DISCOVERY i got “cannot open source input file stm32f7xx_hal_sd.h” https://uploads.disquscdn.com/images/778f248d5893a46768bf81dc56dfecd617e43e745f1025d68fdb02a8e1f9d61b.png

    then I changed this line for #include “stm32f4xx_hal_sd.h” and I got
    fatfs_sd_sdio.c(121): error: #20: identifier “SDMMC1” is undefined


    I don’t know what i am doing wrong.

    Thank you very much in advance!

  • Stefan

    Yes, its the same problem. The new HAL Version, specialy stm32f4xx_hal_sd.h, have some changes in Typedefs, defines and some function.
    The library fatfs_sd_sdio.h/c and stm32f4xx_hal_sd.h/c are linked. Well, the compiler don´t found the “old” standard entries.

    • I must say I don’t get what is the actual problem.

  • Stefan

    About my last comment: I have found the problem. I used the zip libraries from your homepage. This files are not up to date. With the files from Github is all okay.
    Now I have new problem.
    With yourFATFS example, I can open a file, can create a file and close. But when I try to write into a file I becomes a Disk_err. The error is created from HAL and stand for FIFO UNDERRUN.
    Do you have any idea?

  • Brian Koblenz

    I am pretty new to the cube/stm32fxx/fatfs world. I am trying to use SD card with HAL libraries on STM32F745xx. When I build, I have had a number of issues that make me think I just dont have the right libraries.

    I have references to HAL_SD_TransferStateTypedef in fatfs_sd_sdio.c, but no references to that typedef in my HAL files.

    I have HAL_SD_WideBusOperation_Config in fatfs_sd_sdio.c but HAL_SD_ConfigWideBusOperation() in my hal.

    I have HAL_SD_ReadBlocks_DMA with a BlockSize parameter, but my hal instance of that does not have the BlockSize parameter.

    I do not seem to have definitions for HAL_SD_CheckWriteOperation(), HAL_SD_CheckReadOperation(), or HAL_SD_GetStatus().

    I (sortof) worked around those problems for now, and with linking I get unresolved references from ff.o to disk_initialize(), disk_read(), disk_status(), disk_write(), etc.

    Should I be starting with a different library?

    • The best approach for beginner is to start with CubeMX and HAL or LL drivers. We (ST) provide FATFS example as part of Cube package. So you have to select your device and you can start easily. If you have discovery/nucleo/eval board, you can start even faster.

  • sameena shaikh

    Hi Tilen,
    How can i clear these errors..?

    ..0-STM32_LIBRARIESstm32fxxx_hal.h(197): error: #35: #error directive: “There is not selected STM32 family used. Check stm32fxxx_hal.h file for configuration!”
    #error “There is not selected STM32 family used. Check stm32fxxx_hal.h file for configuration!”
    ..0-STM32_LIBRARIEStm_stm32_delay.c: 0 warnings, 1 error
    compiling tm_stm32_disco.c…
    ..0-STM32_LIBRARIESstm32fxxx_hal.h(197): error: #35: #error directive: “There is not selected STM32 family used. Check stm32fxxx_hal.h file for configuration!”
    #error “There is not selected STM32 family used. Check stm32fxxx_hal.h file for configuration!”
    ..0-STM32_LIBRARIEStm_stm32_disco.c: 0 warnings, 1 error
    compiling tm_stm32_gpio.c…
    ..0-STM32_LIBRARIESstm32fxxx_hal.h(197): error: #35: #error directive: “There is not selected STM32 family used. Check stm32fxxx_hal.h file for configuration!”
    #error “There is not selected STM32 family used. Check stm32fxxx_hal.h file for configuration!”
    ..0-STM32_LIBRARIEStm_stm32_gpio.c: 0 warnings, 1 error
    compiling tm_stm32_fatfs.c…
    ..0-STM32_LIBRARIESstm32fxxx_hal.h(197): error: #35: #error directive: “There is not selected STM32 family used. Check stm32fxxx_hal.h file for configuration!”
    #error “There is not selected STM32 family used. Check stm32fxxx_hal.h file for configuration!”
    ..0-STM32_LIBRARIEStm_stm32_fatfs.c: 0 warnings, 1 error
    compiling fatfs_sd_sdio.c…
    ….newstm32fxxx_hal.h(197): error: #35: #error directive: “There is not selected STM32 family used. Check stm32fxxx_hal.h file for configuration!”
    #error “There is not selected STM32 family used. Check stm32fxxx_hal.h file for configuration!”
    ..0-STM32_LIBRARIESfatfsdriversfatfs_sd_sdio.c: 0 warnings, 1 error
    compiling fatfs_sd.c…
    ….newstm32fxxx_hal.h(197): error: #35: #error directive: “There is not selected STM32 family used. Check stm32fxxx_hal.h file for configuration!”
    #error “There is not selected STM32 family used. Check stm32fxxx_hal.h file for configuration!”
    ..0-STM32_LIBRARIESfatfsdriversfatfs_sd.c: 0 warnings, 1 error
    compiling diskio.c…
    ….newstm32fxxx_hal.h(197): error: #35: #error directive: “There is not selected STM32 family used. Check stm32fxxx_hal.h file for configuration!”
    #error “There is not selected STM32 family used. Check stm32fxxx_hal.h file for configuration!”
    ..0-STM32_LIBRARIESfatfsdiskio.c: 0 warnings, 1 error
    compiling stm32fxxx_it.c…
    ..stm32fxxx_hal.h(197): error: #35: #error directive: “There is not selected STM32 family used. Check stm32fxxx_hal.h file for configuration!”
    #error “There is not selected STM32 family used. Check stm32fxxx_hal.h file for configuration!”
    ..stm32fxxx_it.c: 0 warnings, 1 error
    compiling main.c…
    ….newstm32fxxx_hal.h(197): error: #35: #error directive: “There is not selected STM32 family used. Check stm32fxxx_hal.h file for configuration!”
    #error “There is not selected STM32 family used. Check stm32fxxx_hal.h file for configuration!”
    main.c: 0 warnings, 1 error
    compiling stm32f4xx_hal_timebase_tim_template.c…
    ..STM32F4xx_HAL_DriverSrcstm32f4xx_hal_timebase_tim_template.c(59): error: #20: identifier “TIM_HandleTypeDef” is undefined
    TIM_HandleTypeDef TimHandle;
    ..STM32F4xx_HAL_DriverSrcstm32f4xx_hal_timebase_tim_template.c(120): error: #20: identifier “TIM_COUNTERMODE_UP” is undefined
    TimHandle.Init.CounterMode = TIM_COUNTERMODE_UP;
    ..STM32F4xx_HAL_DriverSrcstm32f4xx_hal_timebase_tim_template.c(121): warning: #223-D: function “HAL_TIM_Base_Init” declared implicitly
    if(HAL_TIM_Base_Init(&TimHandle) == HAL_OK)
    ..STM32F4xx_HAL_DriverSrcstm32f4xx_hal_timebase_tim_template.c(124): warning: #223-D: function “HAL_TIM_Base_Start_IT” declared implicitly
    return HAL_TIM_Base_Start_IT(&TimHandle);
    ..STM32F4xx_HAL_DriverSrcstm32f4xx_hal_timebase_tim_template.c(124): warning: #188-D: enumerated type mixed with another type
    return HAL_TIM_Base_Start_IT(&TimHandle);
    ..STM32F4xx_HAL_DriverSrcstm32f4xx_hal_timebase_tim_template.c(139): warning: #223-D: function “__HAL_TIM_DISABLE_IT” declared implicitly
    ..STM32F4xx_HAL_DriverSrcstm32f4xx_hal_timebase_tim_template.c(139): error: #20: identifier “TIM_IT_UPDATE” is undefined
    ..STM32F4xx_HAL_DriverSrcstm32f4xx_hal_timebase_tim_template.c(150): warning: #223-D: function “__HAL_TIM_ENABLE_IT” declared implicitly
    ..STM32F4xx_HAL_DriverSrcstm32f4xx_hal_timebase_tim_template.c(150): error: #20: identifier “TIM_IT_UPDATE” is undefined
    ..STM32F4xx_HAL_DriverSrcstm32f4xx_hal_timebase_tim_template.c(161): error: #20: identifier “TIM_HandleTypeDef” is undefined
    void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
    ..STM32F4xx_HAL_DriverSrcstm32f4xx_hal_timebase_tim_template.c(172): warning: #223-D: function “HAL_TIM_IRQHandler” declared implicitly
    ..STM32F4xx_HAL_DriverSrcstm32f4xx_hal_timebase_tim_template.c: 6 warnings, 5 errors
    “.Objectssd_card_wr_rd.axf” – 14 Error(s), 6 Warning(s).
    Target not created.
    Build Time Elapsed: 00:00:07

  • sameena shaikh

    ……new0-STM32_LIBRARIESstm32fxxx_hal.h(197): error: #35: #error directive: “There is not selected STM32 family used. Check stm32fxxx_hal.h file for configuration!”
    #error “There is not selected STM32 family used. Check stm32fxxx_hal.h file for configuration!”
    ……new0-STM32_LIBRARIEStm_stm32_gpio.c: 0 warnings, 1 error

    How can i clear this error. How do i select my stm32family. I have used cubemx to generate my source code initialization