= SDCard = My experiments with SD Cards! '''For my newer experiments, see [http://mbed.org/users/simon/notebook/sdcards/]''' {{{ #!div class="infobox" '''This code requires mbed Library version 14, or greater! ''' To ensure you are using the latest version, click on the "mbed" library in your project. An "update" button will appear if there is a newer version, allowing you to bring it up to date. }}} == Introduction == SD Cards are widely used by loads of devices for storage; phones, mp3 players, pc's etc. That means they are a very cheap option for storing large amounts of non-volatile data (i.e. the data is not lost when the power is removed). They should be ideal for data logging and storing audio/images. == SD Card Basic Interface == SD and MMC cards support various protocols, but common to them all is one based on SPI. This is the one i'm experimenting with as, whilst not being the most high performance, it uses a generic SPI interface so will be more portable. SD Cards are block devices. That means you read/write data in multiples of the block size (usually 512-bytes); the interface is basically "read from block address n", "write to block address m". Note that a filesystem (e.g. FAT) is an abstraction on top of this, and the disk itself knows nothing about the filesystem. The hardware socket I'm using is a [http://www.sparkfun.com/commerce/product_info.php?products_id=544 SparkFun MicroSD Breakout Board]. Here is the wiring i'm using (you can obviously use either SPI port, and any DigitalOut): {{{ #!html


SparkFun MicroSD Breakout Board
}}} {{{ MicroSD Breakout mbed CS o-------------o 13 (DigitalOut cs) DI o-------------o 5 (SPI mosi) VCC o-------------o VOUT SCK o-------------o 7 (SPI sclk) GND o-------------o GND DO o-------------o 6 (SPI miso) CD o }}} I've just been testing on a 1GB Kingston and 1GB Transcend card, but will aim to test on different cards over time. I'd recommend sticking to 1GB cards or below however, as bigger ones will probably either a) use block sizes bigger than 512 bytes (needed to get around addressing limitations, and won't work) or b) use a High Capacity version of the standard (which I haven't implemented yet). The cards were formatted using: * Windows Vista, Right-click, Format... * Capacity: 971MB * Filesystem: FAT (Default) [FAT, FAT32, NTFS, exFAT] * Allocation size: 16 kbytes == SD Card SPI Protocol == My first experiments were based on the [http://www.standardics.nxp.com/support/documents/microcontrollers/pdf/an10406.pdf NXP MMC Card Interface Appnote] which were enough to get something working. However, I decided to re-write it from scratch to make use of the mbed Interface Libraries (neatens and simplifies the code), make it more robust and complete (the appnote code had a few bugs and often didn't work, and only implemented some of the required functionality), and also so I knew the code was "clean" (i.e. i knew it was written as per the spec and it didn't contain anyone elses code). So, what needs to be implemented? There is an mbed library that supports FAT filesystems (FATFileSystem), which abstracts a generic block device interface in to a filesystem we can use with the standard C functions fopen/fprintf and friends. We also already have libraries for SPI and DigitalOut Interfaces. Therefore, what we need to do is take the block device commands that come down to us from the filesystem, and translate them in to the SPI commands the SD card understands. The mechanism we use is to derive a new filesystem (SDFileSystem) from the generic filesystem (FATFileSystem), and implement the virtual block functions (disk_initialize(), disk_write(), disk_sectors(), ...) The SPI protocol used by the SD Cards is documented in a publicly available cut down spec, and I found it pretty easy to write the code from: * [http://www.sdcard.org/developers/tech/sdcard/pls/Simplified_Physical_Layer_Spec.pdf SD Card Interface Specification] From this we can see the basic requirements are to reset the card in to SPI mode, initialise the card, get the disk size and set the block size. Then construct and perform read and write transactions. The resulting code from this is at [source:SDCard/SDFileSystem]; I've documented all the essential parts at the top of the .cpp source file if you want to read more. == Using the Code == Here is a walkthrough on how to get it working (example writes a file to a formated SD card) * Start a new project so you pull in the mbed library Import as Library: (this is the generic filesystem library) {{{ http://mbed.co.uk/projects/libraries/svn/FATFileSystem/trunk }}} Import as Files: (this is the SD Card code) {{{ http://mbed.co.uk/projects/cookbook/svn/SDCard/SDFileSystem }}} * For details on how to use this in the compiler, see [//handbook/Importing Importing Projects and Libraries in to the Compiler] Change your code to... {{{ #!cpp #include "mbed.h" #include "SDFileSystem.h" SDFileSystem sd(p5, p6, p7, p13, "sd"); int main() { printf("Hello World!\n"); FILE *fp = fopen("/sd/foo.txt", "w"); if(fp == NULL) { error("Could not open file for write\n"); } fprintf(fp, "Hello SD Card World!"); fclose(fp); printf("Goodbye World!\n"); } }}} Insert a formatted disk, reset, and hopefully it'll write a file to the disk. Plug the disk back in to your PC to check it worked! = Knight Rider Upgrade... = Now we have a way to store big files... http://www.youtube.com/watch?v=tmfkLJY-1hc == Sectors and Clusters == Here is some terminology: * Sectors/Blocks - The disk "hardware" block size you can read/write. Although I think there are exceptions, this is commonly 512-bytes. For mbed, i'm going to suggest it is always 512-bytes (you can always emulate by joining blocks or read-modify-write) * Clusters - The "software" collection of sectors, which is the minimum allocation unit for files in FAT The FAT file system uses the following cluster sizes. These sizes the same under Microsoft Windows NT, Microsoft MS-DOS, Microsoft Windows 95 and any other operating system that supports FAT: {{{ Drive Size FAT Type Sectors Cluster (logical volume) Per Cluster Size ----------------- -------- ----------- ------- 0 MB - 15 MB 12-bit 8 4K 16 MB - 127 MB 16-bit 4 2K 128 MB - 255 MB 16-bit 8 4K 256 MB - 511 MB 16-bit 16 8K 512 MB - 1023 MB 16-bit 32 16K 1024 MB - 2048 MB 16-bit 64 32K 2048 MB - 4096 MB 16-bit 128 64K *4096 MB - 8192 MB 16-bit 256 128K NT V4.0 only *8192 MB - 16384 MB 16-bit 512 256K NT V4.0 only }}} * http://support.microsoft.com/kb/140365 == First Experiments == Here is the first working debug dump I got: [[Image(source:/SDCard/doc/HelloSDCardWorld.png)]]