| eCos Reference Manual | ||
|---|---|---|
| Prev | ||
This package provides a disk device driver for two commercial flash memory card standards: MultiMedia Cards (MMC), and Secure Digital (SD) cards, including the high-capacity SDHC variant. The MMC card implementation is intended to allow operation with memory cards compliant with the MultiMediaCard Standard version 2, as published by the MultiMediaCard Association. The SD implementation is intended to allow operation with cards compliant with the SD Physical Layer Specification version 2, as published by the SD Card Association.
This package evolved from an MMC-only implementation and as such the naming of certain aspects such as the CDL package name reflects that heritage. Any identifiers which reference MMC usually refer to either MMC or SD cards unless otherwise noted.
An MMC/SD card provides non-volatile storage in a small footprint (24mm * 32mm * 1.4mm), and weighing less than 2 grams. Typical card sizes are 128MB to 2GB, with an upper limit of 4GB for MMC and SDv1; and 32GB for SDHC cards in SDv2. It should be noted that these sizes are measured in millions of bytes, not 2^20. This driver provides support for 4GB MMC and SDv1 cards, although in practice, the FAT16 filesystem layout on such cards is unusual and may not be supported by a filesystem implementation using this driver. This problem should not occur with cards of size 2GB and less, or with SDHC cards.
At the hardware level there are two ways of accessing an MMC card. The first it to use a custom interface frequently known as either an an MCI (Multimedia Card Interface, although this allows supports for SD as well) or an MMC/SD bus. The second interface is via connection to an SPI bus. A card will detect the interface in use at run-time. The custom MCI interface allows for better performance but requires additional hardware. SPI peripheral support is more readily available on many existing CPUs. At this time, the SPI bus mode of interface does not support SD cards in this driver.
Theoretically an MMC/SD card can be used with any file system. In practice all cards are formatted for PC compatibility, with a partition table in the first block and a single FAT file system on the rest of the card. The SPI mode driver always checks the format of the MMC card and will only allow access to a card if it is formatted this way. The MCI card bus driver can adapt to a card with no partition table as long as it contains a FAT filesystem starting from the first block. This non-standard format can sometimes be created by Windows when reformatting a corrupted card. This ability is controlled by the CYGSEM_IO_DISK_DETECT_FAT_BOOT CDL configuration option in the generic disk device driver package CYGPKG_IO_DISK.
An MMC or SD socket allows cards to be removed and inserted at any time. It is a common feature for such sockets to contain a contact allowing the presence of cards to be detected. On some hardware that signal is routed to the processor allowing it to be sampled, usually connected as a GPIO signal or to an interrupt line (or to a GPIO interrupt if available).
In such cases, the MMC/SD bus driver layer in this package is able to be informed by the hardware MMC/SD bus driver of whether cards are present or not, and if possible, can be informed by an event callback that a card has just been inserted or removed. The SPI mode driver in this package does not yet support this feature.
If using the MMC/SD bus driver with appropriate hardware and driver support, the MMC/SD bus driver layer in this package can plug into the removeable media support offered by the generic disk driver layer (CYGPKG_IO_DISK) if the configuration option CYGFUN_DEVS_DISK_MMCSD_BUS_REMOVABLE_MEDIA_SUPPORT is enabled. This option may only be enabled if a hardware driver indicates that support is available. This facility allows for event notification when a card is inserted or removed from the socket. This information can be used directly by the application using the disk package APIs (see that package's documentation), or to allow use of, for example, the automounter support provided in the File I/O package (CYGPKG_IO_FILEIO).
If card detection by an interrupt is not possible, or if using the
SPI bus driver, then the only time the device driver will detect
removal events is when the next I/O operation happens. At that point,
the operation will fail, typically with an error code such as
ENODEV, ETIMEDOUT or
possible EIO. It is left to higher-level code
to recover from this error - the MMC/SD driver is unable to do
anything since the card has gone. In the case of the eCosPro
implementation of the FAT filesystem, it has been made robust to
such events such that it will always be able to force an unmount
using the umount_force function instead of
the standard umount function.
Without card detection by interrupt, use of the automounter is not
possible, therefore expected usage is that application code will
explicitly mount the card before attempting any
file I/O.
Irrespective of card detection abilities, it is expected that the
application will umount the card before it is
removed. Until unmounted, the system is likely to keep some disk blocks
cached, for performance reasons. If the card is removed before the
umount then it may end up with a corrupted file
system. Application design to inform users of when it is safe to remove
card media, and regular uses of the standard sync
function will reduce the risk of file system corruption.
If card detection support is available, but is only pollable, rather than being connected to an interrupt, then this has limited benefits other than to accelerate the process of determining whether a card has been removed, which otherwise necessitate attempting operations and waiting for potential timeouts. In a future revision of this driver it may become possible to use a polling thread to check periodically for whether cards have been inserted or removed.
The MMC and SD specifications allow cards to be write-protected in software. The current device driver does not yet make it possible to mark a card as write-protected, however it does respect the setting, and on mounting such a card will mark it internally as read-only. Any attempt to write to the card will fail with the error EROFS.
SD cards additionally feature a write-protect or 'lock' switch to indicate that cards must not be written to. This is not a physical protection however - instead it is expected that the lock switch position is detected by a contact in the socket, and it is for software to sample the state of that contact to determine whether the card is write-protected. Therefore the lock switch may not be respected if either the hardware or hardware driver does not support sampling the lock switch position from the socket. If sampling is supported however, the MMC/SD bus driver will respect that and mark the card internally as read-only.
SD (and to a lesser extent MMC) support other security features such as password protection and encryption. This driver does not yet support these features.
CYGPKG_DEVS_DISK_MMC is a hardware package which should get loaded automatically when you configure for a suitable eCos target platform. In this case suitable means that the hardware either:
has an MMC/SD socket connected to an SPI bus, that an SPI bus driver package exists and is also automatically loaded, and that the platform HAL provides information on how the card is connected to the SPI bus; or
has an MMC/SD socket connected to a custom MCI interface's card bus and a driver package for the MCI exists and is also automatically loaded, or exists in the HAL.
The package depends on support from the generic disk package CYGPKG_IO_DISK. That will not be loaded automatically: the presence of an MMC/SD socket on the board does not mean that the application has any need for a file system. Hence by default CYGPKG_DEVS_DISK_MMC will be inactive and will not contribute any code or data to the application's memory footprint. To activate the driver it will be necessary to add one or more packages to the configuration using ecosconfig add or the graphical configuration tool: the generic disk support CYGPKG_IO_DISK; usually a file system, CYGPKG_FS_FAT; support for the file I/O API CYGPKG_IO_FILEIO; and possibly additional support packages that may be needed by the file system, for example CYGPKG_LINUX_COMPAT for FAT. Depending on the template used to create the initial configuration some of these may be loaded already.
The package provides two main configuration options when using the SPI
mode of operation.
CYGDAT_DEVS_DISK_MMC_SPI_DISK0_NAME specifies the
name of the raw disk device, for example /dev/mmcdisk0.
Allowing for partition tables that makes /dev/mmcdisk0/1
the first argument that shoul be passed to a
mount call. If the hardware has multiple disk
devices then each one will need a unique name.
CYGIMP_DEVS_DISK_MMC_SPI_POLLED controls whether
the SPI bus will be accessed in interrupt-driven or polled mode. It
will default to interrupt-driven if the application is multi-threaded,
which is assumed to be the case if the kernel is present. If the
kernel is absent, for example in a RedBoot configuration, then the
driver will default to polled mode. With some hardware polled mode may
significantly increase disk throughput even in a multi-threaded
application, but will consume cpu cycles that could be used by other
threads.
When using an MMC/SD card bus, there a number of CDL configuration settings to be aware of within this driver.
This CDL interface indicates the number of sockets capable of being supported by the MMC/SD card bus driver. It is usually implemented by either a hardware device driver or the platform HAL. At the present time there can only be 1 socket supported. This limitation is intended to be lifted in the future.
This option is present to allow SD card support to be disabled. SD card support is considered a superset of MMC support, and therefore it is not possible to disable MMC card support. If SD cards are not to be used, this option can be disabled to reduce code and memory footprints, along with slightly faster execution.
This is the name of the raw disk device. It provides the prefix used for
the separate disk device strings which are passed to the
mount call. For example, a setting of
/dev/mmcsd0/ would allow the first partition on the
card to be accessed as /dev/mmcsd0/1, the second as
/dev/mmcsd0/2,
etc. /dev/mmcsd0/0 is a special device name used to
access the entire device (including the partition table if
present. Furthermore, the /dev/mmcsd0 device can be
used for registering disk insertion/removal events with the disk
layer. Consult the disk package documentation for details. The setting
of this configuration option must end with a slash character ('/').
This CDL interface is implemented by a hardware device driver or platform HAL to indicate that it is able to report the presence or absence of cards.
This option is used to determine whether the MMC/SD bus layer will plug into the generic disk package's removeable media support, i.e. allowing notification of insertion or removal of cards. There is no point enabling this option without hardware and driver support, so it is not possible to enable it if CYGINT_DEVS_DISK_MMCSD_BUS_CARD_DETECTION has not been implemented. Some code can be saved if this option is disabled.
Detailed debugging output is possible via the diagnostic console. By default there is no debugging output, but setting this option to 1 or 2 will provide increased verbosity of debugging output.
When using the SPI mode to access MMC cards, the disk driver package
exports a variable cyg_mmc_spi_polled. This defaults
to true or false depending on the configuration option
CYGIMP_DEVS_DISK_MMC_SPI_POLLED. If the default
mode is interrupt-driven then file I/O, including mount operations,
are only allowed when the scheduler has started and interrupts have
been enabled. Any attempts at file I/O earlier during system
initialization, for example inside a C++ static constructor, will lock
up. If it is necessary to perform file I/O at this time then the
driver can be temporarily switched to polling mode before the I/O
operation by setting cyg_mmc_spi_polled, and
clearing it again after the I/O. Alternatively the default mode can be
changed to polling by editing the configuration, and then the
main() thread can change the mode to
interrupt-driven once the scheduler has started.
Assuming that the MMC connector is hooked up to a standard SPI bus and that there is already an eCos SPI bus driver, porting the MMC disk driver package should be straightforward. Some other package, usually the platform HAL, should provide a cyg_spi_device structure cyg_spi_mmc_dev0. That structure contains the information needed by this package to interact with the MMC card via the usual SPI interface, for example how to activate the appropriate chip select. The platform HAL should also implement the CDL interface CYGINT_DEVS_DISK_MMC_SPI_CONNECTORS.
When defining cyg_spi_mmc_dev0 special care must be taken with the chip select. The MMC protocol is transaction-oriented. For example a read operation involves an initial command sent to the card, then a reply, then the actual data, and finally a checksum. The card's chip select must be kept asserted for the entire operation, and there can be no interactions with other devices on the same SPI bus during this time.
Optionally the platform HAL may define a macro
HAL_MMC_SPI_INIT which will be invoked during a
mount operation. This can take any hardware-specific actions that may
be necessary, for example manipulating GPIO pins. Usually no such
macro is needed because the hardware is set up during platform
initialization.
On some targets there may be additional hardware to detect events such as card insertion or removal, but there is no support for exploiting such hardware at present.
Only a single MMC socket is supported. Given the nature of SPI buses there is a problem if the MMC socket is hooked up via an expansion connector rather than being attached to the main board. The platform HAL would not know about the socket so would not implement the CDL interface CYGINT_DEVS_DISK_MMC_SPI_CONNECTORS, and the ecos.db target entry would not include CYGPKG_DEVS_DISK_MMC. Because this is a hardware package it cannot easily be added by hand. Instead this scenario would require some editing of the existing platform HAL and target entry.
Creating a hardware driver for accessing a card connected via a card bus requires a large amount of detailed description closely related to the specific code definitions. Therefore comprehensive descriptions of functionality has been provided in the mmcsd_bus.h header file in the include directory of this package. Drivers should include this file, although before doing so they must define the C preprocessor macro __MMCSD_DRIVER_PRIVATE in order to obtain definitions private to card bus drivers.
It is appropriate to provide a high-level overview of the porting process however. A driver package must implement the CDL interface CYGINT_DEVS_DISK_MMCSD_BUS_CONNECTORS to indicate the presence of a socket driven as a card bus. It may also implement CYGINT_DEVS_DISK_MMCSD_BUS_CARD_DETECTION if appropriate.
The driver in this package accesses the hardware driver through the
abstraction of the card bus. This is done by instantiating a bus object
using the CYG_MMCSD_BUS macro. This takes as
arguments an opaque word of private data which may be useful to
the hardware driver for identifying this bus or for any relevant
bus state, and it also takes a function callback list. The
CYG_MMCSD_BUS instantiation must exist in a
module which is always included in the program image. This is
usually performed when building the package by including it in the
libextras.a library (which is converted to extras.o in the eCos
build process and forcibly included in the program image that way).
This function callback list must be instantiated using the
CYG_MMCSD_BUS_FUNS macro. This provides
a table identifying driver functions to: initialise the bus
at system startup time; (re-)initialise the socket when
attempting to access a card in it for the first time; shutting
down a socket to conserve power; doing specialised configuration
options; preparing to select a card in a socket; sending a command
to a card; and transferring data blocks to or from a card. At this point
the byte and stream operations may be left as NULL
and are only present for potential future expansion. Details
on the purpose and arguments to these functions can be found in
mmcsd_bus.h.
If the hardware and driver is capable of reporting card
insertion/removal events, then notification of insertion or removal can
be performed by calling the
MMCSD_CARD_DETECT_EVENT() macro to register this
with the MMC/SD layer, which will perform any further processing
required. It must be called in DSR or thread context, not ISR context.