@@ -61,8 +61,8 @@ static const unsigned int owner_bit_pos = 12;
61
61
62
62
typedef struct {
63
63
uint16_t version;
64
- uint16_t reserved1 ;
65
- uint32_t reserved2 ;
64
+ uint16_t max_keys ;
65
+ uint32_t reserved ;
66
66
} master_record_data_t ;
67
67
68
68
static const uint32_t min_area_size = 4096 ;
@@ -171,11 +171,54 @@ uint16_t NVStore::get_max_possible_keys()
171
171
172
172
void NVStore::set_max_keys (uint16_t num_keys)
173
173
{
174
+ uint16_t key = 0 , old_max_keys = 0 ;
175
+
174
176
MBED_ASSERT (num_keys < get_max_possible_keys ());
177
+
178
+ if (num_keys < NVSTORE_NUM_PREDEFINED_KEYS) {
179
+ return ;
180
+ }
181
+
182
+ if (!_init_done) {
183
+ int ret = init ();
184
+ if (ret != NVSTORE_SUCCESS) {
185
+ return ;
186
+ }
187
+ }
188
+
189
+ _mutex->lock ();
190
+
191
+ // check if there are values that might be discarded
192
+ if (num_keys < _max_keys) {
193
+ for (key = num_keys; key < _max_keys; key++) {
194
+ if (_offset_by_key[key] != 0 ) {
195
+ return ;
196
+ }
197
+ }
198
+ }
199
+
200
+ old_max_keys = _max_keys;
175
201
_max_keys = num_keys;
176
- // User is allowed to change number of keys. As this affects init, need to deinitialize now.
177
- // Don't call init right away - it is lazily called by get/set functions if needed.
178
- deinit ();
202
+
203
+ // Invoke GC to write new max_keys to master record
204
+ garbage_collection (no_key, 0 , 0 , 0 , NULL , std::min (_max_keys, old_max_keys));
205
+
206
+ // Reallocate _offset_by_key with new size
207
+ if (_max_keys != old_max_keys) {
208
+ // Reallocate _offset_by_key with new size
209
+ uint32_t *old_offset_by_key = (uint32_t *) _offset_by_key;
210
+ uint32_t *new_offset_by_key = new uint32_t [_max_keys];
211
+ MBED_ASSERT (new_offset_by_key);
212
+
213
+ // Copy old content to new table
214
+ memset (new_offset_by_key, 0 , sizeof (uint32_t ) * _max_keys);
215
+ memcpy (new_offset_by_key, old_offset_by_key, sizeof (uint32_t ) * std::min (_max_keys, old_max_keys));
216
+
217
+ _offset_by_key = new_offset_by_key;
218
+ delete[] old_offset_by_key;
219
+ }
220
+
221
+ _mutex->unlock ();
179
222
}
180
223
181
224
int NVStore::flash_read_area (uint8_t area, uint32_t offset, uint32_t size, void *buf)
@@ -444,8 +487,8 @@ int NVStore::write_master_record(uint8_t area, uint16_t version, uint32_t &next_
444
487
master_record_data_t master_rec;
445
488
446
489
master_rec.version = version;
447
- master_rec.reserved1 = 0 ;
448
- master_rec.reserved2 = 0 ;
490
+ master_rec.max_keys = _max_keys ;
491
+ master_rec.reserved = 0 ;
449
492
return write_record (area, 0 , master_record_key, 0 , 0 , sizeof (master_rec),
450
493
&master_rec, next_offset);
451
494
}
@@ -518,7 +561,7 @@ int NVStore::copy_record(uint8_t from_area, uint32_t from_offset, uint32_t to_of
518
561
return NVSTORE_SUCCESS;
519
562
}
520
563
521
- int NVStore::garbage_collection (uint16_t key, uint16_t flags, uint8_t owner, uint16_t buf_size, const void *buf)
564
+ int NVStore::garbage_collection (uint16_t key, uint16_t flags, uint8_t owner, uint16_t buf_size, const void *buf, uint16_t num_keys )
522
565
{
523
566
uint32_t curr_offset, new_area_offset, next_offset, curr_owner;
524
567
int ret;
@@ -542,7 +585,7 @@ int NVStore::garbage_collection(uint16_t key, uint16_t flags, uint8_t owner, uin
542
585
543
586
// Now iterate on all types, and copy the ones who have valid offsets (meaning that they exist)
544
587
// to the other area.
545
- for (key = 0 ; key < _max_keys ; key++) {
588
+ for (key = 0 ; key < num_keys ; key++) {
546
589
curr_offset = _offset_by_key[key];
547
590
uint16_t save_flags = curr_offset & offs_by_key_flag_mask & ~offs_by_key_area_mask;
548
591
curr_area = (uint8_t )(curr_offset >> offs_by_key_area_bit_pos) & 1 ;
@@ -579,7 +622,6 @@ int NVStore::garbage_collection(uint16_t key, uint16_t flags, uint8_t owner, uin
579
622
return ret;
580
623
}
581
624
582
-
583
625
int NVStore::do_get (uint16_t key, uint16_t buf_size, void *buf, uint16_t &actual_size,
584
626
int validate_only)
585
627
{
@@ -684,7 +726,7 @@ int NVStore::do_set(uint16_t key, uint16_t buf_size, const void *buf, uint16_t f
684
726
685
727
// If we cross the area limit, we need to invoke GC.
686
728
if (new_free_space >= _size) {
687
- ret = garbage_collection (key, flags, owner, buf_size, buf);
729
+ ret = garbage_collection (key, flags, owner, buf_size, buf, _max_keys );
688
730
_mutex->unlock ();
689
731
return ret;
690
732
}
@@ -800,6 +842,7 @@ int NVStore::init()
800
842
uint16_t key;
801
843
uint16_t flags;
802
844
uint16_t versions[NVSTORE_NUM_AREAS];
845
+ uint16_t keys[NVSTORE_NUM_AREAS];
803
846
uint16_t actual_size;
804
847
uint8_t owner;
805
848
@@ -818,13 +861,6 @@ int NVStore::init()
818
861
return NVSTORE_SUCCESS;
819
862
}
820
863
821
- _offset_by_key = new uint32_t [_max_keys];
822
- MBED_ASSERT (_offset_by_key);
823
-
824
- for (key = 0 ; key < _max_keys; key++) {
825
- _offset_by_key[key] = 0 ;
826
- }
827
-
828
864
_mutex = new PlatformMutex;
829
865
MBED_ASSERT (_mutex);
830
866
@@ -841,10 +877,12 @@ int NVStore::init()
841
877
842
878
calc_validate_area_params ();
843
879
880
+ // retrieve max keys from master record
844
881
for (uint8_t area = 0 ; area < NVSTORE_NUM_AREAS; area++) {
845
882
area_state[area] = NVSTORE_AREA_STATE_NONE;
846
883
free_space_offset_of_area[area] = 0 ;
847
884
versions[area] = 0 ;
885
+ keys[area] = 0 ;
848
886
849
887
_size = std::min (_size, _flash_area_params[area].size );
850
888
@@ -878,6 +916,7 @@ int NVStore::init()
878
916
continue ;
879
917
}
880
918
versions[area] = master_rec.version ;
919
+ keys[area] = master_rec.max_keys ;
881
920
882
921
// Place _free_space_offset after the master record (for the traversal,
883
922
// which takes place after this loop).
@@ -888,6 +927,17 @@ int NVStore::init()
888
927
// that we found our active area.
889
928
_active_area = area;
890
929
_active_area_version = versions[area];
930
+ if (!keys[area]) {
931
+ keys[area] = NVSTORE_NUM_PREDEFINED_KEYS;
932
+ }
933
+ _max_keys = keys[area];
934
+ }
935
+
936
+ _offset_by_key = new uint32_t [_max_keys];
937
+ MBED_ASSERT (_offset_by_key);
938
+
939
+ for (key = 0 ; key < _max_keys; key++) {
940
+ _offset_by_key[key] = 0 ;
891
941
}
892
942
893
943
// In case we have two empty areas, arbitrarily assign 0 to the active one.
@@ -920,9 +970,9 @@ int NVStore::init()
920
970
MBED_ASSERT (ret == NVSTORE_SUCCESS);
921
971
922
972
// In case we have a faulty record, this probably means that the system crashed when written.
923
- // Perform a garbage collection, to make the the other area valid.
973
+ // Perform a garbage collection, to make the other area valid.
924
974
if (!valid) {
925
- ret = garbage_collection (no_key, 0 , 0 , 0 , NULL );
975
+ ret = garbage_collection (no_key, 0 , 0 , 0 , NULL , _max_keys );
926
976
break ;
927
977
}
928
978
if (flags & delete_item_flag) {
0 commit comments