@@ -170,24 +170,28 @@ int TDBStore::write_area(uint8_t area, uint32_t offset, uint32_t size, const voi
170
170
return MBED_SUCCESS;
171
171
}
172
172
173
- int TDBStore::erase_erase_unit (uint8_t area, uint32_t offset)
173
+ int TDBStore::erase_area (uint8_t area, uint32_t offset, uint32_t size )
174
174
{
175
175
uint32_t bd_offset = _area_params[area].address + offset;
176
- uint32_t eu_size = _buff_bd->get_erase_size (bd_offset);
177
176
178
177
if (_buff_bd->get_erase_value () != -1 ) {
179
- return _buff_bd->erase (bd_offset, eu_size );
178
+ return _buff_bd->erase (bd_offset, size );
180
179
} else {
181
- // We need to simulate erase, as our block device
182
- // does not do it. We can do this one byte at a time
183
- // because we use BufferedBlockDevice that has page buffers
184
- uint8_t val = 0xff ;
185
- int ret;
186
- for (; eu_size; --eu_size) {
187
- ret = _buff_bd->program (&val, bd_offset++, 1 );
180
+ // We need to simulate erase to wipe records, as our block device
181
+ // may not do it. Program in chunks of _work_buf_size if the minimum
182
+ // program size is too small (e.g. one-byte) to avoid performance
183
+ // issues.
184
+ MBED_ASSERT (_work_buf != nullptr );
185
+ MBED_ASSERT (_work_buf_size != 0 );
186
+ memset (_work_buf, 0xFF , _work_buf_size);
187
+ while (size) {
188
+ uint32_t chunk = std::min<uint32_t >(_work_buf_size, size);
189
+ int ret = _buff_bd->program (_work_buf, bd_offset, chunk);
188
190
if (ret) {
189
191
return ret;
190
192
}
193
+ size -= chunk;
194
+ bd_offset += chunk;
191
195
}
192
196
}
193
197
return MBED_SUCCESS;
@@ -1458,33 +1462,47 @@ void TDBStore::offset_in_erase_unit(uint8_t area, uint32_t offset,
1458
1462
uint32_t &offset_from_start, uint32_t &dist_to_end)
1459
1463
{
1460
1464
uint32_t bd_offset = _area_params[area].address + offset;
1461
- uint32_t agg_offset = 0 ;
1462
1465
1463
- while (bd_offset >= agg_offset + _buff_bd->get_erase_size (agg_offset)) {
1464
- agg_offset += _buff_bd->get_erase_size (agg_offset);
1465
- }
1466
- offset_from_start = bd_offset - agg_offset;
1467
- dist_to_end = _buff_bd->get_erase_size (agg_offset) - offset_from_start;
1466
+ // The parameter of `BlockDevice::get_erase_size(bd_addr_t addr)`
1467
+ // does not need to be aligned.
1468
+ uint32_t erase_unit = _buff_bd->get_erase_size (bd_offset);
1469
+
1470
+ // Even on a flash device with multiple regions, the start address of
1471
+ // an erase unit is aligned to the current region's unit size.
1472
+ offset_from_start = bd_offset % erase_unit;
1473
+ dist_to_end = erase_unit - offset_from_start;
1468
1474
}
1469
1475
1470
1476
int TDBStore::check_erase_before_write (uint8_t area, uint32_t offset, uint32_t size, bool force_check)
1471
1477
{
1472
1478
// In order to save init time, we don't check that the entire area is erased.
1473
1479
// Instead, whenever reaching an erase unit start erase it.
1480
+ bool erase = false ;
1481
+ uint32_t start_offset;
1482
+ uint32_t end_offset;
1474
1483
while (size) {
1475
1484
uint32_t dist, offset_from_start;
1476
1485
int ret;
1477
1486
offset_in_erase_unit (area, offset, offset_from_start, dist);
1478
1487
uint32_t chunk = std::min (size, dist);
1479
1488
1480
1489
if (offset_from_start == 0 || force_check) {
1481
- ret = erase_erase_unit (area, offset - offset_from_start);
1482
- if (ret != MBED_SUCCESS) {
1483
- return MBED_ERROR_WRITE_FAILED ;
1490
+ if (!erase) {
1491
+ erase = true ;
1492
+ start_offset = offset - offset_from_start ;
1484
1493
}
1494
+ end_offset = offset + dist;
1485
1495
}
1486
1496
offset += chunk;
1487
1497
size -= chunk;
1488
1498
}
1499
+
1500
+ if (erase) {
1501
+ int ret = erase_area (area, start_offset, end_offset - start_offset);
1502
+ if (ret != MBED_SUCCESS) {
1503
+ return MBED_ERROR_WRITE_FAILED;
1504
+ }
1505
+ }
1506
+
1489
1507
return MBED_SUCCESS;
1490
1508
}
0 commit comments