Skip to content

Commit b7bb29a

Browse files
author
David Saada
committed
NVStore: key management enhancements
- Define an enum for predefined keys (later filled by internal users of NVStore) - Add the set_alloc_key API, allocating a free key from the non predefined keys
1 parent 7c30faf commit b7bb29a

File tree

4 files changed

+71
-6
lines changed

4 files changed

+71
-6
lines changed

features/nvstore/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ Each item is kept in an entry containing a header and data, where the header hol
2222
- get: Get the value of an item, given key.
2323
- set: Set the value of an item, given key and value.
2424
- set_once: Like set, but allows only a one time setting of this item (and disables deleting of this item).
25+
- set_alloc_key: Like set, but allocates a free key (from the non predefined keys).
2526
- remove: Remove an item, given key.
2627
- get_item_size: Get the item value size (in bytes).
2728
- set_max_keys: Set maximal value of unique keys. Overriding the default of NVSTORE_MAX_KEYS. This affects RAM consumption,

features/nvstore/TESTS/nvstore/functionality/main.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ static void nvstore_basic_functionality_test()
7070

7171
uint16_t actual_len_bytes = 0;
7272
NVStore &nvstore = NVStore::get_instance();
73+
uint16_t key;
7374

7475
uint8_t *nvstore_testing_buf_set = new uint8_t[basic_func_max_data_size];
7576
uint8_t *nvstore_testing_buf_get = new uint8_t[basic_func_max_data_size];
@@ -127,6 +128,10 @@ static void nvstore_basic_functionality_test()
127128
result = nvstore.set(19, 10, &(nvstore_testing_buf_set[3]));
128129
TEST_ASSERT_EQUAL(NVSTORE_ALREADY_EXISTS, result);
129130

131+
result = nvstore.set_alloc_key(key, 17, &(nvstore_testing_buf_set[3]));
132+
TEST_ASSERT_EQUAL(NVSTORE_NUM_PREDEFINED_KEYS, key);
133+
TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result);
134+
130135
// Make sure set items are also gotten OK after reset
131136
result = nvstore.deinit();
132137
TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result);
@@ -153,6 +158,11 @@ static void nvstore_basic_functionality_test()
153158
TEST_ASSERT_EQUAL(64, actual_len_bytes);
154159
TEST_ASSERT_EQUAL_UINT8_ARRAY(nvstore_testing_buf_set, nvstore_testing_buf_get, 64);
155160

161+
result = nvstore.get(NVSTORE_NUM_PREDEFINED_KEYS, 64, nvstore_testing_buf_get, actual_len_bytes);
162+
TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result);
163+
TEST_ASSERT_EQUAL(17, actual_len_bytes);
164+
TEST_ASSERT_EQUAL_UINT8_ARRAY(&nvstore_testing_buf_set[3], nvstore_testing_buf_get, 17);
165+
156166
result = nvstore.get(10, 65, nvstore_testing_buf_get, actual_len_bytes);
157167
TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result);
158168
TEST_ASSERT_EQUAL(64, actual_len_bytes);

features/nvstore/source/nvstore.cpp

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@ NVStore::NVStore() : _init_done(0), _init_attempts(0), _active_area(0), _max_key
134134
_active_area_version(0), _free_space_offset(0), _size(0), _mutex(0), _offset_by_key(0), _flash(0),
135135
_min_prog_size(0), _page_buf(0)
136136
{
137+
memcpy(_flash_area_params, 0, sizeof(_flash_area_params));
137138
}
138139

139140
NVStore::~NVStore()
@@ -589,6 +590,10 @@ int NVStore::do_get(uint16_t key, uint16_t buf_size, void *buf, uint16_t &actual
589590

590591
if (!buf) {
591592
buf_size = 0;
593+
// This is only required in order to satisfy static code analysis tools, fearing
594+
// that a null buff is dereferenced inside read_record function. However, this won't happen
595+
// when buf_size is 0, so just have buf point to a dummy location.
596+
buf = &flags;
592597
}
593598

594599
_mutex->lock();
@@ -623,7 +628,7 @@ int NVStore::get_item_size(uint16_t key, uint16_t &actual_size)
623628
return do_get(key, 0, NULL, actual_size, 1);
624629
}
625630

626-
int NVStore::do_set(uint16_t key, uint16_t buf_size, const void *buf, uint16_t flags)
631+
int NVStore::do_set(uint16_t &key, uint16_t buf_size, const void *buf, uint16_t flags)
627632
{
628633
int ret = NVSTORE_SUCCESS;
629634
uint32_t record_offset, record_size, new_free_space;
@@ -636,7 +641,11 @@ int NVStore::do_set(uint16_t key, uint16_t buf_size, const void *buf, uint16_t f
636641
}
637642
}
638643

