(kv-store)
Key Value Storage Library

General Description

This library provides a convenient way to store information as key-value pairs in non-volatile storage.

Getting Started

This section provides steps for getting started with this library by using the block storage interface.block-storage

  1. Include the kv-store library header in the application.
    #include "mtb_kvstore.h"
  2. Initialize the underlying storage. This could be done using either the HAL NVM or Serial Memory depending on the storage
    • Example initialization for hal API 3.0 nvm driver
      mtb_hal_nvm_t nvm_obj;
      mtb_hal_nvm_region_info_t block_info;
      cy_rslt_t result = mtb_hal_nvm_setup(&nvm_obj, NULL);
      CY_ASSERT(result == CY_RSLT_SUCCESS);
      mtb_hal_nvm_info_t nvm_info;
      mtb_hal_nvm_get_info(&nvm_obj, &nvm_info);
      block_info = nvm_info.regions[nvm_info.region_count - 1];
    • Example initialization for serial memory driver
      mtb_serial_memory_t serial_memory_obj;
      cy_stc_smif_context_t context;
      /* Setup the serial memory object */
      cy_rslt_t result = mtb_serial_memory_setup(
      &serial_memory_obj, MTB_SERIAL_MEMORY_CHIP_SELECT_0,
      &base_address, &sm_clock, &context, &smif_block_obj);
    • Example initialization for hal API 2.0 nvm driver
      cyhal_nvm_t nvm_obj;
      cyhal_nvm_region_info_t block_info;
      cy_rslt_t result = cyhal_nvm_init(&nvm_obj);
      CY_ASSERT(result == CY_RSLT_SUCCESS);
      cyhal_nvm_info_t nvm_info;
      cyhal_nvm_get_info(&nvm_obj, &nvm_info);
      block_info = nvm_info.regions[nvm_info.region_count - 1];
  3. Create the block storage interface using the HAL NVM or the serial memory.If neither the HAL NVM nor serial memory driver is being used to communicate with the storage device, the application must provide a custom implementation of the block device interface.
    • Example implementation using block storage HAL 3.0 NVM interface
      mtb_block_storage_t nvm_bsd;
      mtb_block_storage_create_hal_nvm(&nvm_bsd, &nvm_obj);
    • Example implementation using block storage serial-memory interface
      /* Create the block-storage - serial memory object */
      mtb_block_storage_t serial_memory_bsd;
      mtb_block_storage_create_serial_memory(&serial_memory_bsd, &serial_memory_obj);
      CY_ASSERT(result == CY_RSLT_SUCCESS);
    • Example implementation using block storage HAL Classic NVM interface
      mtb_block_storage_t nvm_bsd;
      mtb_block_storage_nvm_create(&nvm_bsd);
  4. Initialize the kv-store library.
    • Set the start address and length.
      • If using the hal-nvm driver, for this example the address space provided starts 16 pages from the end of the nvm. Note that if the device does not have a working flash (i.e. using main flash) care must be taken to ensure that the space allocated below is not used by anything else (for eg. Application image).
        uint32_t length = 16U * block_info.block_size;
        uint32_t start_addr = block_info.start_address + block_info.size - length;
      • If using the serial-memory library, for this example we define the space provided to the kv-store library to be the size of 2 sectors.
        uint32_t start_addr = 0;
        uint32_t sector_size = serial_memory_bsd.get_erase_size(serial_memory_bsd.context, start_addr);
        uint32_t length = sector_size * 2;
    • Call mtb_kvstore_init by passing the start address, length, block device and the optional memory allocate and free function pointers
      mtb_kvstore_t obj;
      result = mtb_kvstore_init(&obj, start_addr, length, &nvm_bsd, NULL, NULL);
      CY_ASSERT(result == CY_RSLT_SUCCESS);
      cy_rslt_t mtb_kvstore_init(mtb_kvstore_t *obj, uint32_t start_addr, uint32_t length, const mtb_block_storage_t *bsd, mtb_kvstore_allocate_memory_t alloc_memory, mtb_kvstore_free_memory_t free_memory)
      Initialize an instance of the kv-store library.
      Definition: mtb_kvstore.c:1568
  5. The library should now be ready to perform operations.
    • Write operation.
      uint8_t data[10];
      result = mtb_kvstore_write(&obj, "hello", data, sizeof(data));
      CY_ASSERT(result == CY_RSLT_SUCCESS);
      cy_rslt_t mtb_kvstore_write(mtb_kvstore_t *obj, const char *key, const uint8_t *data, uint32_t size)
      Store a key value pair.
      Definition: mtb_kvstore.c:1659
    • Read operation.
      uint8_t read_data[10];
      uint32_t data_size = sizeof(read_data);
      result = mtb_kvstore_read(&obj, "hello", read_data, &data_size);
      CY_ASSERT(result == CY_RSLT_SUCCESS);
      cy_rslt_t mtb_kvstore_read(mtb_kvstore_t *obj, const char *key, uint8_t *data, uint32_t *size)
      Read data associated with a key.
      Definition: mtb_kvstore.c:1741
    • Delete operation.
      result = mtb_kvstore_delete(&obj, "hello");
      CY_ASSERT(result == CY_RSLT_SUCCESS);
      cy_rslt_t mtb_kvstore_delete(mtb_kvstore_t *obj, const char *key)
      Delete a key value pair.
      Definition: mtb_kvstore.c:1866

