nRF51 SDK v10.0.0
Usage

The following code examples show the typical usage of Flash Data Storage in an application.

Initialization

Initialization, like every other operation in FDS which involves writing or erasing flash memory, is an asynchronous operation whose completion is reported to the application through a callback. Therefore, before initializing FDS, you must register a callback handler to handle FDS events.

The following example code shows the signature of the event handler and how to register it with FDS:

static void fds_evt_handler(ret_code_t result,
fds_record_id_t record_id,
fds_record_key_t record_key)
{
// Handle events here
}
ret_code_t retval = fds_register(fds_evt_handler);
if(retval != NRF_SUCCESS)
{
// Registering of callback handler failed.
}

After the event handler has been registered, initialize FDS:

ret_code_t retval = fds_init();
if (retval != NRF_SUCCESS)
{
// Error.
}

The operation will return an event notification upon success.

In the Peer Manager, fds_init is part of the initialization function pm_init.

Writing down a record

The following example code shows how to write a record:

uint32_t data;
ret_code_t retval;
fds_record_desc_t descriptor;
// Fill in the record keys.
key.type = SOME_UNSIGNED_INTEGER;
key.instance = SOME_UNSIGNED_INTEGER;
// Initialize the record chunk, pointing it to the data to be stored.
chunk.p_data = &data;
chunk.length_words = 1;
// Write the record to flash.
retval = fds_write(&descriptor,
key,
1 /*number of chunks*/,
&chunk);
if (retval != NRF_SUCCESS)
{
// Error.
}
// The command was queued. Wait for a callback signalling its completion.

The command is queued up, and the success or failure is indicated through event callbacks. Upon success, the fds_write function returns a descriptor for the record, which can be used to further manipulate the record.

Instead of writing a record right away, it is possible to reserve memory beforehand and use the resulting reservation token to either write the record at a later moment using the functions fds_reserve, and fds_write_reserved. To cancel a reservation, use fds_reserve_cancel.

Retrieving data

Because the uniqueness of record keys is not enforced, looking up a record by a given set of keys can result in multiple matches. To handle multiple matches, the fds_find, fds_find_by_type and fds_find_by_instance functions accept a fds_find_token_t structure as parameter, which is used to keep information about the progress of the operation. Once a descriptor for a matching record is returned by the first invocation of any of these functions, subsequent calls using the same token will resume searching from the last record matched. Therefore, it is possible to enumerate records. The following example code shows how to use the find functionality to retrieve a record and read its contents.

typedef uint32_t my_type;
my_type data;
fds_type_id_t type;
fds_instance_id_t inst;
fds_record_desc_t descriptor;
fds_record_t record;
// Set the record keys.
type = SOME_UNSIGNED_INTEGER;
inst = SOME_UNSIGNED_INTEGER;
// Loop until all records with the given key pair has been found.
while (fds_find(type, inst, &descriptor, &tok) == NRF_SUCCESS)
{
// A record was found. Open the record to check its contents.
fds_open(&descriptor, &record);
// Cast the data.
data = (uint32_t)(*record.p_data);
if (data == SOME_VALUE)
{
// Do something.
}
// When you are done, close the record using its descriptor.
fds_close(&descriptor);
}

Keep in mind that closing a record using fds_close will not invalidate the record descriptor neither the fds_record_t structure. In fact, the record descriptor can still be used to manipulate the record, e.g. opening it again or deleting it. However, the data pointed by the fds_record_t structure is not guaranteed to remain unmodified if the record has been closed.

Deleting a record

To delete a record, you must . This can either be returned by fds_write or it can be obtained using fds_find, fds_find_by_type and fds_find_by_instance as shown above. The following example code shows clear an item for which you have a descriptor for:

// Assume a descriptor returned by a call to fds_write() or fds_find(), as shown above.
fds_record_desc_t descriptor;
retval = fds_clear(&descriptor);
if (retval != NRF_SUCCESS)
{
// Error.
}

The operation is queued up, and the success or failure is indicated through event callbacks.

Keep in mind that using fds_clear will not free the flash memory used by the record. To reclaim flash space used by records deleted using fds_clear, use fds_gc.


This document was last updated on Mon Nov 9 2015.
Please send us your feedback about the documentation! For technical questions, visit the Nordic Developer Zone.