Low level Memory Technology Device interface. More...
Low level Memory Technology Device interface.
Generic memory technology device interface
Unlike the Flash page driver, this is device driver based (i.e. all functions take a mtd_dev_t as a first argument), so that SPI based EEPROMs (e.g. AT25xxx) can be accessed the same way as internal flash or SD cards), all inside the same application.
MTD devices expose a block based erase and write interface. In that, they are the distinct from block devices (like hard disks) on which individual bytes can be overwritten. The Linux MTD FAQ has a convenient comparison (beware though of terminology differences outlined below). They can be erased (with some granularity, often wearing out the erased area a bit), and erased areas can be written to (sometimes multiple times).
MTD devices are described in terms of sectors, pages and feature flags:
A sector is the device's erase unit. Calls to mtd_erase need to work in alignment with this number (commonly somewhere around 1kiB).
(Note that this corresponds to the term "page" as used in the flashpage API, and the term "eraseblock" in Linux's MTD).
A page is the largest a device can write in one transfer.
Applications rarely need to deal with this; it offers no guarantees on atomicity, but writing within a page is generally faster than across page boundaries.
Pages are a subdivision of sectors.
The write size is the minimum size of writes to the device, and also the required alignment of writes.
The write size is a divider of the page. It is often between 1 to 4 bytes long, but may be up to the full page size.
Unless a flag (such as MTD_DRIVER_FLAG_DIRECT_WRITE or MTD_DRIVER_FLAG_CLEARING_OVERWRITE) allows it, this MTD API does not allow memory areas to be written to twice between erase operations. Drivers are not expected to count write accesses, and neither do this module's functions: The performance impact would be too great. It is up to the application to only write to erased memory once. Failure to do so may damage hardware.
This MTD API currently does not specify which value will be read from an erased sector.
Modules | |
MTD wrapper for emulated MTD devices | |
MTD device that is emulated in RAM for test purposes. | |
Native MTD | |
mtd flash emulation for native | |
Files | |
file | mtd.h |
Data Structures | |
struct | mtd_dev_t |
MTD device descriptor. More... | |
struct | mtd_desc |
MTD driver interface. More... | |
Macros | |
#define | MTD_XFA_ADD(dev, idx) XFA_CONST(mtd_dev_t, mtd_dev_xfa, idx) *mtd ## idx = (mtd_dev_t *)&(dev) |
Define MTD device pointer variable mtd<idx> | |
#define | MTD_NUMOF XFA_LEN(mtd_dev_t *, mtd_dev_xfa) |
Number of MTDs defined in the MTD device array in XFA. | |
#define | MTD_DRIVER_FLAG_DIRECT_WRITE (1 << 0) |
MTD driver can write any data to the storage without erasing it first. | |
#define | MTD_DRIVER_FLAG_CLEARING_OVERWRITE (1 << 1) |
MTD driver supports arbitrary clearing overwrites. | |
Typedefs | |
typedef struct mtd_desc | mtd_desc_t |
MTD driver interface. | |
Enumerations | |
enum | mtd_power_state { MTD_POWER_UP , MTD_POWER_DOWN } |
MTD power states. More... | |
Functions | |
int | mtd_init (mtd_dev_t *mtd) |
mtd_init Initialize a MTD device | |
int | mtd_read (mtd_dev_t *mtd, void *dest, uint32_t addr, uint32_t count) |
Read data from a MTD device. | |
int | mtd_read_page (mtd_dev_t *mtd, void *dest, uint32_t page, uint32_t offset, uint32_t size) |
Read data from a MTD device with pagewise addressing. | |
int | mtd_write (mtd_dev_t *mtd, const void *src, uint32_t addr, uint32_t count) |
Write data to a MTD device. | |
int | mtd_write_page_raw (mtd_dev_t *mtd, const void *src, uint32_t page, uint32_t offset, uint32_t size) |
Write data to a MTD device with pagewise addressing. | |
int | mtd_write_page (mtd_dev_t *mtd, const void *src, uint32_t page, uint32_t offset, uint32_t size) |
Write data to a MTD device with pagewise addressing. | |
int | mtd_erase (mtd_dev_t *mtd, uint32_t addr, uint32_t count) |
Erase sectors of a MTD device. | |
int | mtd_erase_sector (mtd_dev_t *mtd, uint32_t sector, uint32_t num) |
Erase sectors of a MTD device. | |
int | mtd_write_sector (mtd_dev_t *mtd, const void *src, uint32_t sector, uint32_t num) |
Write data to a MTD device with whole sector writes. | |
int | mtd_power (mtd_dev_t *mtd, enum mtd_power_state power) |
Set power mode on a MTD device. | |
static mtd_dev_t * | mtd_dev_get (unsigned idx) |
Get an MTD device by index. | |
Variables | |
mtd_dev_t *const | mtd_dev_xfa [] |
MTD device array as XFA. | |
static mtd_dev_t * | mtd_default_get_dev (unsigned idx) |
Default MTD device configuration. | |
#define MTD_DRIVER_FLAG_CLEARING_OVERWRITE (1 << 1) |
MTD driver supports arbitrary clearing overwrites.
If this is set, (arbitrarily) many writes are permitted per write size, and the result is the old value bitwise-AND the written value.
This property is common for managed flash memories. (By comparison, the raw flash often used internally by MCUs may not allow overwrites, or may allow them with the same semantics, but only for a limited number of writes between erasures; there is currently no flag describing these any further).
#define MTD_DRIVER_FLAG_DIRECT_WRITE (1 << 0) |
#define MTD_NUMOF XFA_LEN(mtd_dev_t *, mtd_dev_xfa) |
#define MTD_XFA_ADD | ( | dev, | |
idx | |||
) | XFA_CONST(mtd_dev_t, mtd_dev_xfa, idx) *mtd ## idx = (mtd_dev_t *)&(dev) |
Define MTD device pointer variable mtd<idx>
The macro defines the MTD device pointer variable mtd<idx>
, sets it to the address of the MTD device specified by the dev
parameter, and adds it to the XFA of MTD device pointers mtd_dev_xfa. For example
defines the variable mtd1
pointing to the device my_dev
.
The parameter idx
is used as priority of the MTD device pointer within the XFA. That means it determines the order of the MTD device pointers within mtd_dev_xfa.
idx
corresponds to the position of the MTD device pointer within the mtd_dev_xfa XFA and mtd_dev_xfa[i]
points to the i-th MTD device.dev | MTD device |
idx | Priority of the MTD device pointer within the XFA |
typedef struct mtd_desc mtd_desc_t |
MTD driver interface.
This define the functions to access a MTD.
A MTD is composed of pages combined into sectors. A sector is the smallest erasable unit. The number of pages in a sector must be constant for the whole MTD.
The erase operation is available only for entire sectors.
enum mtd_power_state |
|
inlinestatic |
Default MTD device configuration.
Helpers for generic MTD use.
Get the default MTD device by index
[in] | idx | Index of the MTD device |
idx
0 and so on NULL if no MTD device exists for the given index Definition at line 54 of file mtd_default.h.
|
inlinestatic |
int mtd_erase | ( | mtd_dev_t * | mtd, |
uint32_t | addr, | ||
uint32_t | count | ||
) |
Erase sectors of a MTD device.
addr
must be aligned on a sector boundary. count
must be a multiple of a sector size.
mtd | the device to erase | |
[in] | addr | the address of the first sector to erase |
[in] | count | the number of bytes to erase |
0 | if erase successful |
<0 | if an error occurred |
-ENODEV | if mtd is not a valid device |
-ENOTSUP | if operation is not supported on mtd |
-EOVERFLOW | if addr or count are not valid, i.e. outside memory |
-EIO | if I/O error occurred |
int mtd_erase_sector | ( | mtd_dev_t * | mtd, |
uint32_t | sector, | ||
uint32_t | num | ||
) |
Erase sectors of a MTD device.
mtd | the device to erase | |
[in] | sector | the first sector number to erase |
[in] | num | the number of sectors to erase |
0 | if erase successful |
<0 | if an error occurred |
-ENODEV | if mtd is not a valid device |
-ENOTSUP | if operation is not supported on mtd |
-EOVERFLOW | if addr or sector are not valid, i.e. outside memory |
-EIO | if I/O error occurred |
int mtd_init | ( | mtd_dev_t * | mtd | ) |
mtd_init Initialize a MTD device
mtd | the device to initialize |
0 | on success |
<0 | on error probably errno |
-ENODEV | if no device if given or no driver is set |
-ENOTSUP | if device has no init function |
int mtd_power | ( | mtd_dev_t * | mtd, |
enum mtd_power_state | power | ||
) |
Set power mode on a MTD device.
mtd | the device to access | |
[in] | power | the power mode to set |
0 | if power mode successfully set |
<0 | if an error occurred |
-ENODEV | if mtd is not a valid device |
-ENOTSUP | if operation or power state is not supported on mtd |
-EIO | if I/O error occurred |
int mtd_read | ( | mtd_dev_t * | mtd, |
void * | dest, | ||
uint32_t | addr, | ||
uint32_t | count | ||
) |
Read data from a MTD device.
No alignment is required on addr
and count
.
mtd | the device to read from | |
[out] | dest | the buffer to fill in |
[in] | addr | the start address to read from |
[in] | count | the number of bytes to read |
0 | on success |
<0 | if an error occurred |
-ENODEV | if mtd is not a valid device |
-ENOTSUP | if operation is not supported on mtd |
-EOVERFLOW | if addr or count are not valid, i.e. outside memory |
-EIO | if I/O error occurred |
int mtd_read_page | ( | mtd_dev_t * | mtd, |
void * | dest, | ||
uint32_t | page, | ||
uint32_t | offset, | ||
uint32_t | size | ||
) |
Read data from a MTD device with pagewise addressing.
The MTD layer will take care of splitting up the transaction into multiple reads if it is required by the underlying storage media.
mtd | the device to read from | |
[out] | dest | the buffer to fill in |
[in] | page | Page number to start reading from |
[in] | offset | offset from the start of the page (in bytes) |
[in] | size | the number of bytes to read |
0 | on success |
<0 | value on error |
-ENODEV | if mtd is not a valid device |
-ENOTSUP | if operation is not supported on mtd |
-EOVERFLOW | if addr or count are not valid, i.e. outside memory |
-EIO | if I/O error occurred |
int mtd_write | ( | mtd_dev_t * | mtd, |
const void * | src, | ||
uint32_t | addr, | ||
uint32_t | count | ||
) |
Write data to a MTD device.
addr
+ count
must be inside a page boundary. addr
can be anywhere but the buffer cannot overlap two pages.
Both parameters must be multiples of the device's write size.
mtd | the device to write to | |
[in] | src | the buffer to write |
[in] | addr | the start address to write to |
[in] | count | the number of bytes to write |
0 | on success |
<0 | if an error occurred |
-ENODEV | if mtd is not a valid device |
-ENOTSUP | if operation is not supported on mtd |
-EOVERFLOW | if addr or count are not valid, i.e. outside memory, or overlapping two pages |
-EIO | if I/O error occurred |
-EINVAL | if parameters are invalid (invalid alignment for instance) |
int mtd_write_page | ( | mtd_dev_t * | mtd, |
const void * | src, | ||
uint32_t | page, | ||
uint32_t | offset, | ||
uint32_t | size | ||
) |
Write data to a MTD device with pagewise addressing.
The MTD layer will take care of splitting up the transaction into multiple writes if it is required by the underlying storage media.
If the underlying sector needs to be erased before it can be written, the MTD layer will take care of the read-modify-write operation.
offset
must be smaller than the page size
mtd_write_page
modulemtd | the device to write to | |
[in] | src | the buffer to write |
[in] | page | Page number to start writing to |
[in] | offset | byte offset from the start of the page |
[in] | size | the number of bytes to write |
0 | on success |
<0 | value on error |
-ENODEV | if mtd is not a valid device |
-ENOTSUP | if operation is not supported on mtd |
-EOVERFLOW | if addr or count are not valid, i.e. outside memory, |
-EIO | if I/O error occurred |
-EINVAL | if parameters are invalid |
int mtd_write_page_raw | ( | mtd_dev_t * | mtd, |
const void * | src, | ||
uint32_t | page, | ||
uint32_t | offset, | ||
uint32_t | size | ||
) |
Write data to a MTD device with pagewise addressing.
The MTD layer will take care of splitting up the transaction into multiple writes if it is required by the underlying storage media.
This performs a raw write, no automatic read-modify-write cycle is performed.
Both offset
and size
must be multiples of the device's write size.
mtd | the device to write to | |
[in] | src | the buffer to write |
[in] | page | Page number to start writing to |
[in] | offset | byte offset from the start of the page |
[in] | size | the number of bytes to write |
0 | on success |
<0 | value on error |
-ENODEV | if mtd is not a valid device |
-ENOTSUP | if operation is not supported on mtd |
-EOVERFLOW | if addr or count are not valid, i.e. outside memory, |
-EIO | if I/O error occurred |
-EINVAL | if parameters are invalid |
int mtd_write_sector | ( | mtd_dev_t * | mtd, |
const void * | src, | ||
uint32_t | sector, | ||
uint32_t | num | ||
) |
Write data to a MTD device with whole sector writes.
The MTD layer will take care of splitting up the transaction into multiple writes if it is required by the underlying storage media.
The sectors will be erased before writing if needed.
mtd | Device to write to | |
[in] | src | Buffer to write |
[in] | sector | Sector number to start writing to |
[in] | num | Number of sectors to write |
0 | on success |
<0 | value on error |
-ENODEV | if mtd is not a valid device |
-ENOTSUP | if operation is not supported on mtd |
-EOVERFLOW | if addr or count are not valid, i.e. outside memory, |
-EIO | if I/O error occurred |
-EINVAL | if parameters are invalid |
mtd_dev_t* const mtd_dev_xfa[] |
MTD device array as XFA.
The array contains the addresses of all MTD devices that are defined using the MTD_XFA_ADD macro, for example:
The MTD devices in this array can be used for automatic functions such as with the mtd_default
module. The i-th device in this array can then be accessed with mtd_dev_xfa[i]
. The number of MTDs defined in this array is XFA_LEN(mtd_dev_xfa)
.