Interfacing ARM controllers with Memory-Cards

arm-logo + sd-cards

by Martin THOMAS

Ok, ok. Due to numerous requests the page is here again. I had the page removed since I got too many requests for support and I simple do not have the time to answer all e-mails and sometimes simply do not have an answer. I know that parts of the codes may not work with all boards and all memory-cards, they just worked for me in a test-environment so please test carefully. (And yes, I have done FAT/SD-Card codes for other controllers but they are buried in commecial developments and I have to extract the FAT/SD parts first before they can be published. And yes, the examples below may not include the latest FAT/SD codes I use for private and commercial developments. I will try to add more information, examples and bug-fixes here when I have more time.)



General remarks on using Memory Cards with Microcontrollers

Memory-cards like SD-Cards or MMC offer a huge amount of memory and are relatively cheap. SD-Cards and MMC can be accessed in SPI-Mode so only 4 data-lines are needed to connect such cards to a microcontroller (chip-select, MOSI, MISO, SCK). To read and write data from/to the card with a "standard"-PC a filesystem is needed.

Some general remarks: If you are looking for a FAT library and you have the low-level block-interface code working check out Chan's FAT File System Module. It is a compact, portable, free and fast (C-)code. It supports FAT16 and FAT32 and starting with version R0.07 it also supports long filennames. Another library with LFN-support is libfat from DevkitPro. It's license is "BSD-style" and should not cause any problems. The code offers a lot of features (beside LFN also some caching) but it needs some more memory. I have not done much with libfat but experiments with AT91SAM7S and LPC2000 ARM7TDMI(-S) have been successful.

All FAT-codes need at least some interface-functions to access the hardware. Depending on the used controller a SD-Card can be accessed in "4-bit-bus" or "1-bit-bus" SD-Mode or in SPI-Mode (some micro-SD-cards may not offer SPI). You will need at least three functions: one that initializes the controller and card, one that reads a "block" (typ. 512 Bytes) from the card into RAM and one that writes a block from RAM to a card. Again you might find useful templates or even ready-made code in Chan's FatFs samples. Some hardware- or compiler-vendors also offer driver-code for SD-Cards or at least SPI. Also search for USB mass-storage examples, some of them interface with a memory card and offer it's contents over the USB MSD interface, you will just need the card-routines (respect the licenses). If you have to start from scratch get the SPI-interface working first (check with a scope), borrow code from Chan's example for AVR, modify the AVR-specific sections and get a combination of Chan's FatFs and your low-level code working in a simple example (print directory, read some bytes from a file already on the card, create a file). Once you have the tests done you can optimize the code, use the low-level code with another FAT-library or change/improve the interface step-by-step.

On the hardware: At least add a pull-up resistor in the controller's MISO-line/Card DO if the controller offers internal pull-up resistors you may use it instead. Make shure the supply voltage is in a the valid range, use 3.3V if in doubt. Use a regulator/converter, avoid "tricks" like "diode-chains" or "loaded voltage-dividers" - they will only cause problems. Stabilize the supply by using at least a 100nF capacitor between VCC and GND near the card-slot, a 10uF capacitor should be added to. It's also recommended to add a circuit to fully power-off the card i.e. with a P-channel FET, so the card can be reset by software if needed (MMC/SD/SDHC-cards do not offer an extra reset-line). Remind to disable pull-up resistors too when disabling the card's power since they may "parasite-power" the card. Keep the bus frequency low during the first steps (esp. during initialisation, see card's manual/datasheet). Avoid level-shifting with voltage-dividers. If you'd like to use them anyway check the signals with a scope and reduce the frequency if needed. Read Chan's article on MMS/SD-Cards esp. the remarks about releasing the DO/MISO line.

Some links that might be useful:

On this page there are currently interfaces for the Embedded Filesystem Library (EFSL) with LPC2000 and AT91SAM7S controllers and for ChaN's Fat-Filesystem-module with STM32, AT91SAM7, LPC17xx controllers using SPI and LPC23xx/24xx using MCI available.



An ARM-Interface for ChaN's Fat Filesystem Module

ChaN has published a nice code named FatFs which he describes as "a generic file system module to implement the FAT file system to small embedded systems". Please visit his page for further information. In the following sections you will find some example-applications in which ChaN's module has been used. Please not that there may be updates or bug-fixes for the FAT-code availabele from ChaN's page. As long as the interface to the low-level driver has not been changed you can apply these patches or replace the FatFs-Module with newer versions in the examples.

ChaN's FAT-Module and AT91SAM7

I have added an AT91SAM7 SPI-interface for MMC/SD/SDHC-cards with optional PDC/DMA-Support to ChaN's FatFs code and created a small demo-application based on ChaN's "monitor"-examples. The package includes:

