From b46da659375fd790ba76a7674f17cb5da9190ce1 Mon Sep 17 00:00:00 2001 From: Kyle Kearney Date: Wed, 8 Apr 2020 16:42:46 -0700 Subject: [PATCH] TDBStore: Handle odd number of sectors in block Rework TDBStore::calc_area_params so that it can handle situations where the block device size is not an even multiple of the sector size (while retaining its ability to handle non-uniform erase sizes). This avoids intermittent asserts on boards where TDBStore is implemented in internal flash, in which case the size of the block device varies with the application size and a minor change (or a shift in optimization level) can shift TDBStore from an odd to an even number of sectors. --- .../storage/kvstore/tdbstore/TDBStore.cpp | 25 ++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/features/storage/kvstore/tdbstore/TDBStore.cpp b/features/storage/kvstore/tdbstore/TDBStore.cpp index fd7d8ce3c0..e81b2cd2f1 100644 --- a/features/storage/kvstore/tdbstore/TDBStore.cpp +++ b/features/storage/kvstore/tdbstore/TDBStore.cpp @@ -200,16 +200,35 @@ void TDBStore::calc_area_params() memset(_area_params, 0, sizeof(_area_params)); size_t area_0_size = 0; + size_t area_1_size = 0; - while (area_0_size < bd_size / 2) { + // The size calculations are a bit complex because we need to make sure we're + // always aligned to an erase block boundary (whose size may not be uniform + // across the address space), and we also need to make sure that the first + // area never goes over half of the total size even if bd_size is an odd + // number of sectors. + while (true) { bd_size_t erase_unit_size = _bd->get_erase_size(area_0_size); - area_0_size += erase_unit_size; + if (area_0_size + erase_unit_size <= (bd_size / 2)) { + area_0_size += erase_unit_size; + } else { + break; + } + } + + while (true) { + bd_size_t erase_unit_size = _bd->get_erase_size(area_0_size + area_1_size); + if (area_1_size + erase_unit_size <= (bd_size / 2)) { + area_1_size += erase_unit_size; + } else { + break; + } } _area_params[0].address = 0; _area_params[0].size = area_0_size; _area_params[1].address = area_0_size; - _area_params[1].size = bd_size - area_0_size; + _area_params[1].size = area_1_size; // The areas must be of same size MBED_ASSERT(_area_params[0].size == _area_params[1].size);