Name
CYGPKG_DEVS_DISK_MMC
— eCos Support for MMC, SD, SDHC and SDIO media Cards
Description
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 package also provides some (non-disk) basic SD I/O (SDIO) card support.
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. Similarly, the
package provides (limited) support for SDIO cards which
do NOT require the presence of
the CYGPKG_IO_DISK
infrastructure and do not
present as disk (memory) devices.
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 or SDIO cards in this driver.
Theoretically an MMC/SD memory 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
.
Card Insertion and Removal
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.
Write Protection and Security
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.
Configuration Options
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.
For memory card support 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.
For non-memory SDIO cards it is possible for the package to be used
without the disk I/O infrastructure. This is controlled by
the CYGFUN_DEVS_DISK_MMCSD_SDIO
option, which is
available when the target platform indicates that it implements the
relevant SDIO support. This allows for embedded (non-removable) SDIO
device support on platforms without incurring the cost of including
the unnecessary disk I/O code.
SPI mode operation configuration
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.
MMC/SD card bus mode operation configuration
When using an MMC/SD card bus, there a number of CDL configuration settings to be aware of within this driver.
- Number of sockets on the MMC/SD bus (
CYGINT_DEVS_DISK_MMCSD_BUS_CONNECTORS
) - 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.
- SD card support (
CYGFUN_DEVS_DISK_MMCSD_SD
) - 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.
- SDIO card support (
CYGFUN_DEVS_DISK_MMCSD_SDIO
) - This option is present to allow SDIO card support to be enabled for targets that do not require memory MMC/SD card disk support. It is enabled by default when the target platform/variant indicates the requirement, and is not normally an option the user should need to manually configure.
- Device name for the MMC/SD disk 0 device (
CYGDAT_DEVS_DISK_MMCSD_BUS_DISK0_NAME
) -
This is the name of the raw disk or SDIO device. For disks 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 ('/'). - Hardware drivers support card detection (
CYGINT_DEVS_DISK_MMCSD_BUS_CARD_DETECTION
) - 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.
- Removable MMC/SD media support (
CYGFUN_DEVS_DISK_MMCSD_BUS_REMOVABLE_MEDIA_SUPPORT
) -
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. - MMC/SD debug output (
CYGDBG_DEVS_DISK_MMCSD_BUS_DEBUG
) - 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.
Certain MMC/SD bus device drivers may provide support for multi-sector I/O.
But if you are using the FAT filesystem, it will not take advantage of this
facility unless you make a configuration change within the FAT filesystem
package (CYGPKG_FS_FAT
). You may increase the value of
the "FAT block cache block size"
(CYGNUM_FS_FAT_BLOCK_CACHE_BLOCKSIZE
) to a higher power of
two, in order to increase the number of sectors read or written in a chunk
by the filesystem. This will cause multi-sector I/O to be employed within this
driver. It has been noticed that certain models of SD cards (including some
made by brand-name manufacturers like Sandisk and Kingston) perform
disproportionately poorly if only using single block I/O; therefore we
recommend that where possible you do adjust this option to a higher value
(e.g. 16384). Note that memory usage will go up proportionately unless you
also reduce the "FAT block cache memory size"
(CYGNUM_FS_FAT_BLOCK_CACHE_MEMSIZE
), which you may wish to
do depending on your memory requirements.
Additional SPI Mode Functionality
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.
Porting to New Hardware
SPI mode
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.
Card bus mode
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.
SDIO Support
Due to the undefined nature of SDIO card features, the package (currently) provides basic initialisation and device access support. Custom drivers will be needed to support specific SDIO cards or embedded devices. A simple API is exposed to allow the underlying SD commands to be passed to the SDIO card compliant with the SD Specifications Part E1 SDIO Simplified Specification Version 3.00 document as published by the SD Card Association.
A custom driver will reference the SDIO card via an I/O handle
obtained via a call to the cyg_io_lookup()
function. This handle can be used to perform MMC/SD bus driver
“config” calls as well as perform SD operations via the
SDIO specific functions exposed by this package. Currently two SDIO
specific functions are available.
Cyg_ErrNo cyg_sdio_transaction_direct(cyg_io_handle_t handle, cyg_uint32 cmd, cyg_uint32 arg, cyg_uint32 *response);
The function above can be used to send card control commands (e.g. CMD0, CMD5, etc.) or the SDIO single register read/write CMD52 whereas the function below is an interface to the specific SDIO block data transfer CMD53 support.
Cyg_ErrNo cyg_sdio_transaction_extended(cyg_io_handle_t handle, cyg_uint32 arg, cyg_uint32 *response, cyg_bool read, cyg_uint32 block_length, cyg_uint32 block_count, cyg_uint8 *buf);
Notes | |
---|---|
|
2024-03-18 | Open Publication License |