Great news – we have decided to open source this project! It can be downloaded for free from GitHub – please follow this link.

Previous customers may continue to use the project under the embedded-code.com licence they purchased under, or apply the new MIT licence we have now released the project under.

MMC (MultiMediaCard) and SD (Secure Digital) memory cards provide a very convenient and inexpensive means of storing large quantities of data on a removable card. However providing a FAT16 / FAT 32 driver for a MMC or SD card, so that the files on the card may also be written and read by a PC is a daunting and complex task.

This MMC / SD card driver provides standard C library fopen() etc functions for FAT16 and FAT32 formatted cards, allowing you to add a MMC / SD card interface to your project with ease.

 

The driver provides the following main features:-

  • Designed for both FAT16 and FAT32 formatted SD, SDHC (high capacity), MMC and MMCplus (high capacity) cards.
  • Uses the licence free SPI bus interface for both MMC and SD cards allowing either type to be used with the same driver (the more complex 4 bit interface requires licence payments). Also fully compatible with the miniaturised versions of MMC and SD cards for space critical applications.
  • Optimised for embedded designs. Only a single 512 data buffer is required for all operations. (It is not possible to write to MMC or SD cards without a 512 byte buffer as sectors have to be read to local memory, modified and written back as a whole).
  • Intelligent use of the local ram sector buffer. Read and writes of sector data only occur when necessary, avoiding unnecessary and slow repeated read or write operations to the card.
  • Optimised file delete function for fast deleting of large files. Instead of altering each FAT table entry one at a time, a complete sector of FAT table entries are altered in one operation before writing back to the card, resulting in a large speed improvement.
  • Provides the following standard ANSI-C functions:- fopen, fseek, ftell, fgetpos, fsetpos, ffs_rewind, fputc, putc, fgetc, getc, fputs, fgets, fwrite, fread, fflush, fclose, remove, rename, clearer, feof and ferror
  • Standard DOS ‘*’ and ‘?’ wildcard characters may be used in file operations.
  • Multiple files may be opened, accessed and written at the same time.
  • Optional real time clock support for applications that include time keeping. File creation, last modified and last accessed time and date values are automatically stored.
  • Detailed project technical manual with a wealth of information on the FAT filing system and the structure of a FAT disk / memory card.
  • No reliance on compiler specific libraries.
  • Full source code supplied for you to use and modify as required.

Don't think you need FAT32?

You may think that you don’t need anything more than FAT16 for your application if you don’t plan to store more than 2GB of data on a MMC or SD card. After all, many embedded applications only need to store relatively small amounts of data. However MMC and SD cards with capacities greater than 256MB are typically supplied pre-formatted with FAT32. Also Windows will typically format a MMC or SD card with a capacity greater than 32MB as FAT32 by default. This is because FAT32 uses larger volumes more efficiently than FAT16 and is also less susceptible to a single point of failure due to the use of a backup copy of critical data structures in the boot record. Therefore if you use a driver that only supports FAT16 for your application your users will need to find a PC with a MMC or SD card adaptor to re-format larger capacity cards to be FAT16 before they can be used with your device. You also run the risk of increased technical support demands from users who haven’t read your instructions or don't understand how to format a card as FAT16 instead of the default FAT32 and can’t work out why their new MMC or SD card won’t work in your device. Using a driver that supports FAT16 and FAT32 doesn't result in a large amount of additional code space by today’s standards, as the two systems are very similar, and it makes life a lot easier for you and your users.

[product_section_start:product_page_section_specifications.png]

Hardware Specifications

The driver is designed to support the licence free SPI bus MMC / SD memory card interface.

For full specifications please see the project technical manual.

 

     
 
This source code product is written in C and has been designed to be used with any ANSI compliant C compiler on any platform. Direct compatibility has been tested with the compilers and processors / microcontrollers listed below. Using the driver with other ANSI compliant C compilers and devices should not present significant problems.
     
 
Tested with the Rowley Associates CrossWorks for ARM C Compiler, with sample project for the NXP LPC23xx family of 32 bit ARM microcontrollers included.
     
 
Tested with the Microchip C18 MPLAB C Compiler for PIC18 family of 8 bit microcontrollers with sample project included. Free version of the compiler available from Microchip.
     
 
Tested with the Microchip C30 MPLAB C Compiler for PIC24 family of 16 bit microcontrollers and dsPIC digital signal controllers with sample project included. Free version of the compiler available from Microchip.
     
 
Tested with the Microchip C32 MPLAB C Compiler for PIC32 family of 32 bit microcontrollers. Free version of the compiler available from Microchip.

 

