nRF5 SDK v15.3.0
Functionality

The Flash Data Storage API exposes functions to manipulate files and records. Files consist of one or more records, which contain the actual data.

Every record is identified by a key and assigned to a file through the file ID. Files are basically groups of records. Neither record keys nor file IDs must be unique, and files can contain several records with the same key. Records can be accessed through any combination of file ID and record key.

For example, an application could use the following two files:

You could then iterate, for example, through all records in file 1, through all records with key 0x1111, or through all records with key 0x2222 in file 2.

Creating records

When writing a new record to flash, you must provide a record key, a file ID, and the data to be stored. Instead of writing the record right away, you can also reserve memory and use the resulting reservation token to either write the record at a later time or cancel the reservation again.

The write function returns a record descriptor that you can use to access the record. Before you access it, wait for the event that signals that the write operation completed successfully.

Manipulating records

To read, update, or delete the contents of a record, you must access the record through its descriptor. This descriptor is created and returned when you first write the record to flash. After the record has been created, you can retrieve its descriptor by using one of the find record functions (fds_record_find, fds_record_find_by_key, or fds_record_find_in_file). These functions allow you to search for a record based on its record key and file ID.

There is no requirement that keys or IDs must be unique. Therefore, more than one record might match the query. The find record functions return one match at a time and keep track of the progress of the operation. They return a status token that encodes the location of the latest match; this token can be used in a subsequent call to continue the search from that position. So to iterate over all matches, you can repeat the call to the find record function using the same token until no more matches are found. See Retrieving data for an example on how to enumerate all records with a given key and file ID.

Reading records

You can read the contents of a record (both the stored data and, if required, the metadata) directly from flash storage. This means that the application decides if the data is copied, stored in RAM, or used in place.

To access the record content, open the record to retrieve pointers to where the record data and metadata is stored in flash. The fds_record_open function ensures that the record is not modified or moved to a different location in flash memory while it is being accessed. Remember to close the record to release the lock after the record has been read.

Updating records

When you update a record, FDS actually creates a new record and invalidates the old one. This scheme ensures that data is not lost if there is a power loss in the middle of the the operation.

The update function returns a new record descriptor for the updated record. Keep in mind that because of the way FDS treats updates, frequent changes to the record data, key, or file ID can fill up the flash storage and might require you to free up space (see Garbage collection).

Deleting records

Deleting a record does not actually delete the record data and clear the used flash space, but it invalidates the record. After a record has been deleted, it cannot be opened, read, or located anymore.

However, the flash space that is used by the record is not freed right away. To free the space that is used by invalidated records, you must run garbage collection (see Garbage collection).

Garbage collection

Instead of deleting records right away, FDS relies on garbage collection to reclaim flash space used by records that have been invalidated. FDS ensures that no data is lost if there is a power loss in the middle of a garbage collection process. Garbage collection is not run automatically by FDS, but must be started by the application. It is better to run garbage collection when necessary, i.e., when the space in flash is (nearly) full. When the space is exhausted, write requests return the error FDS_ERR_NO_SPACE_IN_FLASH, and you must run garbage collection and wait for completion before repeating the call to the write function. The function fds_stat can return useful information to determine if there are any dirty records in flash which can be garbage collected. Ideally, you should run garbage collection when BLE activity is low otherwise the operation might timeout. When garbage collection times out and the FDS_ERR_TIMEOUT is returned by the FDS_EVT_GC event, the system can continue normal operation. Successive calls to fds_gc will resume garbage collection.

Configuration

There are several configuration options for the FDS module that you can configure at compile time.

The following macros in fds_config.h can be changed to suit your usage of the FDS module:

In addition, you can set the following compile flag:

Restrictions on keys and IDs

Record keys should be in the range 0x0001 - 0xBFFF. The value 0x0000 is reserved by the system. The values from 0xC000 to 0xFFFF are reserved for use by the Peer Manager module and can only be used in applications that do not include Peer Manager.

File IDs should be in the range 0x0000 - 0xBFFF. The value 0xFFFF is used by the system. The values from 0xC000 to 0xFFFE are reserved for use by the Peer Manager module and can only be used in applications that do not include Peer Manager.


Documentation feedback | Developer Zone | Subscribe | Updated