Chapter 57. The eCos configuration store
Table of Contents
The eCos configuration store is a simple typed key/value store which uses NAND flash for its persistent storage.
The library is aimed at applications that wish to store simple configuration data without the overhead of a fully NAND-aware filesystem. It is also used by RedBoot to store persistent configuration data.
The following functionality is provided:
- Write data
- Read data
- Erase individual data items
- List and dump out store keys and contents (for debugging)
57.1.1. Design limitations
- The data which may be stored is limited to a total of one NAND block, including the store's internal metadata.
- The store is designed to be robust but simple. It is not expected to scale well; if there are a great many items in the store, read access will be slow.
- The entire store is rewritten on every write; this means that write access to a busy store will similarly be slow.
- The store is NAND-aware and incorporates simple wear-levelling logic but excessive numbers of writes will still risk burning out the NAND array. If the store is allocated only a small number of NAND blocks, this will exacerbate the effect. It is recommended to allow a reasonable number of blocks (5-10) to allow for blocks wearing out over the lifetime of the device.
- Only simple locking is used to prevent corruption; all config store operations block until they are able to secure the protecting mutex.
57.2. Using the config store
The main entry points to the config store logic are as follows:
/* From <cyg/configstore/write.h>. * These functions write out a key, overwriting it if it is already there. * They return 0 for success or a negative errno value; see the header * file for details. */ externC int cyg_configstore_write_int(const char *key, cyg_uint32 i); externC int cyg_configstore_write_bool(const char *key, cyg_bool b); externC int cyg_configstore_write_bytes(const char *key, void *src, cyg_uint32 len); externC int cyg_configstore_write_string(const char *key, const char *data); /* Erases a single key */ externC int cyg_configstore_erase_keystr(const char *key);
/* From <cyg/configstore/read.h>. * These functions read out a key or header. * They return 0 for success or a negative errno value; see the header * file for details. */ externC int cyg_configstore_read_int(const char *key, cyg_uint32 *i); externC int cyg_configstore_read_bool(const char *key, cyg_bool *b); /* Note: * For bytes and strings, check *len_io after read to see the actual number * of bytes read, INCLUDING the trailing NUL. */ externC int cyg_configstore_read_bytes(const char *key, CYG_BYTE *buf, unsigned *len_io); externC int cyg_configstore_read_string(const char *key, char *buf, unsigned *len_io); /* Reading out only the header allows you to check a key's type and size. */ externC int cyg_configstore_read_header(const char *key, cyg_configstore_header_t *hdr);
/* From <cyg/configstore/util.h>. */ /* Lists all keys in the store (to diag_printf). * Not really machine-readable; intended for human-read debugging. */ externC void cyg_configstore_list(void); /* Dumps out everything in the store (to diag_printf). * Intended for human-read debugging. * NOTE: This may emit large amounts of output, which may * take an excessive length of time over a slow debug channel. */ externC void cyg_configstore_dump(void);
For more details of the types and structures used, refer to
Both store keys, and strings in the store, should not contain the ASCII NUL (0x00) character. Behaviour in this case is undefined.
The config store uses mutexes in order to prevent corruption by concurrent access.
CYGPKG_KERNEL is loaded in your eCos configuration, the
config store automatically inherits the configured mutex behaviour.
If the NAND array reports an error when writing or erasing a block, the config
store will automatically retry the operation, up to
times. The default setting is 3 retries.
The config store is allocated a single NAND partition.
The device and partition are configured by the CDL options
is set by the platform HAL;
may also be hard-wired, if RedBoot or other
boot loader needs it.
To configure partition sizes, refer to the eCos HAL documents for your platform. It is recommended to allow a reasonable number of blocks (5-10) for the config store, in order to allow for blocks wearing out over the lifetime of the device.
57.2.3. Storage details
The config store uses a single NAND block, conceptually contiguous from its component NAND pages but of course read and written a single page at a time.
The data block has the following contents:
- Block serial number. These allow us to detect old versions and automatically clean them up. Serial Number Arithmetic (RFC1982) is used to compare.
Zero or more records, each introduced by the magic number
CYG_CONFIGSTORE_MAGIC_FOOTER. This allows us to detect an incompletely-written block.
Every page written by the config store also contains magic numbers
in the out-of-band (spare) area identifying it as belonging to the store. This allows
us to attempt to be a tolerant neighbour and not erase data that appears to belong to
another (possibly misconfigured) client of the NAND array.
Each record has the following contents:
- The key. This is a null-terminated string to the user, though the null is not stored on NAND. This is stored in the same way as a string (see below).
- The record type. This is one of Integer, Boolean, String or Bytes.
- The length of the data.
- The length of the data including padding.
- The data itself.
- Any padding required (see below).
Everything written is padded to the nearest 4-octet boundary.
- Integers are always stored unsigned as 4 octets in host byte order.
- Booleans are stored as integers with 1 mapping to True and 0 to False.
- Strings and Bytes are stored as a tuple (data length, data, padding). The difference is that strings are null-terminated in RAM; the trailing null is stripped on write and restored on read.
On every access, both read and write, the config block is scanned for consistency. Any obsoleted or incompletely-written blocks are automatically erased. When writing, the old block is only erased once the new block has been completely written.
|2022-10-12||Open Publication License|