From 7f18a6ce491fc859aabd6530d984b2e6876420ef Mon Sep 17 00:00:00 2001 From: Kyle Kearney Date: Mon, 2 Mar 2020 16:34:01 -0800 Subject: [PATCH] Move flash bounds helpers from TDBStore to kv_config --- .../direct_access_devicekey_test/main.cpp | 2 +- features/storage/kvstore/conf/kv_config.cpp | 148 +++++++++++++++++- features/storage/kvstore/conf/kv_config.h | 28 ++++ .../DirectAccessDevicekey.cpp | 5 +- .../storage/kvstore/tdbstore/TDBStore.cpp | 129 --------------- features/storage/kvstore/tdbstore/TDBStore.h | 33 ---- 6 files changed, 173 insertions(+), 172 deletions(-) diff --git a/features/storage/TESTS/kvstore/direct_access_devicekey_test/main.cpp b/features/storage/TESTS/kvstore/direct_access_devicekey_test/main.cpp index e58983716b..869e335f0b 100644 --- a/features/storage/TESTS/kvstore/direct_access_devicekey_test/main.cpp +++ b/features/storage/TESTS/kvstore/direct_access_devicekey_test/main.cpp @@ -94,7 +94,7 @@ int get_virtual_TDBStore_position(uint32_t conf_start_address, uint32_t conf_si } else { bd_addr_t default_start; bd_size_t default_size; - TDBStore::get_default_flash_addresses(&default_start, &default_size); + kv_get_default_flash_addresses(&default_start, &default_size); aligned_start_address = (uint32_t)default_start; bd_final_size = (uint32_t)default_size; } diff --git a/features/storage/kvstore/conf/kv_config.cpp b/features/storage/kvstore/conf/kv_config.cpp index 0cc1f292b3..c6c3c79db6 100644 --- a/features/storage/kvstore/conf/kv_config.cpp +++ b/features/storage/kvstore/conf/kv_config.cpp @@ -150,6 +150,12 @@ static const char *filesystemstore_folder_path = NULL; using namespace mbed; +// Use the last 2 sectors or 14 pages of flash for the TDBStore by default (whichever is larger) +// For each area: must be a minimum of 1 page of reserved and 2 pages for master record +/** Minimum number of internal flash sectors required for TDBStore */ +static const int STORE_SECTORS = 2; +/** Minimum number of internal flash pages required for TDBStore */ +static const int STORE_PAGES = 14; static SingletonPtr mutex; static bool is_kv_config_initialize = false; @@ -183,13 +189,13 @@ int _calculate_blocksize_match_tdbstore(BlockDevice *bd) bd_size_t page_size = bd->get_program_size(); bd_size_t number_of_sector = size / erase_size; bd_size_t number_of_page = size / page_size; - if (number_of_sector < TDBStore::STORE_SECTORS) { - tr_error("KV Config: There are less than %d sectors - TDBStore will not work.", TDBStore::STORE_SECTORS); + if (number_of_sector < STORE_SECTORS) { + tr_error("KV Config: There are less than %d sectors - TDBStore will not work.", STORE_SECTORS); return -1; } - if (number_of_page < TDBStore::STORE_PAGES) { - tr_error("KV Config: There are less than %d pages - TDBStore will not work.", TDBStore::STORE_PAGES); + if (number_of_page < STORE_PAGES) { + tr_error("KV Config: There are less than %d pages - TDBStore will not work.", STORE_PAGES); return -1; } @@ -279,7 +285,7 @@ FileSystem *_get_filesystem_default(const char *mount) BlockDevice *_get_blockdevice_FLASHIAP(bd_addr_t start_address, bd_size_t size) { #if COMPONENT_FLASHIAP - int ret = TDBStore::get_flash_bounds_from_config(&start_address, &size); + int ret = kv_get_flash_bounds_from_config(&start_address, &size); if (ret != 0) { tr_error("KV Config: Determination of internal block device bounds failed. The configured start address/size is likely invalid."); return NULL; @@ -572,7 +578,7 @@ int _create_internal_tdb(BlockDevice **internal_bd, KVStore **internal_tdb, bd_s //Get the default address and size for the TDBStore if (size == 0 && start_address == 0) { //Calculate the block device size and start address in case default values are used. - ret = TDBStore::get_default_flash_addresses(&start_address, &size); + ret = kv_get_default_flash_addresses(&start_address, &size); if (ret != MBED_SUCCESS) { return MBED_ERROR_FAILED_OPERATION; } @@ -594,7 +600,7 @@ int _create_internal_tdb(BlockDevice **internal_bd, KVStore **internal_tdb, bd_s //Check if TDBStore has at least 2 sectors or 14 pages. if (_calculate_blocksize_match_tdbstore(*internal_bd) != MBED_SUCCESS) { - tr_error("KV Config: Can not create TDBStore with less then %d sectors or %d pages.", TDBStore::STORE_SECTORS, TDBStore::STORE_PAGES); + tr_error("KV Config: Can not create TDBStore with less then %d sectors or %d pages.", STORE_SECTORS, STORE_PAGES); return MBED_ERROR_INVALID_ARGUMENT; } @@ -991,3 +997,131 @@ exit: mutex->unlock(); return ret; } + +int kv_get_default_flash_addresses(bd_addr_t *start_address, bd_size_t *size) +{ + int ret = MBED_SUCCESS; + +#if COMPONENT_FLASHIAP + FlashIAP flash; + if (flash.init() != 0) { + return MBED_ERROR_INITIALIZATION_FAILED; + } + + // Let's work from end of the flash backwards + bd_addr_t end_of_flash = flash.get_flash_start() + flash.get_flash_size(); + bd_addr_t curr_addr = end_of_flash; + bd_size_t sector_space = 0; + + for (int i = STORE_SECTORS; i; i--) { + bd_size_t sector_size = flash.get_sector_size(curr_addr - 1); + sector_space += sector_size; + } + + bd_size_t page_space = flash.get_page_size() * STORE_PAGES; + if (sector_space > page_space) { + curr_addr -= sector_space; + *size = sector_space; + } else { + curr_addr -= page_space; + // Align to 2 sector boundary so that garbage collection works properly + curr_addr = align_down(curr_addr, 2 * flash.get_sector_size(curr_addr)); + *size = end_of_flash - curr_addr; + } + + // Store- and application-sectors mustn't overlap + uint32_t first_wrtbl_sector_addr = + (uint32_t)(align_up(FLASHIAP_APP_ROM_END_ADDR, flash.get_sector_size(FLASHIAP_APP_ROM_END_ADDR))); + + MBED_ASSERT(curr_addr >= first_wrtbl_sector_addr); + if (curr_addr < first_wrtbl_sector_addr) { + ret = MBED_ERROR_MEDIA_FULL; + } else { + *start_address = curr_addr; + } + + flash.deinit(); +#endif + + return ret; +} + +int kv_get_flash_bounds_from_config(bd_addr_t *start_address, bd_size_t *size) +{ +#if COMPONENT_FLASHIAP + + bd_addr_t flash_end_address; + bd_addr_t flash_start_address; + bd_addr_t flash_first_writable_sector_address; + bd_addr_t aligned_start_address; + bd_addr_t aligned_end_address; + bd_addr_t end_address; + FlashIAP flash; + + if (!start_address || !size) { + return MBED_ERROR_INVALID_ARGUMENT; + } + + int ret = flash.init(); + if (ret != 0) { + return MBED_ERROR_INITIALIZATION_FAILED; + } + + // Get flash parameters + flash_first_writable_sector_address = align_up(FLASHIAP_APP_ROM_END_ADDR, flash.get_sector_size(FLASHIAP_APP_ROM_END_ADDR)); + flash_start_address = flash.get_flash_start(); + flash_end_address = flash_start_address + flash.get_flash_size(); + + if (*start_address == 0) { + if (*size == 0) { + //The block device will have all space from start address to the end of the flash + *size = flash.get_flash_size(); + } + + *start_address = flash_end_address - *size; + aligned_start_address = align_down(*start_address, flash.get_sector_size(*start_address)); + if (*start_address != aligned_start_address) { + // Start address not aligned - size should likely be changed so that it is + flash.deinit(); + return MBED_ERROR_INVALID_SIZE; + } + } else { + aligned_start_address = align_down(*start_address, flash.get_sector_size(*start_address)); + if (*start_address != aligned_start_address) { + // Start address not aligned - size should likely be changed so that it is + flash.deinit(); + return MBED_ERROR_INVALID_SIZE; + } + + if (*size == 0) { + //The block device will have all space from start address to the end of the flash + *size = (flash_end_address - *start_address); + } else { + // Do checks on end address to make sure configured start address/size are good + + end_address = *start_address + *size; + if (end_address > flash_end_address) { + // End address is out of flash bounds + flash.deinit(); + return MBED_ERROR_INVALID_SIZE; + } + + aligned_end_address = align_up(end_address, flash.get_sector_size(end_address - 1)); + if (end_address != aligned_end_address) { + // End address not aligned - size should likely be changed so that it is + flash.deinit(); + return MBED_ERROR_INVALID_SIZE; + } + } + } + + flash.deinit(); + + if (*start_address < flash_first_writable_sector_address) { + // Calculated start address overlaps with ROM + return MBED_ERROR_MEDIA_FULL; + } +#endif + + return MBED_SUCCESS; +} diff --git a/features/storage/kvstore/conf/kv_config.h b/features/storage/kvstore/conf/kv_config.h index 660a6bdd88..f16688fd5e 100644 --- a/features/storage/kvstore/conf/kv_config.h +++ b/features/storage/kvstore/conf/kv_config.h @@ -16,6 +16,8 @@ #ifndef _KV_CONFIG #define _KV_CONFIG +#include "features/storage/blockdevice/BlockDevice.h" + #ifdef __cplusplus extern "C" { #endif @@ -42,6 +44,32 @@ int kv_init_storage_config(); */ const char *get_filesystemstore_folder_path(); +/** + * @brief Get the default TDBStore flash start address and size. + * + * @param[out] start_address Default TDBStore start address in flash. + * @param[out] size Default TDBStore size. + * + * @returns MBED_SUCCESS Success. + * MBED_ERROR_INITIALIZATION_FAILED Failed to initialize flash driver. + * MBED_ERROR_MEDIA_FULL Default TDBStore space overlaps with program memory. + */ +int kv_get_default_flash_addresses(mbed::bd_addr_t *start_address, mbed::bd_size_t *size); + +/** + * @brief Get the TDBStore flash bounds from the configured start address and size. + * + * @param[inout] start_address Configured TDBStore start address in flash. + * @param[inout] size Configured TDBStore size. If 0, the size will be from the start address to the end of flash + * + * @returns MBED_SUCCESS Success. + * MBED_ERROR_INVALID_ARGUMENT One of the arguments is NULL or both the configured start address and size are 0. + * MBED_ERROR_INITIALIZATION_FAILED Failed to initialize flash driver. + * MBED_ERROR_INVALID_SIZE Configured size results in misaligned start/end address or end address past the end of flash. + * MBED_ERROR_MEDIA_FULL Configured start address/size results in bounds overlapping with program memory. + */ +int kv_get_flash_bounds_from_config(mbed::bd_addr_t *start_address, mbed::bd_size_t *size); + #ifdef __cplusplus } // closing brace for extern "C" #endif diff --git a/features/storage/kvstore/direct_access_devicekey/DirectAccessDevicekey.cpp b/features/storage/kvstore/direct_access_devicekey/DirectAccessDevicekey.cpp index f1dfd23b0c..2c7add9a59 100644 --- a/features/storage/kvstore/direct_access_devicekey/DirectAccessDevicekey.cpp +++ b/features/storage/kvstore/direct_access_devicekey/DirectAccessDevicekey.cpp @@ -24,6 +24,7 @@ #include "MbedCRC.h" #include "mbed_trace.h" #include "TDBStore.h" +#include "kv_config.h" #define TRACE_GROUP "DADK" using namespace mbed; @@ -145,13 +146,13 @@ int get_expected_internal_TDBStore_position(uint32_t *out_tdb_start_offset, uint int ret; if ((tdb_start_address == 0) && (tdb_size == 0)) { - ret = TDBStore::get_default_flash_addresses(&tdb_start_address, &tdb_size); + ret = kv_get_default_flash_addresses(&tdb_start_address, &tdb_size); if (ret != MBED_SUCCESS) { return MBED_ERROR_FAILED_OPERATION; } } - ret = TDBStore::get_flash_bounds_from_config(&tdb_start_address, &tdb_size); + ret = kv_get_flash_bounds_from_config(&tdb_start_address, &tdb_size); if (ret != MBED_SUCCESS) { return MBED_ERROR_FAILED_OPERATION; } diff --git a/features/storage/kvstore/tdbstore/TDBStore.cpp b/features/storage/kvstore/tdbstore/TDBStore.cpp index 4e82dd3fe6..fd7d8ce3c0 100644 --- a/features/storage/kvstore/tdbstore/TDBStore.cpp +++ b/features/storage/kvstore/tdbstore/TDBStore.cpp @@ -1428,135 +1428,6 @@ int TDBStore::reserved_data_get(void *reserved_data, size_t reserved_data_buf_si return ret; } -int TDBStore::get_default_flash_addresses(bd_addr_t *start_address, bd_size_t *size) -{ - int ret = MBED_SUCCESS; - -#if COMPONENT_FLASHIAP - FlashIAP flash; - if (flash.init() != 0) { - return MBED_ERROR_INITIALIZATION_FAILED; - } - - // Let's work from end of the flash backwards - bd_addr_t end_of_flash = flash.get_flash_start() + flash.get_flash_size(); - bd_addr_t curr_addr = end_of_flash; - bd_size_t sector_space = 0; - - for (int i = STORE_SECTORS; i; i--) { - bd_size_t sector_size = flash.get_sector_size(curr_addr - 1); - sector_space += sector_size; - } - - bd_size_t page_space = flash.get_page_size() * STORE_PAGES; - if (sector_space > page_space) { - curr_addr -= sector_space; - *size = sector_space; - } else { - curr_addr -= page_space; - // Align to 2 sector boundary so that garbage collection works properly - curr_addr = align_down(curr_addr, 2 * flash.get_sector_size(curr_addr)); - *size = end_of_flash - curr_addr; - } - - // Store- and application-sectors mustn't overlap - uint32_t first_wrtbl_sector_addr = - (uint32_t)(align_up(FLASHIAP_APP_ROM_END_ADDR, flash.get_sector_size(FLASHIAP_APP_ROM_END_ADDR))); - - MBED_ASSERT(curr_addr >= first_wrtbl_sector_addr); - if (curr_addr < first_wrtbl_sector_addr) { - ret = MBED_ERROR_MEDIA_FULL; - } else { - *start_address = curr_addr; - } - - flash.deinit(); -#endif - - return ret; -} - -int TDBStore::get_flash_bounds_from_config(bd_addr_t *start_address, bd_size_t *size) -{ -#if COMPONENT_FLASHIAP - - bd_addr_t flash_end_address; - bd_addr_t flash_start_address; - bd_addr_t flash_first_writable_sector_address; - bd_addr_t aligned_start_address; - bd_addr_t aligned_end_address; - bd_addr_t end_address; - FlashIAP flash; - - if (!start_address || !size) { - return MBED_ERROR_INVALID_ARGUMENT; - } - - int ret = flash.init(); - if (ret != 0) { - return MBED_ERROR_INITIALIZATION_FAILED; - } - - // Get flash parameters - flash_first_writable_sector_address = align_up(FLASHIAP_APP_ROM_END_ADDR, flash.get_sector_size(FLASHIAP_APP_ROM_END_ADDR)); - flash_start_address = flash.get_flash_start(); - flash_end_address = flash_start_address + flash.get_flash_size(); - - if (*start_address == 0) { - if (*size == 0) { - //The block device will have all space from start address to the end of the flash - *size = flash.get_flash_size(); - } - - *start_address = flash_end_address - *size; - aligned_start_address = align_down(*start_address, flash.get_sector_size(*start_address)); - if (*start_address != aligned_start_address) { - // Start address not aligned - size should likely be changed so that it is - flash.deinit(); - return MBED_ERROR_INVALID_SIZE; - } - } else { - aligned_start_address = align_down(*start_address, flash.get_sector_size(*start_address)); - if (*start_address != aligned_start_address) { - // Start address not aligned - size should likely be changed so that it is - flash.deinit(); - return MBED_ERROR_INVALID_SIZE; - } - - if (*size == 0) { - //The block device will have all space from start address to the end of the flash - *size = (flash_end_address - *start_address); - } else { - // Do checks on end address to make sure configured start address/size are good - - end_address = *start_address + *size; - if (end_address > flash_end_address) { - // End address is out of flash bounds - flash.deinit(); - return MBED_ERROR_INVALID_SIZE; - } - - aligned_end_address = align_up(end_address, flash.get_sector_size(end_address - 1)); - if (end_address != aligned_end_address) { - // End address not aligned - size should likely be changed so that it is - flash.deinit(); - return MBED_ERROR_INVALID_SIZE; - } - } - } - - flash.deinit(); - - if (*start_address < flash_first_writable_sector_address) { - // Calculated start address overlaps with ROM - return MBED_ERROR_MEDIA_FULL; - } -#endif - - return MBED_SUCCESS; -} - - void TDBStore::offset_in_erase_unit(uint8_t area, uint32_t offset, uint32_t &offset_from_start, uint32_t &dist_to_end) { diff --git a/features/storage/kvstore/tdbstore/TDBStore.h b/features/storage/kvstore/tdbstore/TDBStore.h index 48c94eefb3..71b92b1fa4 100644 --- a/features/storage/kvstore/tdbstore/TDBStore.h +++ b/features/storage/kvstore/tdbstore/TDBStore.h @@ -37,13 +37,6 @@ public: static const uint32_t RESERVED_AREA_SIZE = 64; - // Use the last 2 sectors or 14 pages of flash for the TDBStore by default (whichever is larger) - // For each area: must be a minimum of 1 page of reserved and 2 pages for master record - /** Minimum number of internal flash sectors required for TDBStore */ - static const int STORE_SECTORS = 2; - /** Minimum number of internal flash pages required for TDBStore */ - static const int STORE_PAGES = 14; - /** * @brief Class constructor * @@ -287,32 +280,6 @@ public: virtual int reserved_data_get(void *reserved_data, size_t reserved_data_buf_size, size_t *actual_data_size = 0); - /** - * @brief Get the default TDBStore flash start address and size. - * - * @param[out] start_address Default TDBStore start address in flash. - * @param[out] size Default TDBStore size. - * - * @returns MBED_SUCCESS Success. - * MBED_ERROR_INITIALIZATION_FAILED Failed to initialize flash driver. - * MBED_ERROR_MEDIA_FULL Default TDBStore space overlaps with program memory. - */ - static int get_default_flash_addresses(bd_addr_t *start_address, bd_size_t *size); - - /** - * @brief Get the TDBStore flash bounds from the configured start address and size. - * - * @param[inout] start_address Configured TDBStore start address in flash. - * @param[inout] size Configured TDBStore size. If 0, the size will be from the start address to the end of flash - * - * @returns MBED_SUCCESS Success. - * MBED_ERROR_INVALID_ARGUMENT One of the arguments is NULL or both the configured start address and size are 0. - * MBED_ERROR_INITIALIZATION_FAILED Failed to initialize flash driver. - * MBED_ERROR_INVALID_SIZE Configured size results in misaligned start/end address or end address past the end of flash. - * MBED_ERROR_MEDIA_FULL Configured start address/size results in bounds overlapping with program memory. - */ - static int get_flash_bounds_from_config(bd_addr_t *start_address, bd_size_t *size); - #if !defined(DOXYGEN_ONLY) private: