EIR Memory Card Support
Hardware
As explained on this page, the MMC socket is not connected to the hardware SPI. The following table shows the signals and pins:
GPIO | Periph. A | Periph. B | MMC Pin | SD-Card Mode | SDIO Mode | SPI Mode | EIR Conn. |
---|---|---|---|---|---|---|---|
PA15 | TF | A15 | 1 | Unused | CD/DAT3 | CS | K1-16 |
PA16 | TK | A16/BA0 | 5 | CLK | CLK | SCK | K1-17 |
PA17 | TD | A17/BA1 | 2 | CMD | CMD | MOSI | K1-18 |
PA18 | RD | NBS3/CFIOW | 7 | DATA | DAT0 | MISO | K1-19 |
PA19 | RK | NCS4/CFCS0 | 8 | IRQ | DAT1 | Unused | K1-20 |
PA20 | RF | NCS2/CFCS1 | 9 | RW | DAT2 | Unused | K1-21 |
Two additional GPIO pins are connected to the card detection and write protect switches of the memory card socket:
GPIO | Periph. A | Periph. B | Card Socket | EIR Conn. |
---|---|---|---|---|
PC18 | A20 | NANDWE | Card detect | K3-19 |
PC19 | A21/NANDALE | Write protect | K3-20 |
SPI Bit Banging Driver
This driver is available since Nut/OS 4.8 in the following source code files:
nut/dev/sbi_mmc.c | Low level memory card routines with SPI read and write functions as well as card and write protect detection. They are used by the block driver routines in nut/dev/mmcard.c. |
nut/dev/sbi0mmc0.c | Settings for "MMC0" (devSbi0MmCard0), which drives first card socket connected to the first SPI. The actual code is generated by including the source from nut/dev/sbi_mmc.c. |
nut/dev/sbi0mmc1.c | Settings for "MMC1" (devSbi0MmCard1), which drives second card socket connected to the first SPI. The actual code is generated by including the source from nut/dev/sbi_mmc.c. |
nut/dev/sbi1mmc0.c | Settings for "MMC2" (devSbi1MmCard0), which drives first card socket connected to a secondary SPI. The actual code is generated by including the source from nut/dev/sbi_mmc.c. |
nut/dev/sbi1mmc1.c | Settings for "MMC3" (devSbi1MmCard1), which drives second card socket connected to a secondary SPI. The actual code is generated by including the source from nut/dev/sbi_mmc.c. |
nut/include/dev/sbi_mmc.h | Header file, which needs to be included by the application, either directly or via dev/board.h. |
This portable driver can be configured with the Nut/OS Configurator. Typically this is done when loading the EIR configuration file eir10c.conf.
As expected, the performance of the bit banging driver is lousy. The following figures had been attained from a no-name micro-SD card.
Writing 64 byte blocks for 10s...9 kBytes/s Writing 128 byte blocks for 10s...9 kBytes/s Writing 256 byte blocks for 10s...10 kBytes/s Writing 512 byte blocks for 10s...16 kBytes/s Reading 64 byte blocks...24 kBytes/s Reading 128 byte blocks...24 kBytes/s Reading 256 byte blocks...28 kBytes/s Reading 512 byte blocks...28 kBytes/s
SPI Bus Based Driver
In opposite to the bit banging driver explained above, the newer SPI bus based drivers allow to concurrently access several devices on the same SPI bus. Actually this had been possibly with the old driver model as well, but the application needs to take care that accesses do not overlap. In the new driver model, the bus controller driver is separated from the device driver and serializes their access.
The required drivers for the EIR are available since Nut/OS 5.0 in the following source code files:
nut/arch/arm/dev/atmel/spibus_at91ssc.c | General SPI over SSC bus controller routines. |
nut/arch/arm/dev/atmel/spibus0at91ssc.c | SPI over SSC bus controller routines, that are specific for the first bus. |
nut/include/dev/spibus_ssc.h | Header file, which needs to be included by the application, either directly or via dev/board.h. |
nut/dev/spi_mmc.c | General memory card routines, which based on an SPI bus driver. |
nut/dev/spi_mmc_gpio.c | Memory card support routines, mainly GPIO functions for hardware initialization, card detect and write protect. It also includes the device structure, which makes use of nut/dev/spi_mmc.c to implement the driver. |
nut/include/dev/spi_mmc_gpio.h | Header file, which needs to be included by the application, either directly or via dev/board.h. |
No special configuration required for the bus controller driver, because it has been specifically designed for the AT91SAM7SE CPU that is mounted on the EIR board. All memory card specific configuration items are either included in the eir10c.conf file or used with default values. However, earlier versions of the configuration file do not include the settings for the card detect and write protect switches. You may add them manually.
The performance gain compared to the bit banging driver is quite impressive. The following figures had been attained from the same micro-SD card as above.
Writing 64 byte blocks for 10s...28 kBytes/s Writing 128 byte blocks for 10s...26 kBytes/s Writing 256 byte blocks for 10s...30 kBytes/s Writing 512 byte blocks for 10s...37 kBytes/s Writing 1024 byte blocks for 10s...256 kBytes/s Writing 2048 byte blocks for 10s...359 kBytes/s Writing 4096 byte blocks for 10s...436 kBytes/s Reading 64 byte blocks...114 kBytes/s Reading 128 byte blocks...161 kBytes/s Reading 256 byte blocks...198 kBytes/s Reading 512 byte blocks...229 kBytes/s Reading 1024 byte blocks...242 kBytes/s Reading 2048 byte blocks...242 kBytes/s Reading 4096 byte blocks...242 kBytes/s
Application Code
An application that wants to use an MMC driver, must register it first. For the bit banging driver this is done by simply calling
#include <dev/sbi_mmc.h> NutRegisterDevice(&devSbi0MmCard0, 0, 0);
When using the new SSC based driver, the registration requires a different call and different header files to attach the MMC driver to the SPI bus:
#include <dev/spibus_ssc.h> #include <dev/spi_mmc_gpio.h> NutRegisterSpiDevice(&devSpiMmcGpio, &spiBus0Ssc, 0);
All these registration functions initialize the hardware and return 0 on success or -1 in case of an error. The following part is identical for all MMC drivers.
Typically, applications will use the FAT file system to access the data on the card. In fact, Nut/OS currently doesn't support any other. The Nut/OS PHAT filesystem driver supports FAT12, FAT16 and FAT32 including long filename support. Also this driver needs to be registered:
NutRegisterDevice(&devPhat0, 0, 0);
Now the application is ready to mount the file system on the memory card by using a C standard function:
#include <io.h> #include <fcntl.h> int volid; volid = _open("MMC0:1/PHAT0", _O_RDWR | _O_BINARY);
The path is composed of following parts: Name of the memory card driver, followed by a colon, followed by the number of the partition, followed by a slash and finally followed by the name of the file system driver.
The function returns a file handle (volume identifier) or -1 if the mounting failed. Depending on the format of the memory card, this call may take several seconds, or even a few minutes with the bit banging driver.
When successfully mounted, the application code can use all supported C standard functions to create, delete, read or write files.
Before removing the card or switching off the power supply, the application should close all open files and unmount the file system with
_close(volid);
This is mandatory, if data had been written. Otherwise the file system may become corrupted. There is currently no support in Nut/OS to repair corrupted FAT filesystems.
Known Problems
While MultiMedia and SD-Cards seem to work, I'm not able to mount SDHC cards.
Support for SDHC cards had been added since Nut/OS 5.0.5.
When trying to mount cards formatted with FAT12 or FAT16, the related open call never returns.
This bug has been fixed in Nut/OS 5.0.5.
The bit banging driver works on the EIR board, but the SPI/SSC bus controller doesn't.
When using the bus controller driver, it is required to short pins 17 and 20 at port A connector K1, as explained on this page.
The bit banging driver fails to read blocks larger than 512 bytes.
There is currently no fix available.
Return to the EIR project page.