@@ -68,7 +68,8 @@ typedef struct {
68
68
69
69
typedef enum {
70
70
TDBSTORE_AREA_STATE_NONE = 0 ,
71
- TDBSTORE_AREA_STATE_EMPTY,
71
+ TDBSTORE_AREA_STATE_ERASED,
72
+ TDBSTORE_AREA_STATE_INVALID,
72
73
TDBSTORE_AREA_STATE_VALID,
73
74
} area_state_e;
74
75
@@ -848,6 +849,7 @@ int TDBStore::garbage_collection()
848
849
int ret;
849
850
size_t ind;
850
851
852
+ // Reset the standby area
851
853
ret = reset_area (1 - _active_area);
852
854
if (ret) {
853
855
return ret;
@@ -883,12 +885,6 @@ int TDBStore::garbage_collection()
883
885
return ret;
884
886
}
885
887
886
- // Now reset standby area
887
- ret = reset_area (1 - _active_area);
888
- if (ret) {
889
- return ret;
890
- }
891
-
892
888
return MBED_SUCCESS;
893
889
}
894
890
@@ -985,7 +981,7 @@ int TDBStore::init()
985
981
uint32_t next_offset;
986
982
uint32_t flags, hash;
987
983
uint32_t actual_data_size;
988
- int os_ret, ret = MBED_SUCCESS, reserved_ret ;
984
+ int os_ret, ret = MBED_SUCCESS;
989
985
uint16_t versions[_num_areas];
990
986
991
987
_mutex.lock ();
@@ -1053,13 +1049,9 @@ int TDBStore::init()
1053
1049
MBED_ERROR (ret, " TDBSTORE: Unable to read record at init" );
1054
1050
}
1055
1051
1056
- // Master record may be either corrupt or erased - either way erase it
1057
- // (this will do nothing if already erased)
1052
+ // Master record may be either corrupt or erased
1058
1053
if (ret == MBED_ERROR_INVALID_DATA_DETECTED) {
1059
- if (reset_area (area)) {
1060
- MBED_ERROR (MBED_ERROR_READ_FAILED, " TDBSTORE: Unable to reset area at init" );
1061
- }
1062
- area_state[area] = TDBSTORE_AREA_STATE_EMPTY;
1054
+ area_state[area] = TDBSTORE_AREA_STATE_INVALID;
1063
1055
continue ;
1064
1056
}
1065
1057
@@ -1074,9 +1066,11 @@ int TDBStore::init()
1074
1066
}
1075
1067
1076
1068
// In case we have two empty areas, arbitrarily use area 0 as the active one.
1077
- if ((area_state[0 ] == TDBSTORE_AREA_STATE_EMPTY) && (area_state[1 ] == TDBSTORE_AREA_STATE_EMPTY)) {
1069
+ if ((area_state[0 ] == TDBSTORE_AREA_STATE_INVALID) && (area_state[1 ] == TDBSTORE_AREA_STATE_INVALID)) {
1070
+ reset_area (0 );
1078
1071
_active_area = 0 ;
1079
1072
_active_area_version = 1 ;
1073
+ area_state[0 ] = TDBSTORE_AREA_STATE_ERASED;
1080
1074
ret = write_master_record (_active_area, _active_area_version, _free_space_offset);
1081
1075
if (ret) {
1082
1076
MBED_ERROR (ret, " TDBSTORE: Unable to write master record at init" );
@@ -1086,58 +1080,31 @@ int TDBStore::init()
1086
1080
}
1087
1081
1088
1082
// In case we have two valid areas, choose the one having the higher version (or 0
1089
- // in case of wrap around). Reset the other one.
1083
+ // in case of wrap around).
1090
1084
if ((area_state[0 ] == TDBSTORE_AREA_STATE_VALID) && (area_state[1 ] == TDBSTORE_AREA_STATE_VALID)) {
1091
1085
if ((versions[0 ] > versions[1 ]) || (!versions[0 ])) {
1092
1086
_active_area = 0 ;
1093
1087
} else {
1094
1088
_active_area = 1 ;
1095
1089
}
1096
1090
_active_area_version = versions[_active_area];
1097
- ret = reset_area (1 - _active_area);
1098
- if (ret) {
1099
- MBED_ERROR (ret, " TDBSTORE: Unable to reset area at init" );
1100
- }
1101
1091
}
1102
1092
1103
1093
// Currently set free space offset pointer to the end of free space.
1104
1094
// Ram table build process needs it, but will update it.
1105
1095
_free_space_offset = _size;
1106
1096
ret = build_ram_table ();
1107
1097
1098
+ // build_ram_table() scans all keys, until invalid data found.
1099
+ // Therefore INVALID_DATA is not considered error.
1108
1100
if ((ret != MBED_SUCCESS) && (ret != MBED_ERROR_INVALID_DATA_DETECTED)) {
1109
- MBED_ERROR (ret, " TDBSTORE: Unable to build RAM table at init" );
1110
- }
1111
-
1112
- if ((ret == MBED_ERROR_INVALID_DATA_DETECTED) && (_free_space_offset < _size)) {
1113
- // Space after last valid record may be erased, hence "corrupt". Now check if it really is erased.
1114
- bool erased;
1115
- if (is_erase_unit_erased (_active_area, _free_space_offset, erased)) {
1116
- MBED_ERROR (MBED_ERROR_READ_FAILED, " TDBSTORE: Unable to check whether erase unit is erased at init" );
1117
- }
1118
- if (erased) {
1119
- // Erased - all good
1120
- ret = MBED_SUCCESS;
1121
- }
1122
- }
1123
-
1124
- // If we either have a corrupt record somewhere
1125
- // perform garbage collection to salvage all preceding records.
1126
- if ((ret == MBED_ERROR_INVALID_DATA_DETECTED)) {
1127
- ret = garbage_collection ();
1128
- if (ret) {
1129
- MBED_ERROR (ret, " TDBSTORE: Unable to perform GC at init" );
1130
- }
1131
- os_ret = _buff_bd->sync ();
1132
- if (os_ret) {
1133
- MBED_ERROR (MBED_ERROR_WRITE_FAILED, " TDBSTORE: Unable to sync BD at init" );
1134
- }
1101
+ goto fail;
1135
1102
}
1136
1103
1137
1104
end:
1138
1105
_is_initialized = true ;
1139
1106
_mutex.unlock ();
1140
- return ret ;
1107
+ return MBED_SUCCESS ;
1141
1108
fail:
1142
1109
delete[] ram_table;
1143
1110
delete _buff_bd;
@@ -1367,6 +1334,13 @@ int TDBStore::reserved_data_set(const void *reserved_data, size_t reserved_data_
1367
1334
trailer.data_size = reserved_data_buf_size;
1368
1335
trailer.crc = calc_crc (initial_crc, reserved_data_buf_size, reserved_data);
1369
1336
1337
+ // Erase the header of non-active area, just to make sure that we can write to it
1338
+ // In case garbage collection has not yet been run, the area can be un-erased
1339
+ ret = reset_area (1 - _active_area);
1340
+ if (ret) {
1341
+ goto end;
1342
+ }
1343
+
1370
1344
/*
1371
1345
* Write to both areas
1372
1346
* Both must success, as they are required to be erased when TDBStore initializes
@@ -1470,35 +1444,10 @@ void TDBStore::offset_in_erase_unit(uint8_t area, uint32_t offset,
1470
1444
dist_to_end = _buff_bd->get_erase_size (agg_offset) - offset_from_start;
1471
1445
}
1472
1446
1473
- int TDBStore::is_erase_unit_erased (uint8_t area, uint32_t offset, bool &erased)
1474
- {
1475
- uint32_t offset_from_start, dist;
1476
- offset_in_erase_unit (area, offset, offset_from_start, dist);
1477
- uint8_t buf[sizeof (record_header_t )], blanks[sizeof (record_header_t )];
1478
- memset (blanks, _buff_bd->get_erase_value (), sizeof (blanks));
1479
-
1480
- while (dist) {
1481
- uint32_t chunk = std::min (dist, (uint32_t ) sizeof (buf));
1482
- int ret = read_area (area, offset, chunk, buf);
1483
- if (ret) {
1484
- return MBED_ERROR_READ_FAILED;
1485
- }
1486
- if (memcmp (buf, blanks, chunk)) {
1487
- erased = false ;
1488
- return MBED_SUCCESS;
1489
- }
1490
- offset += chunk;
1491
- dist -= chunk;
1492
- }
1493
- erased = true ;
1494
- return MBED_SUCCESS;
1495
- }
1496
-
1497
1447
int TDBStore::check_erase_before_write (uint8_t area, uint32_t offset, uint32_t size, bool force_check)
1498
1448
{
1499
1449
// In order to save init time, we don't check that the entire area is erased.
1500
1450
// Instead, whenever reaching an erase unit start erase it.
1501
-
1502
1451
while (size) {
1503
1452
uint32_t dist, offset_from_start;
1504
1453
int ret;
@@ -1516,4 +1465,3 @@ int TDBStore::check_erase_before_write(uint8_t area, uint32_t offset, uint32_t s
1516
1465
}
1517
1466
return MBED_SUCCESS;
1518
1467
}
1519
-
0 commit comments