Storage Library

The Storage library provides abstractions for reading, writing, and erasing non-volatile memory (NVM).

Overview

The library supports multiple storage instances, each bound to a specific memory region, and reports operation results through user-defined event handlers. Depending on the backend and runtime state, operations may be synchronous or asynchronous.

Configuration

The library is enabled and configured entirely using the Kconfig system. Set the CONFIG_BM_STORAGE Kconfig option to enable the library.

Select a storage backend by enabling one of the following Kconfig options:

The selected backend’s API instance is made available through the include/bm/storage/bm_storage_backends.h header, which is included transitively by include/bm/storage/bm_storage.h.

SoftDevice backend options:

Initialization

Each storage instance is represented by a bm_storage structure.

To initialize a storage instance, use the bm_storage_init() function, providing a configuration struct bm_storage_config with the following information:

The following example shows how to initialize a storage instance with a backend API:

#include <bm/storage/bm_storage.h>

struct bm_storage storage;
struct bm_storage_config config = {
    .evt_handler = my_handler,
    .api = &bm_storage_sd_api,
    .addr = PARTITION_ADDR,
    .size = PARTITION_SIZE,
};

bm_storage_init(&storage, &config);

All read, write, and erase operations use offsets relative to the partition start (0-based).

You can uninitialize a storage instance with the bm_storage_uninit() function.

Usage

The following is a list of operations you can perform with this library.

Read

Use the bm_storage_read() function to copy data from NVM into RAM.

Write

Use the bm_storage_write() function to write data to NVM. The completion of the operation is reported by the BM_STORAGE_EVT_WRITE_RESULT event.

Note

The program unit is the minimum programmable block in NVM. Write operations must start at an address aligned by the program unit and use a length that is a multiple of this value.

If bm_storage_config.is_wear_aligned is set during initialization, the wear unit (bm_storage_info.wear_unit) is used for alignment instead. If bm_storage_config.is_write_padded is set during initialization, write operations are automatically padded to the chosen alignment unit (either the program or wear unit).

Erase

Use the bm_storage_erase() function to erase a region in NVM. The completion of the operation is reported by the BM_STORAGE_EVT_ERASE_RESULT event.

Note

The erase unit is the minimum erasable block in NVM. Erase operations must start at an address aligned by the erase unit and use a length that is a multiple of this value. The erase unit is reported by bm_storage_info.erase_unit.

When the erase operation is not supported by the hardware, the backend will emulate it by writing the memory’s erased value to the NVM area. If the erase operation is emulated, the alignment requirements are the same as those for the write operation.

Busy state

Use the bm_storage_is_busy() function to check whether a backend is executing an operation.

Events

The following events may be reported to the user callback:

Each event includes the result code, information about the address range of the associated operation, and whether the operation is synchronous or asynchronous.

Event deferral

Backends that do not have an internal operation queue (for example, the RRAM backend) deliver events synchronously from the same call context as the caller. If the application queues another storage operation from within its event handler, unbounded recursion can occur.

Backends with an internal operation queue (for example, the SoftDevice backend) are not affected, because re-entrant calls are enqueued and processed iteratively.

To prevent recursion in backends without a queue, enable the CONFIG_BM_SCHEDULER Kconfig option. When the scheduler is available, synchronous events are automatically deferred and delivered from the main thread context on the next call to bm_scheduler_process(). Deferred events have their bm_storage_evt.is_async field set to true.

Sample

The usage of this library is demonstrated in the Bare Metal Storage sample.

Dependencies

Optional dependencies:

API documentation

Header file: include/bm/storage/bm_storage.h
Header file: include/bm/storage/bm_storage_backends.h
Source files: lib/bm_storage/

Storage library API reference