nRF5 SDK v17.0.2
Flash Storage (fstorage)

Flash Storage (or fstorage for short) is a module for reading, writing, and erasing data in persistent flash storage. The module defines an asynchronous interface to access flash memory with read, write, and (page) erase operations. The application is notified of the operation results through callbacks to registered event handlers.

The functionality of the interface can be implemented by different backends with different characteristics. The following backends are implemented.

Name Peripheral Characteristics
nrf_fstorage_nvmc On-Chip flash Uses the NVMC peripheral. Can only be used when the SoftDevice is not present or present but not enabled.
nrf_fstorage_sd On-Chip flash Use the SoftDevice flash API. Can be used anytime the SoftDevice is present, regardless of its status (enabled/disabled).
Note
None of the above backends are currently thread-safe.

This is a low-level library intended to provide a simple, raw interface to flash memory. If you need a higher level API with update/search functionality to store records and files that takes care of where to store data for you, how to read it back, how to manage updates and so forth, use Flash Data Storage (FDS) instead.

Flash Data Storage (FDS) internally uses fstorage. The module can be used directly as well.

Defining an instance

Any user of fstorage can select one of the backends available and specify an area of flash memory on which it is allowed to operate, together with a callback function used to report the status of requested operations. Thus, an fstorage instance is defined.

The NRF_FSTORAGE_DEF macro is provided to simplify this procedure. It is possible for different instances to use the same backend.

Initialization

Once defined, an fstorage instance needs to be initialized using nrf_fstorage_init. A complete initialization example is shown below:

void callback(nrf_fstorage_evt_t * p_evt);
{
.evt_handler = callback,
.start_addr = 0xFD000,
.end_addr = 0xFFFFF,
};
int main()
{
&my_instance, /* You fstorage instance, previously defined. */
&nrf_fstorage_sd, /* Name of the backend. */
NULL /* Optional parameter, backend-dependant. */
);
}

Any instance can be reinitialized to operate using a different backend, should this be necessary, by calling nrf_fstorage_init again with the selected backend.

Note
fstorage makes no effort to ensure that different instances operate on non-overlapping flash memory regions. It is up to the users to ensure that their usage of the module does not disrupt others'.

Below is some useful information on which areas of the on-chip flash are used by SDK modules to store data in flash.

fds.svg
Flash layout with and without the bootloader

Writing data

The code snippet below shows how to write data, assuming that my_instance is the fstorage instance previously defined.

/* This is the address in flash were data will be written.
The address below is presented as an example to illustrate the API.
To decide where to store your data in flash, you must have an understanding of
the layout of your application in flash.
*/
#define FLASH_ADDR 0xFC000
/* This is the data to write in flash.
Because the fstorage interface is asynchrounous, the data must be kept in memory.
*/
static uint32_t number = 123;
&my_instance, /* The instance to use. */
FLASH_ADDR, /* The address in flash where to store the data. */
&number, /* A pointer to the data. */
sizeof(number), /* Lenght of the data, in bytes. */
NULL /* Optional parameter, backend-dependent. */
);
if (rc == NRF_SUCCESS)
{
/* The operation was accepted.
Upon completion, the NRF_FSTORAGE_WRITE_RESULT event
is sent to the callback function registered by the instance. */
}
else
{
/* Handle error.*/
}

Reading data

The code snippet below shows how to write data, assuming that my_instance is the fstorage instance previously defined.

/* This is the address in flash where data will be written.
The address below is presented as an example to illustrate the API.
To decide where to store your data in flash, you must have an understanding of
the layout of your application in flash.
*/
#define FLASH_ADDR 0xFC000
/* This is the data to write in flash.
Because the fstorage interface is asynchrounous, the data must be kept in memory.
*/
static uint32_t number;
&my_instance, /* The instance to use. */
FLASH_ADDR, /* The address in flash where to read data from. */
&number, /* A buffer to copy the data into. */
sizeof(number) /* Lenght of the data, in bytes. */
);
if (rc == NRF_SUCCESS)
{
/* The operation was accepted. */
}
else
{
/* Handle error.*/
}

Erasing flash pages

The code snippet below shows how to erase flash pages, assuming that my_instance is the fstorage instance previously defined.

/* This is the address in flash page to be erased.
The address below is presented as an example to illustrate the API. */
#define FLASH_ADDR 0xFC000
static uint32_t pages_to_erase = 1;
&my_instance, /* The instance to use. */
FLASH_ADDR, /* The address of the flash pages to erase. */
pages_to_erase, /* The number of pages to erase. */
NULL /* Optional parameter, backend-dependent. */
);
if (rc == NRF_SUCCESS)
{
/* The operation was accepted.
Upon completion, the NRF_FSTORAGE_ERASE_RESULT event
is sent to the callback function registered by the instance. */
}
else
{
/* Handle error.*/
}
Note
Success or failure of each operation is indicated through events. Therefore, checking the return value confirms only that the function was called successfully, but not that the operation has actually been carried out yet.

Backends

Two backends are provided in the SDK:

SoftDevice backend

A backend for on-chip flash, using the SoftDevice.

This backend interfaces with the SoftDevice flash API to perform operations in flash. It can be used any time the SoftDevice is present, regardless of whether the SoftDevice is enabled or not. However, when running a protocol stack, the success of flash operations is tied to the timing constraints of the protocol and the characteristics of the hardware. Using too aggressive scan or advertising intervals, or running multiple connections, can influence the success of a flash operation. In most situations, nrf_fstorage_sd will handle flash operations concurrently with radio protocols without problems. Should you encounter timeout errors, try decreasing the size of the data that is being written at once (in one nrf_fstorage_write call), if possible. Otherwise, try modifying NRF_FSTORAGE_SD_MAX_WRITE_SIZE and increment NRF_FSTORAGE_SD_MAX_RETRIES. If the problem persists, refer to the SoftDevice specification document to determine more suitable scanning and advertising intervals.

This backend is an observer of SoftDevice state change requests. When a request to change the state of the SoftDevice is made through the SoftDevice Handler library by calling nrf_sdh_enable_request or nrf_sdh_disable_request, fstorage will receive this request. Then, depending on whether there are ongoing flash operations issued by any of its users, it will defer or acknowledge the SoftDevice state change.

In practice, this means that it is possible to disable and enable the SoftDevice at will with the guarantee that flash operations won't be disrupted.

This backend has several configuration options found in Flash abstraction library configuration.

NRF_FSTORAGE_SD_MAX_WRITE_SIZE configures the maximum number of bytes that will be written at once. Effectively, this allows to split write operations in a transparent way for the application. The effect of splitting write operations is to enable the SoftDevice to more easily schedule those along radio operation.

Requests to erase multiple pages are split up into individual page erases.

NRF_FSTORAGE_SD_MAX_RETRIES configures the number of times fstorage will retry an operation when the SoftDevice has failed to schedule it in time and timed out.

NVMC backend

A backend for on-chip flash, using the NVMC peripheral.

This backend uses the NVMC hardware on the chip. Using this backend when the SoftDevice is present AND enabled will cause an assert.

Example

For the usage example of this library, see Flash Storage Example.


Documentation feedback | Developer Zone | Subscribe | Updated