CYGPKG_FLASHSAFE -- provide safe storage for data in flash memory
Description
The Flash Safe package provides a robust and simple mechanism for
storing data in flash memory. It is intended for relatively small
quantities of data such as configuration and customization
data. For larger amounts of data, the JFFS2 flash filesystem
is available.
The Flash Safe operates by dividing a region of the flash into a
number of equal sized blocks. Each block is given a sequence
number and is checksummed. A header containing these is stored at
the start and end of each block. At startup the Flash Safe
searches the available blocks for one with the latest sequence
number and a valid checksum. The application can now retrieve data
stored in the Flash Safe against a numeric key.
To store new data, the application opens a block, which will cause
the block with the oldest sequence number to be erased and
prepared for writing. Data can now be written to the block with a
numeric key identifying each write. When all the data has been
written, the block is committed, which will cause the headers to
be written with valid checksums. This block now becomes the source
of all subsequent data retrieval, freeing the original valid block
for reuse.
This approach provides a simple transactional mechanism for
storing data across power failures and crashes. At any time at
least one committed block is valid and is released only after a
new valid block has been committed to replace it. Any interruption
during the creation of a new block will leave it invalid and data
retrieval will fall back to the last committed block. The use of
keys to identify data makes retrieval independent of the order in
which the items are stored, of any change in size of the data and
of any alignment requirements of the underlying flash device and
driver.
The Flash Safe needs a minimum of two blocks to be defined, which
must each be a multiple of the block size of the underlying flash
device. A single Flash Safe block per flash device block would be
the normal approach. More Flash Safe blocks may be used to
implement a crude wear levelling mechanism, since under normal
circumstances the Flash Safe will use the blocks in a round-robin
manner.
Configuration
The flashsafe is mostly configured at runtime. The following CDL
configuration options are present:
CYGNUM_FLASHSAFE_BUFFER_SIZE
This option defines the size of the buffer that the flashsafe
uses to store data prior to writing it to disk. Different flash
devices have different alignment and minimum sizes for writes
to the flash. This buffer collects data items into segments that
can be written in single operations.
CYGPKG_FLASHSAFE_TESTS
This lists the set of test programs. At present there is only
one test, which runs on the synthetic target.
Interaction with RedBoot
The Flash Safe is mainly targetted at small systems where a FIS
directory or JFFS2 would not be appropriate. Consequently it does
not try to look up a named entry in the FIS or work via the flash
IO device. Instead it uses raw flash block addresses. The
flashsafe parameters can be set up at runtime by the application
querying the RedBoot FIS interface, and the flash subsystem. The
following code extract demonstrates how this might be done.
cyg_flashsafe flashsafe;
cyg_flash_info_t flashinfo;
cyg_uint32 size;
int err;
// Initialize flash system
err = cyg_flash_init(diag_printf);
if( err != CYG_FLASH_ERR_OK ) ...
// Fetch flashsafe region base and size from FIS directory.
err = CYGACC_CALL_IF_FLASH_FIS_OP(CYGNUM_CALL_IF_FLASH_FIS_GET_FLASH_BASE, "flashsafe", &flashsafe.base);
if( err == 0 ) ...
err = CYGACC_CALL_IF_FLASH_FIS_OP(CYGNUM_CALL_IF_FLASH_FIS_GET_SIZE, "flashsafe", &size);
if( err == 0 ) ...
// Fetch flash device info from flash system
err = cyg_flash_get_info_addr( flashsafe.base, &flashinfo );
if( err != CYG_FLASH_ERR_OK ) ...
// Calculate block number and size.
flashsafe.block_size = flashinfo.block_info[0].block_size;
flashsafe.block_count = size/flashsafe.block_size;
err = cyg_flashsafe_init( &flashsafe );
if(err != CYG_FLASHSAFE_ERR_OK) ...