Wednesday, June 24, 2009

SD Card Interfacing with ATmega8 (FAT32 implementation) (BY C C DHARMANI)

Hi friends,
Here is my project on interfacing of SD Card (microSD). MicroSD cards are available very cheap nowadays, a great option for having a huge memory in any embedded system project. It is compatible with SPI bus, so interfacing is easy. SD card adapters are also easily available in market, so one can easily make an bread-board adapter by soldering few pins on it.

Following figures show the SD card pin-out & the bread-board adapter design by soldering 7-pins of a breakout header on the microSD adapter.


In this project, I've used 1GB microSD card from sandisk (later on tested with transcend card also) The microcontroller is AVR ATmega8 running at 8Mhz internal clock. MAX232 is used to interface the circuit with PC for monitoring the data. A 3.3v supply is used for powering the mega8, microSD and max232 (though the specified supply for max232 is 5v, it works comfortably at 3.3v).
7 pins of the microSD are used. Datasheets and many designers suggest to pull-up the data lines as well as unused pins, but it works perfectly without that also, so I've not used any pull-ups)

Schematic is shown here ( series resistors and ISP connector added):
The aim of this project was to learn interfacing of SD card and to understand the data transfer in raw format as well as in FAT32 format. I started with raw data transfer, sending some data to any block of the microSD, reading a block of it, reading and writing multiple blocks, erasing multiple blocks. All this in raw format. I used RS232 for viewing the data read by microcontroller from SD card. The uc sends the data to HyperTerminal. Similarly, to write data to card, the data was fed thru HyperTerminal, by typing some text.

Once raw data transfer achieved, I formatted the card with windowsXP (FAT32) and loaded it with some text files, directories and other files (all stored in root directory of the card). After that I wrote the FAT32 routines to read files, get file list (using HyperTerminal again), finding the total/free memory of card. All this data is sent to HyperTerminal by the uc.

Following is the HyperTerminal window showing different options:
Options 0 to 4 are low level functions dealing with raw data. If you use option 0, 1 or 3, you may have to reformat the card before using the FAT32 routines.
0: Erases selected number of blocks strating from selected block
1: Writes data to specified SD block address. Data to be entered in HyperTerminal using PC keyboard
2: Readss data of specified SD block address. Data is displayed on HyperTerminal window
3. Writes selected number of blocks strating from selected block
4. Reads selected number of blocks strating from selected block

Here, the multiple-block functions related to options 3 & 4 are disabled due to memory constraint of mega8 as those functions are not required for FAT32 testing. For enabling options 3 & 4, a macro defined in SD_routines.h (#define FAT_TESTING_ONLY) should be removed. And if you are using mega8, FAT32 library can be removed while testing these options for providing enough memory.

Options 5 to 9 are related to FAT32 . Only short file names are supported right now, 8byte name+3bytes extension. If you store a long name file in SD, it will be displayed by these routines in short name format only.
For testing these options, format the card with FAT32 file system and store some directories and text files (because text files can be read & checked thru HyperTerminal).

5: Displays list of available directories and files with size (in the root directory of the card)
6: Reads a specified file and displays the file contents on HyperTerminal
7: Create file with specified name, enetr text from HyperTerminal
8: Deletes any existing file with specified name
9: Displays total & free memory of the card (using FSinfo sector of the SD card)

Following figures show the HyperTerminal wondow when options 5 & 9 are selected:

Note: HyperTerminal is used here at 19200 baudrate, No parity, Flow Control 'none'.

This project needs very few components and can be done easily at home. Try it out!

Source code updates in Version 2.0:
- Support added for SD cards having first sector as MBR rather than the boot sector
- createFile and deleteFile functions added
- A bug fixed in reading files stord at far locations in memory also correction made to accept 8+3 char file name (by mistake, it was taking 7+3 earlier)
- FSinfo sector used for storing total free cluster count &
next free cluster number for faster file access
- Instant freeMemory display (earlier it was taking more than 30secs) using FSinfo sector. FSinfo sector is updated now whenever a file is created or deleted
- File memory size display in decimal, like windows (earlier it was in hex)
- Raw SD functions multiple block read and write, which are not required for FAT32, are disabled using FAT32_TESTING_ONLY macro for getting extra space required by createFile & deleteFile changes (you can activate it if you have more than 8k flash) Right now flash is 99.9% full
- Clock speed raised from 1Mhz to 8 MHz, new SPI speed (after SD initialization): 4MHz instead of 500K & baudrate: 19200 (for HyperTerminal) instead of 4800

Updates in Ver 2.1:
- A bug removed which stopped creating new files after 32*8 files in the root directory
- The root directory was unnecessarily getting expanded by one cluster whenever a file was created. Fixed in the new version
- Also, the fixed cluster size of 8 sectors is removed, this version will support other cluster sizes as well

Data transfer rate: 1 raw data block (512 bytes) takes 4.15ms for reading or writing (123.37 KBytes/s) at current 4 MHz SPI clock rate. If you have flash more than 8k, you can declare the SPI_receive() and SPI_transmit() functions as 'inline' functions. This will increase the transfer rate to 140 KBytes/s. These transfer rates can be further increased by using a 16MHz crystal (8 MHz SPI clock). FAT32 file reading is done at 78 to 91 KBytes/sec.

Download Source code files V2.1 (in AVR-GCC format):
(Updated on 03-Mar-2009)
Following files are compiled using winAVR (ver-20081205) inside AVRStudio, with optimizer ON (set at -0s).
1. SD_main.c
2. SD_routines.c & SD_routines.h
3. FAT32.c & FAT32.h
(Ver 2.1, added on 21 June 09)
4. SPI_routines.c & SPI_routines.h
5. UART_routines.c & UART_routines.h
6. Makefile
7. HEX file (Ver 2.1, added on 21Jun'09)


Download here the zipped source code files modified for mega32. Here it is having all the above mentioned 10 options enabled (added on 21 April 2009, modified on 21 June 2009):
Download Complete Source code files for ATmega32 (ver2.1)


Reference:
1. Microsoft's FAT32 specification document
2. SanDisk SD mnual v1.9
3. A paper on SD card application
4. FAT32 Structure info, includes MBR info
5. Chan's FAT library

4 comments:

  1. Great project - well done!
    (too bad schematics is so small - can't really see it)
    Moris

    ReplyDelete
  2. Amazing work! Thank you so much for posting this! Just one simple question though: what programmer are you using? All the simple programmer schematics are designed to drive the uC running at 5v, are you using a special or modified programmer to drive the chip running at 3.3v?

    ReplyDelete
  3. hey i would like to adapt a sd card slot to an aux cable.. how would you go about that? if you could email me at burgessisking@yahoo.com thanks for your time

    ReplyDelete
  4. Nothing exists under download complete anymore and FAT32.c has a missing bracket within the code making it pretty much useless.

    ReplyDelete