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