Macros

#define MTB_KVSTORE_MAX_KEY_SIZE   (64U)
 Maximum key size permitted.
 
#define MTB_KVSTORE_ENSURE_MAX   (0xFFFFFFFFu)
 When passed as an argument to mtb_kvstore_ensure_capacity, indicates that cleanup tasks should always be performed regardless of the amount of space which is currently free, to ensure the maximum possible amount of free space is available.
 
#define MTB_KVSTORE_BAD_PARAM_ERROR    CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_MIDDLEWARE_KVSTORE, 0)
 An invalid parameter value is passed in.
 
#define MTB_KVSTORE_ALIGNMENT_ERROR    CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_MIDDLEWARE_KVSTORE, 1)
 The storage area passed in is not aligned to erase sector boundary. More...
 
#define MTB_KVSTORE_MEM_ALLOC_ERROR    CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_MIDDLEWARE_KVSTORE, 2)
 Memory allocation failed. More...
 
#define MTB_KVSTORE_INVALID_DATA_ERROR    CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_MIDDLEWARE_KVSTORE, 3)
 Invalid data was detected. More...
 
#define MTB_KVSTORE_ERASED_DATA_ERROR    CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_MIDDLEWARE_KVSTORE, 4)
 Erased data was detected. More...
 
#define MTB_KVSTORE_ITEM_NOT_FOUND_ERROR    CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_MIDDLEWARE_KVSTORE, 5)
 Item was not found in the storage.
 
#define MTB_KVSTORE_STORAGE_FULL_ERROR    CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_MIDDLEWARE_KVSTORE, 6)
 The storage is full.
 
#define MTB_KVSTORE_BUFFER_TOO_SMALL    CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_MIDDLEWARE_KVSTORE, 7)
 Buffer provided is too small for value found.
 

Typedefs

typedef cy_rslt_t(* mtb_kvstore_bd_read) (void *context, uint32_t addr, uint32_t length, uint8_t *buf)
 Function prototype for reading data from the block device. More...
 
typedef cy_rslt_t(* mtb_kvstore_bd_program) (void *context, uint32_t addr, uint32_t length, const uint8_t *buf)
 Function prototype for writing data to the block device. More...
 
typedef cy_rslt_t(* mtb_kvstore_bd_erase) (void *context, uint32_t addr, uint32_t length)
 Function prototype for read from the block device. More...
 
typedef uint32_t(* mtb_kvstore_bd_read_size) (void *context, uint32_t addr)
 Function prototype to get the read size of the block device for a specific address. More...
 
typedef uint32_t(* mtb_kvstore_bd_program_size) (void *context, uint32_t addr)
 Function prototype to get the program size of the block device for a specific address. More...
 
typedef uint32_t(* mtb_kvstore_bd_erase_size) (void *context, uint32_t addr)
 Function prototype to get the erase size of the block device for a specific address. More...
 
typedef void *(* mtb_kvstore_allocate_memory_t) (size_t size)
 Function prototype for allocating memory to be used for kv-store internal operations. More...
 
typedef void(* mtb_kvstore_free_memory_t) (void *ptr)
 Function prototype for freeing memory. More...
 

Functions