639-
if (key >= _max_keys) {
644+
if ((key != no_key) && (key >= _max_keys)) {
645+
return NVSTORE_BAD_VALUE;
646+
}
647+
648+
if ((key == no_key) && (flags & delete_item_flag)) {
640649
return NVSTORE_BAD_VALUE;
641650
}
642651

@@ -648,14 +657,25 @@ int NVStore::do_set(uint16_t key, uint16_t buf_size, const void *buf, uint16_t f
648657
return NVSTORE_NOT_FOUND;
649658
}
650659

651-
if (_offset_by_key[key] & offs_by_key_set_once_mask) {
660+
if ((key != no_key) && (_offset_by_key[key] & offs_by_key_set_once_mask)) {
652661
return NVSTORE_ALREADY_EXISTS;
653662
}
654663

655664
record_size = align_up(sizeof(nvstore_record_header_t) + buf_size, _min_prog_size);
656665

657666
_mutex->lock();
658667

668+
if (key == no_key) {
669+
for (key = NVSTORE_NUM_PREDEFINED_KEYS; key < _max_keys; key++) {
670+
if (!_offset_by_key[key]) {
671+
break;
672+
}
673+
}
674+
if (key == _max_keys) {
675+
return NVSTORE_NO_FREE_KEY;
676+
}
677+
}
678+
659679
new_free_space = core_util_atomic_incr_u32(&_free_space_offset, record_size);
660680
record_offset = new_free_space - record_size;
661681

@@ -696,6 +716,12 @@ int NVStore::set_once(uint16_t key, uint16_t buf_size, const void *buf)
696716
return do_set(key, buf_size, buf, set_once_flag);
697717
}
698718

719+
int NVStore::set_alloc_key(uint16_t &key, uint16_t buf_size, const void *buf)
720+
{
721+
key = no_key;
722+
return do_set(key, buf_size, buf, 0);
723+
}
724+
699725
int NVStore::remove(uint16_t key)
700726
{
701727
return do_set(key, 0, NULL, delete_item_flag);

features/nvstore/source/nvstore.h

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,20 @@ typedef enum {
4141
NVSTORE_FLASH_AREA_TOO_SMALL = -7,
4242
NVSTORE_OS_ERROR = -8,
4343
NVSTORE_ALREADY_EXISTS = -9,
44+
NVSTORE_NO_FREE_KEY = -10,
4445
} nvstore_status_e;
4546

47+
typedef enum {
48+
NVSTORE_FIRST_PREDEFINED_KEY = 0,
49+
50+
// All predefined keys used for internal features should be defined here
51+
52+
NVSTORE_LAST_PREDEFINED_KEY = 15,
53+
NVSTORE_NUM_PREDEFINED_KEYS
54+
} nvstore_predefined_keys_e;
55+
4656
#ifndef NVSTORE_MAX_KEYS
47-
#define NVSTORE_MAX_KEYS 16
57+
#define NVSTORE_MAX_KEYS ((uint16_t)NVSTORE_NUM_PREDEFINED_KEYS)
4858
#endif
4959

5060
// defines 2 areas - active and nonactive, not configurable
@@ -148,6 +158,24 @@ class NVStore : private mbed::NonCopyable<NVStore> {
148158
*/
149159
int set(uint16_t key, uint16_t buf_size, const void *buf);
150160

161+
/**
162+
* @brief Programs one item of data on Flash, allocating a key.
163+
*
164+
* @param[out] key Returned key of stored item.
165+
* @param[in] buf_size Item size in bytes.
166+
* @param[in] buf Buffer containing data.
167+
*
168+
* @returns NVSTORE_SUCCESS Value was successfully written on Flash.
169+
* NVSTORE_WRITE_ERROR Physical error writing data.
170+
* NVSTORE_BAD_VALUE Bad value in any of the parameters.
171+
* NVSTORE_FLASH_AREA_TOO_SMALL
172+
* Not enough space in Flash area.
173+
* NVSTORE_ALREADY_EXISTS Item set with write once API already exists.
174+
* NVSTORE_NO_FREE_KEY Couldn't allocate a key for this call.
175+
*
176+
*/
177+
int set_alloc_key(uint16_t &key, uint16_t buf_size, const void *buf);
178+
151179
/**
152180
* @brief Programs one item of data on Flash, given key, allowing no consequent sets to this key.
153181
*
@@ -394,14 +422,14 @@ class NVStore : private mbed::NonCopyable<NVStore> {
394422
/**
395423
* @brief Actual logics of set API (covers also set_once and remove APIs).
396424
*
397-
* @param[in] key key.
425+
* @param[out] key key (both input and output).
398426
* @param[in] buf_size Buffer size (bytes).
399427
* @param[in] buf Input Buffer.
400428
* @param[in] flags Record flags.
401429
*
402430
* @returns 0 for success, nonzero for failure.
403431
*/
404-
int do_set(uint16_t key, uint16_t buf_size, const void *buf, uint16_t flags);
432+
int do_set(uint16_t &key, uint16_t buf_size, const void *buf, uint16_t flags);
405433

406434
};
407435
/** @}*/

0 commit comments

Comments
 (0)