| nRF5 SDK v12.0.0 |

Choose documentation: | nRF5 SDK | S130 SoftDevice API | S132 SoftDevice API | S212 SoftDevice API | S332 SoftDevice API

All Data Structures Functions Variables Typedefs Enumerations Enumerator Groups Pages
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:

- File 1 with two records: 0x1111="Phone1", 0x2222="data: 12345"
- File 2 with three records: 0x1111="Tablet1", 0x2222="data: abcdef", 0x2222="data: 67890"

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. 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. Garbage collection usually requires many flash operations, which makes it quite costly in terms of power consumption.

Therefore, garbage collection is not run automatically by FDS, but must be started by the application. Ideally, you should run garbage collection when BLE activity is low. But you should run it only when necessary, thus 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.

# 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:

- FDS_OP_QUEUE_SIZE: The size of the internal queue of FDS operations. Increase the size if there are many users, or if your application will queue many operations at a time without waiting for the previous operations to complete. In general, you should increase the queue size if you frequently receive FDS_ERR_NO_SPACE_IN_QUEUES errors.
- FDS_CHUNK_QUEUE_SIZE: The number of record chunks (pieces of record data) that can be buffered. Increase the queue size if you frequently receive FDS_ERR_NO_SPACE_IN_QUEUES errors and your data is typically composed of many chunks.
- FDS_VIRTUAL_PAGE_SIZE: The size of a virtual page. By default, a virtual page is the same size as a physical page, but you can increase the virtual page size to be able to store data that is larger than a physical page (see Maximum length).
- FDS_VIRTUAL_PAGES: The number of virtual pages to use. The total amount of flash memory that is used depends on the size and the number of virtual pages.
- FDS_MAX_USERS: The maximum number of callbacks that can be registered, which defines how many modules can use FDS at the same time. Increase the number if you receive an FDS_ERR_USER_LIMIT_REACHED error to allow more users to register with FDS.

In addition, you can set the following compile flags:

- FDS_CRC_ENABLED: If set, FDS will verify a record before opening it for reading. In addition, you can enable a check that ensures that data does not change between the request to write it to a record and the actual write operation (see fds_verify_crc_on_writes). Enabling FDS_CRC_ENABLED slightly increases the code size.
- FDS_THREADS: If set, the FDS module can be used by multiple modules at the same time (for example, by the Peer Manager and the application). Enabling FDS_THREADS increases the code size. Note that this feature is experimental and should not be used in production.