cy_rslt_t mtb_kvstore_init (mtb_kvstore_t *obj, uint32_t start_addr, uint32_t length, const mtb_block_storage_t *bsd, mtb_kvstore_allocate_memory_t alloc_memory, mtb_kvstore_free_memory_t free_memory)
 Initialize an instance of the kv-store library. More...
 
cy_rslt_t mtb_kvstore_write (mtb_kvstore_t *obj, const char *key, const uint8_t *data, uint32_t size)
 Store a key value pair. More...
 
cy_rslt_t mtb_kvstore_read (mtb_kvstore_t *obj, const char *key, uint8_t *data, uint32_t *size)
 Read data associated with a key. More...
 
cy_rslt_t mtb_kvstore_read_partial (mtb_kvstore_t *obj, const char *key, uint8_t *data, uint32_t *size, const uint32_t offset_bytes)
 Read data associated with a key. More...
 
cy_rslt_t mtb_kvstore_key_exists (mtb_kvstore_t *obj, const char *key)
 Check if a key is stored in memory. More...
 
cy_rslt_t mtb_kvstore_value_size (mtb_kvstore_t *obj, const char *key, uint32_t *size)
 Get the size in bytes of data in memory corresponding to a given key. More...
 
cy_rslt_t mtb_kvstore_delete (mtb_kvstore_t *obj, const char *key)
 Delete a key value pair. More...
 
uint32_t mtb_kvstore_size (mtb_kvstore_t *obj)
 Query the size consumed in the kv-store storage. More...
 
uint32_t mtb_kvstore_remaining_size (mtb_kvstore_t *obj)
 Query the free space available in the kv-store storage. More...
 
cy_rslt_t mtb_kvstore_ensure_capacity (mtb_kvstore_t *obj, uint32_t size)
 Tries to make the specified amount of space available for immediate use. More...
 
cy_rslt_t mtb_kvstore_reset (mtb_kvstore_t *obj)
 Reset kv-store storage. More...
 
void mtb_kvstore_deinit (mtb_kvstore_t *obj)
 Delete kv-store instance. More...
 

Macro Definition Documentation

◆ MTB_KVSTORE_ALIGNMENT_ERROR

#define MTB_KVSTORE_ALIGNMENT_ERROR    CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_MIDDLEWARE_KVSTORE, 1)

The storage area passed in is not aligned to erase sector boundary.

See notes in mtb_kvstore_init for more information on constraints.

◆ MTB_KVSTORE_MEM_ALLOC_ERROR

#define MTB_KVSTORE_MEM_ALLOC_ERROR    CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_MIDDLEWARE_KVSTORE, 2)

Memory allocation failed.

There is not enough space available on the heap.

◆ MTB_KVSTORE_INVALID_DATA_ERROR

#define MTB_KVSTORE_INVALID_DATA_ERROR    CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_MIDDLEWARE_KVSTORE, 3)

Invalid data was detected.

The record may be corrupted.

◆ MTB_KVSTORE_ERASED_DATA_ERROR

#define MTB_KVSTORE_ERASED_DATA_ERROR    CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_MIDDLEWARE_KVSTORE, 4)

Erased data was detected.

The record may be corrupted

Typedef Documentation

◆ mtb_kvstore_bd_read

typedef cy_rslt_t(* mtb_kvstore_bd_read) (void *context, uint32_t addr, uint32_t length, uint8_t *buf)

Function prototype for reading data from the block device.

Parameters
[in]contextContext object that is passed into mtb_kvstore_init
[in]addrAddress to read the data from the block device. This address is passed in as start_addr + offset.
[in]lengthLength of the data that needs to be read.
[out]bufBuffer to read the data.
Returns
Result of the read operation.

◆ mtb_kvstore_bd_program

typedef cy_rslt_t(* mtb_kvstore_bd_program) (void *context, uint32_t addr, uint32_t length, const uint8_t *buf)

Function prototype for writing data to the block device.

Parameters
[in]contextContext object that is passed into mtb_kvstore_init
[in]addrAddress to program the data into the block device. This address is passed in as start_addr + offset.
[in]lengthLength of the data that needs to be written
[out]bufData that needs to be written
Returns
Result of the program operation.

◆ mtb_kvstore_bd_erase

typedef cy_rslt_t(* mtb_kvstore_bd_erase) (void *context, uint32_t addr, uint32_t length)

Function prototype for read from the block device.

Parameters
[in]contextContext object that is passed into mtb_kvstore_init
[in]addrAddress to read the data from the device. This address is passed in as start_addr + offset.
[in]lengthLength of the data that needs to be erased.
Returns
Result of the erase operation.

◆ mtb_kvstore_bd_read_size

typedef uint32_t(* mtb_kvstore_bd_read_size) (void *context, uint32_t addr)

Function prototype to get the read size of the block device for a specific address.

Parameters
[in]contextContext object that is passed into mtb_kvstore_init
[in]addrAddress for which the read size is queried. This address is passed in as start_addr + offset.
Returns
Read size of the memory device.

◆ mtb_kvstore_bd_program_size

typedef uint32_t(* mtb_kvstore_bd_program_size) (void *context, uint32_t addr)

Function prototype to get the program size of the block device for a specific address.

Parameters
[in]contextContext object that is passed into mtb_kvstore_init
[in]addrAddress for which the program size is queried. This address is passed in as start_addr + offset.
Returns
Program size of the memory device.

◆ mtb_kvstore_bd_erase_size

typedef uint32_t(* mtb_kvstore_bd_erase_size) (void *context, uint32_t addr)

Function prototype to get the erase size of the block device for a specific address.

Parameters
[in]contextContext object that is passed into mtb_kvstore_init
[in]addrAddress for which the erase size is queried. This address is passed in a start_addr + offset.
Returns
Erase size of the memory device.

◆ mtb_kvstore_allocate_memory_t

typedef void *(* mtb_kvstore_allocate_memory_t) (size_t size)

Function prototype for allocating memory to be used for kv-store internal operations.

Parameters
[in]sizeSize in bytes of the memory to be allocated
Returns
Pointer to the allocated memory in case the memory allocation is success or NULL in case of failure.

◆ mtb_kvstore_free_memory_t

typedef void(* mtb_kvstore_free_memory_t) (void *ptr)

Function prototype for freeing memory.

Parameters
[in]ptrPointer to the memory block to be freed
Returns
None.

Function Documentation

◆ mtb_kvstore_init()

cy_rslt_t mtb_kvstore_init ( mtb_kvstore_t *  obj,
uint32_t  start_addr,
uint32_t  length,
const mtb_block_storage_t *  bsd,
mtb_kvstore_allocate_memory_t  alloc_memory,
mtb_kvstore_free_memory_t  free_memory 
)

Initialize an instance of the kv-store library.

Parameters
[out]objPointer to a kv-store object. The caller must allocate the memory for this object but the init function will initialize its contents.
[in]start_addrStart address for the memory. All addresses when performing memory operations will be offset from this address. See notes for constraints.
[in]lengthTotal space available in bytes. See notes for constraints.
[in]bsdBlock storage device interface for the underlying memory to be used.
[in]alloc_memoryOptional parameter that could be used to allocate the requested memory size. Application could set up this function pointer if they desire to allocate the memory from specific memory region. If not null, KV Store uses the specified function for allocating the memory needed for internal operations. When specified as NULL, KV Store uses the malloc function to allocate the memory
[in]free_memoryOptional parameter that could be used to free the memory block allocated using the 'alloc_memory' function.If not null, KV Store uses the specified function for freeing the memory. When specified as NULL, KV Store uses the free function to free the memory

Address space considerations

Note
The start_addr and start_addr + length must be aligned to the erase sector boundary.
An even number of erase sectors must be provided as storage. (2 * N * erase sector size) where N is the number of sectors.
The implementation assumes that the value of the storage in the erased state is either 0x00 or 0xFF.
The space provided to the library provided must have the uniform characteristics (erase, program and read size). A space spanning regions with different characteristics in a hybrid sector device is not supported and if provided may lead to undefined behavior.
If the application desires to use specific memory region for KV Store internal operation, it should set up both the alloc_memory and free_memory functions.

RTOS considerations

Note
In a RTOS environment the library must be initialized after the RTOS kernel has started.
Returns
Result of the initialization operation.

◆ mtb_kvstore_write()

cy_rslt_t mtb_kvstore_write ( mtb_kvstore_t *  obj,
const char *  key,
const uint8_t *  data,
uint32_t  size 
)

Store a key value pair.

Parameters
[in]objPointer to a kv-store object
[in]keyLookup key for the data.
[in]dataPointer to the start of the data to be stored.
[in]sizeTotal size of the data in bytes.
Returns
Result of the write operation.

◆ mtb_kvstore_read()

cy_rslt_t mtb_kvstore_read ( mtb_kvstore_t *  obj,
const char *  key,
uint8_t *  data,
uint32_t *  size 
)

Read data associated with a key.

Parameters
[in]objPointer to a kv-store object
[in]keyLookup key for the data.
[out]dataPointer to the start of the buffer for the data to be read into.
[in,out]size[in] Total size of the data in bytes. [out] Actual size of the data in storage. If a data buffer is provided then the size cannot be NULL or 0.
Note
It is valid to set both data and size to NULL to check if the key exists in the storage.
Returns
Result of the read operation.

◆ mtb_kvstore_read_partial()

cy_rslt_t mtb_kvstore_read_partial ( mtb_kvstore_t *  obj,
const char *  key,
uint8_t *  data,
uint32_t *  size,
const uint32_t  offset_bytes 
)

Read data associated with a key.

If buffer is too small, will partially read and fill buffer. No corruption checking is performed.

Parameters
[in]objPointer to a kv-store object
[in]keyLookup key for the data.
[out]dataPointer to the start of the buffer for the data to be read into.
[in,out]size[in] Total size of the data in bytes. [out] Number of bytes read into buffer. If a data buffer is provided then the size cannot be NULL or 0.
[in]offset_bytesNumber of bytes to skip at the start the value read into data
Returns
Result of the read operation.

◆ mtb_kvstore_key_exists()

cy_rslt_t mtb_kvstore_key_exists ( mtb_kvstore_t *  obj,
const char *  key 
)

Check if a key is stored in memory.

Parameters
[in]objPointer to a kv-store object
[in]keyLookup key
Returns
Result of the key_exists operation

◆ mtb_kvstore_value_size()

cy_rslt_t mtb_kvstore_value_size ( mtb_kvstore_t *  obj,
const char *  key,
uint32_t *  size 
)

Get the size in bytes of data in memory corresponding to a given key.

Parameters
[in]objPointer to a kv-store object
[in]keyLookup key for the data
[out]sizeSize of data in bytes
Returns
Result of the value size operation

◆ mtb_kvstore_delete()

cy_rslt_t mtb_kvstore_delete ( mtb_kvstore_t *  obj,
const char *  key 
)

Delete a key value pair.

Note
This function will return CY_RSLT_SUCCESS if the key cannot be found in the storage.
Parameters
[in]objPointer to a kv-store object.
[in]keyLookup key to delete key value pair.
Returns
Result of the delete operation.

◆ mtb_kvstore_size()

uint32_t mtb_kvstore_size ( mtb_kvstore_t *  obj)

Query the size consumed in the kv-store storage.

Parameters
[in]objPointer to a kv-store object.
Returns
Size of storage consumed in bytes.

◆ mtb_kvstore_remaining_size()

uint32_t mtb_kvstore_remaining_size ( mtb_kvstore_t *  obj)

Query the free space available in the kv-store storage.

Parameters
[in]objPointer to a kv-store object
Returns
Size of storage free in bytes.

◆ mtb_kvstore_ensure_capacity()

cy_rslt_t mtb_kvstore_ensure_capacity ( mtb_kvstore_t *  obj,
uint32_t  size 
)

Tries to make the specified amount of space available for immediate use.

If necessary, internal cleanup operations will be executed to make additional space available, so this is a potentially long-running operation.

Parameters
[in]objPointer to a kv-store object
[in]sizeAmount of space to ensure is available, in bytes. To always perform cleanup operations regardless of the amount of space currently free, use MTB_KVSTORE_ENSURE_MAX.
Returns
Result of the operation. If size is not MTB_KVSTORE_ENSURE_MAX and it is not possible to make the requested amount of space available, returns MTB_KVSTORE_STORAGE_FULL_ERROR.

◆ mtb_kvstore_reset()

cy_rslt_t mtb_kvstore_reset ( mtb_kvstore_t *  obj)

Reset kv-store storage.

This function erases all the data in the storage.

Parameters
[in]objPointer to a kv-store object
Returns
Result of the reset operation

◆ mtb_kvstore_deinit()

void mtb_kvstore_deinit ( mtb_kvstore_t *  obj)

Delete kv-store instance.

This function frees any program memory allocated by the library.

Parameters
[in]objPointer to a kv-store object