A version of this driver designed for CompactFlash memory cards is also available – click here.

 

USEFUL?
We benefit hugely from resources on the web so we decided we should try and give back some of our knowledge and resources to the community by opening up many of our company’s internal notes and libraries through mini sites like this. We hope you find the site helpful.
Please feel free to comment if you can add help to this page or point out issues and solutions you have found, but please note that we do not provide support on this site. If you need help with a problem please use one of the many online forums.

Comments

  1. Ambuj Maurya

    6 years ago

    is the lpc2365 header files can be directly run on LPC2148 or i have to chnge it..??

  2. Mike

    5 years ago

    Nice code set. Thanks for making it available.

    However I needed to make two changes (other than those needed to adapt to specific hardware) to make it work properly

    Note I was using the PIC18F / C18 version. I don’t know if any of the following applies to other versions.

    1) The SD cards I was using did not have a Master Boot Record out of the box. I was able to use Windows 7 utility “diskpart” to reformat the cards and create a MBR but that was awkward. The sector at address “0” was actually a partition boot sector. It contains the info needed (but at different offsets). In ffs_process (near the comment “READ THE MASTER BOOT RECORD” I

    * looked for the string “32” at offset 85 (0x55) to detect a partition boot sector. The full string in that area is “FAT32”. If found I

    * set main_partition_start_sector = 0
    * set ffs_no_partition_sectors = data starting at offset 32 (0x20).

    One can ignore initializing head (it is not used). Note also ffs_no_partition_sectors is also not used but exposed to the user if they want it.

    2) The SD cards I used seemed to not actually commit the last sector write to the internal flash until another sector I/O was done. For me … if I wrote a simple file text file of just a few bytes, did a ffs_fclose, then removed the card I found the directory was not actually updated and I had a file that was 0 bytes long. I fixed this by modifying ffs_flush by adding the code

    ffs_buffer_contains_lba = 0; // Force actual read
    ffs_read_sector_to_buffer(file_pointer->directory_entry_sector);

    right after the code

    ffs_write_sector_from_buffer(file_pointer->directory_entry_sector);

    There may be a better way but this works for now. I will look for a more efficient solution later.

    Also — the function ffs_write_sector_from_buffer looks suspicious. There is a loop at the top

    while((write_successful == 0) && (ffs_10ms_timer))

    However, looking at the code it appears if there is ever an error one executes

    goto ffs_write_sector_from_buffer_exit

    so a retry is never attempted. I replaced the goto with

    goto try_again

    and put the try_again label at the bottom of the while loop. At that point I tested write_successful. If it == 0 I did

    FFS_CE(1),
    delay for 100mS

    I suspect 100 mS way too long — but this should never happen! Now the while loop conditions will cause the loop to be exited instead of the goto.

  3. Mike

    5 years ago

    I am concerned that the code at github is NOT the latest. Looking at the code’s revision history I see that the problem I discussed before of the last sector write not being committed to the card’s internal flash was addressed in version 1.10 (ENSURE CARD HAS COMPLETED LAST WRITE PROCESS) by modifying fflush — but the code at github does not contain this change. The ENSURE CARD HAS COMPLETED LAST WRITE PROCESS is still in the close function. This makes me worry the code at GitHub is actually something older than v1.10 and not v1.12 as stated.

    I will need to go through all of the changes described in the revision history and compare with the code downloaded and try to apply them myself.

    Can anyone comment on this? Is there another download site for v1.12?

  4. Adam

    5 years ago

    Hi Mike the code on github is the latest and has been used by us without issue on various projects in the past. I’m sorry but I don’t have time currently to look into the issues you’ve mentioned but will make a note to try look should we update it in the future or you can obviously create your own fork if you wish. Cheers Adam

Comments

Your email address will not be published.