@@ -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
@@ -836,6 +837,7 @@ int TDBStore::garbage_collection()
836
837
int ret;
837
838
size_t ind;
838
839
840
+ // Reset the standby area
839
841
ret = reset_area (1 - _active_area);
840
842
if (ret) {
841
843
return ret;
@@ -871,12 +873,6 @@ int TDBStore::garbage_collection()
871
873
return ret;
872
874
}
873
875
874
- // Now reset standby area
875
- ret = reset_area (1 - _active_area);
876
- if (ret) {
877
- return ret;
878
- }
879
-
880
876
return MBED_SUCCESS;
881
877
}
882
878
@@ -972,7 +968,7 @@ int TDBStore::init()
972
968
uint32_t next_offset;
973
969
uint32_t flags, hash;
974
970
uint32_t actual_data_size;
975
- int os_ret, ret = MBED_SUCCESS, reserved_ret ;
971
+ int os_ret, ret = MBED_SUCCESS;
976
972
uint16_t versions[_num_areas];
977
973
978
974
_mutex.lock ();
@@ -1039,13 +1035,9 @@ int TDBStore::init()
1039
1035
MBED_ERROR (ret, " TDBSTORE: Unable to read record at init" );
1040
1036
}
1041
1037
1042
- // Master record may be either corrupt or erased - either way erase it
1043
- // (this will do nothing if already erased)
1038
+ // Master record may be either corrupt or erased
1044
1039
if (ret == MBED_ERROR_INVALID_DATA_DETECTED) {
1045
- if (reset_area (area)) {
1046
- MBED_ERROR (MBED_ERROR_READ_FAILED, " TDBSTORE: Unable to reset area at init" );
1047
- }
1048
- area_state[area] = TDBSTORE_AREA_STATE_EMPTY;
1040
+ area_state[area] = TDBSTORE_AREA_STATE_INVALID;
1049
1041
continue ;
1050
1042
}
1051
1043
@@ -1060,9 +1052,11 @@ int TDBStore::init()
1060
1052
}
1061
1053
1062
1054
// In case we have two empty areas, arbitrarily use area 0 as the active one.
1063
- if ((area_state[0 ] == TDBSTORE_AREA_STATE_EMPTY) && (area_state[1 ] == TDBSTORE_AREA_STATE_EMPTY)) {
1055
+ if ((area_state[0 ] == TDBSTORE_AREA_STATE_INVALID) && (area_state[1 ] == TDBSTORE_AREA_STATE_INVALID)) {
1056
+ reset_area (0 );
1064
1057
_active_area = 0 ;
1065
1058
_active_area_version = 1 ;
1059
+ area_state[0 ] = TDBSTORE_AREA_STATE_ERASED;
1066
1060
ret = write_master_record (_active_area, _active_area_version, _free_space_offset);
1067
1061
if (ret) {
1068
1062
MBED_ERROR (ret, " TDBSTORE: Unable to write master record at init" );
@@ -1072,58 +1066,31 @@ int TDBStore::init()
1072
1066
}
1073
1067
1074
1068
// In case we have two valid areas, choose the one having the higher version (or 0
1075
- // in case of wrap around). Reset the other one.
1069
+ // in case of wrap around).
1076
1070
if ((area_state[0 ] == TDBSTORE_AREA_STATE_VALID) && (area_state[1 ] == TDBSTORE_AREA_STATE_VALID)) {
1077
1071
if ((versions[0 ] > versions[1 ]) || (!versions[0 ])) {
1078
1072
_active_area = 0 ;
1079
1073
} else {
1080
1074
_active_area = 1 ;
1081
1075
}
1082
1076
_active_area_version = versions[_active_area];
1083
- ret = reset_area (1 - _active_area);
1084
- if (ret) {
1085
- MBED_ERROR (ret, " TDBSTORE: Unable to reset area at init" );
1086
- }
1087
1077
}
1088
1078
1089
1079
// Currently set free space offset pointer to the end of free space.
1090
1080
// Ram table build process needs it, but will update it.
1091
1081
_free_space_offset = _size;
1092
1082
ret = build_ram_table ();
1093
1083
1084
+ // build_ram_table() scans all keys, until invalid data found.
1085
+ // Therefore INVALID_DATA is not considered error.
1094
1086
if ((ret != MBED_SUCCESS) && (ret != MBED_ERROR_INVALID_DATA_DETECTED)) {
1095
- MBED_ERROR (ret, " TDBSTORE: Unable to build RAM table at init" );
1096
- }
1097
-
1098
- if ((ret == MBED_ERROR_INVALID_DATA_DETECTED) && (_free_space_offset < _size)) {
1099
- // Space after last valid record may be erased, hence "corrupt". Now check if it really is erased.
1100
- bool erased;
1101
- if (is_erase_unit_erased (_active_area, _free_space_offset, erased)) {
1102
- MBED_ERROR (MBED_ERROR_READ_FAILED, " TDBSTORE: Unable to check whether erase unit is erased at init" );
1103
- }
1104
- if (erased) {
1105
- // Erased - all good
1106
- ret = MBED_SUCCESS;
1107
- }
1108
- }
1109
-
1110
- // If we either have a corrupt record somewhere
1111
- // perform garbage collection to salvage all preceding records.
1112
- if ((ret == MBED_ERROR_INVALID_DATA_DETECTED)) {
1113
- ret = garbage_collection ();
1114
- if (ret) {
1115
- MBED_ERROR (ret, " TDBSTORE: Unable to perform GC at init" );
1116
- }
1117
- os_ret = _buff_bd->sync ();
1118
- if (os_ret) {
1119
- MBED_ERROR (MBED_ERROR_WRITE_FAILED, " TDBSTORE: Unable to sync BD at init" );
1120
- }
1087
+ goto fail;
1121
1088
}
1122
1089
1123
1090
end:
1124
1091
_is_initialized = true ;
1125
1092
_mutex.unlock ();
1126
- return ret ;
1093
+ return MBED_SUCCESS ;
1127
1094
fail:
1128
1095
delete[] ram_table;
1129
1096
delete _buff_bd;
@@ -1353,6 +1320,13 @@ int TDBStore::reserved_data_set(const void *reserved_data, size_t reserved_data_
1353
1320
trailer.data_size = reserved_data_buf_size;
1354
1321
trailer.crc = calc_crc (initial_crc, reserved_data_buf_size, reserved_data);
1355
1322
1323
+ // Erase the header of non-active area, just to make sure that we can write to it
1324
+ // In case garbage collection has not yet been run, the area can be un-erased
1325
+ ret = reset_area (1 - _active_area);
1326
+ if (ret) {
1327
+ goto end;
1328
+ }
1329
+
1356
1330
/*
1357
1331
* Write to both areas
1358
1332
* Both must success, as they are required to be erased when TDBStore initializes
@@ -1456,35 +1430,10 @@ void TDBStore::offset_in_erase_unit(uint8_t area, uint32_t offset,
1456
1430
dist_to_end = _buff_bd->get_erase_size (agg_offset) - offset_from_start;
1457
1431
}
1458
1432
1459
- int TDBStore::is_erase_unit_erased (uint8_t area, uint32_t offset, bool &erased)
1460
- {
1461
- uint32_t offset_from_start, dist;
1462
- offset_in_erase_unit (area, offset, offset_from_start, dist);
1463
- uint8_t buf[sizeof (record_header_t )], blanks[sizeof (record_header_t )];
1464
- memset (blanks, _buff_bd->get_erase_value (), sizeof (blanks));
1465
-
1466
- while (dist) {
1467
- uint32_t chunk = std::min (dist, (uint32_t ) sizeof (buf));
1468
- int ret = read_area (area, offset, chunk, buf);
1469
- if (ret) {
1470
- return MBED_ERROR_READ_FAILED;
1471
- }
1472
- if (memcmp (buf, blanks, chunk)) {
1473
- erased = false ;
1474
- return MBED_SUCCESS;
1475
- }
1476
- offset += chunk;
1477
- dist -= chunk;
1478
- }
1479
- erased = true ;
1480
- return MBED_SUCCESS;
1481
- }
1482
-
1483
1433
int TDBStore::check_erase_before_write (uint8_t area, uint32_t offset, uint32_t size, bool force_check)
1484
1434
{
1485
1435
// In order to save init time, we don't check that the entire area is erased.
1486
1436
// Instead, whenever reaching an erase unit start erase it.
1487
-
1488
1437
while (size) {
1489
1438
uint32_t dist, offset_from_start;
1490
1439
int ret;
@@ -1502,4 +1451,3 @@ int TDBStore::check_erase_before_write(uint8_t area, uint32_t offset, uint32_t s
1502
1451
}
1503
1452
return MBED_SUCCESS;
1504
1453
}
1505
-
0 commit comments