Because of all this the package is rather huge (ca. 4.4 MBytes). Some concepts in the diskio-driver have been inspired by Andreas Schwarz's MP3/AAC-Player-code.

[Download] (timestamp 20090915, tested with an AT91SAM7S256 on Olimex SAM7-Pxxx evaluation-board, Codesourcery G++ lite 2009Q1, option to build for AT91SAM7S64 available in the makefile)

An additional information from Andy Kunz:
[...] I was using part of your at91sam_chanfat_mthomas_20090915c.zip package and found a discrepancy you might want to address. In sd_spi_at91.c Line 455:
PSPI_BASE->SPI_CSR[SPI_CSR_NUM] = AT91C_SPI_CPOL | AT91C_SPI_BITS_8;
With this code, it works fine on newer and large capacity cards. We were doing some testing with a small Canon 16M chip, and it would work for one or two sectors before dying. With all the larger (2G – 8G) chips, it worked fine. If I change the init code to
PSPI_BASE->SPI_CSR[SPI_CSR_NUM] = AT91C_SPI_NCPHA | AT91C_SPI_BITS_8;
it works fine for all cards, old and new.[...]

Version History:

ChaN's FAT-Module and NXP LPC2000 using SPI(SSP)

I have added a LPC2000 SSP-interface for MMC/SD/SDHC-cards to ChaN's FatFs code and created a small demo-application based on ChaN's "monitor"-examples. Memory-Cards are interfaced in SPI-Mode (not MCI/SD-Mode) so this code can be used on controllers like the LPC214x/LPC213x with SSP interface which is an SPI interface with a small FIFO-buffer that is available on most LPC2000 controllers. The package includes:

Some concepts in the diskio-driver have been inspired by the EFSL LPC2k hardware-interface by Mike Anton and me but nothing has been copied directly from the EFSL-code to avoid license-issues.

[Download] (timestamp 20100704, tested with a LPC2148 on Olimex LPC-P2148 evaluation-board, Codesourcery G++ lite)

Version History:

ChaN's FAT-Module and LPC23xx/24xx MCI

preliminary

18. Apr. 2009: Please note that ChaN now provides his own implementation of a MCI-driver for LPC2k. Please download the "Sample projects"-package from his page.

A preliminary version of a MCI-Interface (SD/MMC hardware on "newer" and "larger" NXP LPC2000 like LPC2368 and LPC2378) is also available here. This code uses the MCI driver from the NXP example collection (available for nxp.com) and ChaN's FatFs-module. I made some modifications and extensions in the MCI-code and adapted Chan's "standard" example to LPC23xx/24xx. The archive includes three configurations:

[Download] (timestamp 20090823, tested with LPC2378 on Olimex/IAR LPC-2378-STK, see readme.txt for futher information).

Version History:

ChaN's FAT-Module with STM32 SPI

This is a small demo-application to show how Chan's Fat-Module can be used to interface MMC/SD/SDHC-Cards with a STM32 microcontroller (ARM Ltd. Cortex-M3 core).

This code uses the SPI-Interface, not the SDIO host interface since the evaluation board here has the card-slot connected to SPI1 and the controller on it (STM32F103VB) does not offer SDIO. When using a STM32 with SDIO and a board which has a card-slot connected to the SDIO the example code from the STM fwlib can be used as low-level driver ("diskio"). Since ChaN's FAT module is used long filenames are supported. Please note that you may have to buy a license from Microsoft when using LFN in commercial devices. LFN support can be disabled by a "define". Use of DMA for SPI can also be enabled by a define.

Beside of the diskio-Drivers for STM32 SPI you may find some useful code when developing firmware with the GNU toolchain in this package (for example: vectors-location, startup, linker-script, OpenOCD flash-programming, debugging with Eclipse/gdb).

An Eclipse-Workpace with OpenOCD configuration, a Makefile for stand-alone building/Eclipse and a Keil/ARM uVision workspace are included. The code is only prepared for a GNU arm cross-toolchain. uVision can be used as IDE but RealView Tools are currently not supported/tested. The code should be easily portable to other toolchains. Tests have been done with Codesourcery's G++ lite for ARM "bare-metal" (arm-none-eabi). Test-Hardware: Manley EK-STM32F with STM32F103VB Rev.Z. Examples for flash-programming using OpenOCD are included too ("make program").

The package includes the complete source code for the demo-application, Chan's Fat module (with Unicode tables), the ST Microelectronics standard peripheral library for STM32 and a OpenOCD Win32 binary (only for tests). Because of this the package is rather huge (ca. 2.7MB).

[Download] (timestamp 20100704b, please refer to readme.txt included in the package for further information)

11. Oct. 2011: Make sure the GPIO-clock of the port with the MOSI, MISO and SCK-Pins connected to the memory card is enabled. In my example this is done in main.c/Periph_Configuration(), a better approach would be to enabled the peripheral clock in sd_spi_stm32.c/poweron() maybe after testing if is not already enabled. (Remark triggered by an e-mail from Wolfgang Abends - thanks for the freedback.)

Version History:

ChaN's FAT-Module with LPC17xx SPI/SSP and USB-MSD

This is a small demo-application to show how ChaN's FatFs-Module can be used to interface MMC/SD/SDHC-Cards and USB mass-storage devices with NXP's LPC17xx microcontrollers (ARM Ltd. Cortex-M3 core) to read and write files on FAT-formated drives (FAT16, FAT32).

Beside of the diskio-drivers for LPC SSP and LPC USB host you may find some useful code when developing firmware with the GNU toolchain in this package. Eclipse-Workpace with OpenOCD configuration, a Makefile for stand-alone building/Eclipse and a Keil/ARM uVision workspace are included. Examples for flash-programming using OpenOCD are included too ("make program"). The code is only prepared for a GNU cross-toolchain. ARM/Keil µVision can be used as IDE but RealView Compiler/Tools are not supported. The code should be easily portable to other toolchains.

Tests have been done with Codesourcery's G++ lite for ARM "bare-metal" (arm-none-eabi). Test-Hardware: Olimex LPC1766-STK with NXP LPC1766 Rev '-', Amontec JTAGkey2, OpenOCD0.5.0-pre/GIT

The package includes the complete source code for the demo-application, ChaN's FatFs module, the NXP driver library and the NXP/OnChip USB-Host 'lite' for LPC17xx.

[Download] (timestamp 20100715, please refer to readme.txt included in the package for further information)

A bug in the current version has been noticed by Martin Maurer - thanks for the information. For now just the 'patch', it will be corrected in the next release:

/* file spi_sd_lpc17xx, function static void spi_init(void): */
/* drain SPI RX FIFO */
while( LPC_SSP1->SR & SSP_SR_RNE ) {
    volatile uint32_t dummy = LPC_SSP1->DR; // replaced LPC_SSP0 with LPC_SSP1
    (void)dummy;
}

Version History:

Using the Embedded Filesystem Library (EFSL) with ARM-Controllers

I have added interfaces for NPX/Philips LPC2000 ARM7TDMI-S and Atmel AT91SAM7S ARM7TDMI controllers to the Embedded Filesystem Library created by Lennart Yseboodt and Michael De Nil (see sourceforge.net/projects/efsl/). This library support FAT-filesystems so data written with a PC to the card can be read from the mircocontroller firmware and the data written by the microcontroller can be postprocessed with a PC.

The LPC2000-interface supports the SPI-interface and the SSP-interface (only available on newer controllers of the NXP/Philips ARM7-family). It has been tested with LPC2138 (Keil eval-board) and LPC2148. The AT91SAM7-interface currently just supports SPI without "DMA" (PDC). It has been tested with an AT91SAM7S64 and AT91SAM7S256 (ATMEL eval-board, OX SAM7-P board). Both interfaces have been submitted to the EFSL-maintainers. The LPC2000-interface is already available in the offical distribution. The AT91SAM7-interface has not been merged into the official code-base so far (see the EFSL-Hompage and Sourceforge-pages for updated information).

Software

The source-archive includes the full EFSL source-code (based on Version 0.2.x) and the LPC2000 and AT91SAM7 interfaces. I have also added example-applications for the LPC2138 (also tested with LPC2148) and AT91SAM7S64 (see examples-directory). Other controllers of the same family (i.e. LPC2129, LPC2106, AT91SAM7S256) should work too after minimal changes. The library can be used as "real" library (efsl.a) or as "source-modules". The examples demonstrate both methods. Please read the readme_arm7.txt in the docs-subdirectory for further information on my "ARM-interfaces". Detailed information about the EFSL-API can be found in the manual (pdf-file in archive).

The code is prepared to be compiled with an arm-elf-gcc compiler and the newlib as "libc" (as in my WinARM or in gnuarm). Makefiles and linker-scripts for WinARM are included.

The license has recently been changed from LGPL to the the ecos-license (see the EFSL mailing-list-archive on sourceforge). So it is possible to use the code in "closed-source"-projects, but all modifications and extensions in the efsl-library-code have to be published as source-code (best method: submit patches and extensions to the efsl-developers).

Download source-archive [here]
(Timestamp 20060910, Based on efsl Ver. 0.2.8 with some additinal patches from sf.net not included in the official sources, zip-File ca. 650kBytes, with examples for LPC2138/LPC2148 and AT91SAM7S64/AT91SAM7S256, efsl documentation included).

Version History: Older versions and test-versions:

Links


To my ARM-Projects page (WinARM, other ARM projects)

To my Atmel AVR-Projects page


Martin Thomas
mail-adress: mthomas /at/ rhrk /dot/ uni-kl /dot/ de



Last mod.: