Move flash bounds helpers from TDBStore to kv_config

pull/11629/head
Kyle Kearney 2020-03-02 16:34:01 -08:00
parent 926423c109
commit 7f18a6ce49
6 changed files with 173 additions and 172 deletions

View File

@ -94,7 +94,7 @@ int get_virtual_TDBStore_position(uint32_t conf_start_address, uint32_t conf_si
} else { } else {
bd_addr_t default_start; bd_addr_t default_start;
bd_size_t default_size; 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; aligned_start_address = (uint32_t)default_start;
bd_final_size = (uint32_t)default_size; bd_final_size = (uint32_t)default_size;
} }

View File

@ -150,6 +150,12 @@ static const char *filesystemstore_folder_path = NULL;
using namespace mbed; 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<PlatformMutex> mutex; static SingletonPtr<PlatformMutex> mutex;
static bool is_kv_config_initialize = false; 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 page_size = bd->get_program_size();
bd_size_t number_of_sector = size / erase_size; bd_size_t number_of_sector = size / erase_size;
bd_size_t number_of_page = size / page_size; bd_size_t number_of_page = size / page_size;
if (number_of_sector < TDBStore::STORE_SECTORS) { if (number_of_sector < STORE_SECTORS) {
tr_error("KV Config: There are less than %d sectors - TDBStore will not work.", TDBStore::STORE_SECTORS); tr_error("KV Config: There are less than %d sectors - TDBStore will not work.", STORE_SECTORS);
return -1; return -1;
} }
if (number_of_page < TDBStore::STORE_PAGES) { if (number_of_page < STORE_PAGES) {
tr_error("KV Config: There are less than %d pages - TDBStore will not work.", TDBStore::STORE_PAGES); tr_error("KV Config: There are less than %d pages - TDBStore will not work.", STORE_PAGES);
return -1; 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) BlockDevice *_get_blockdevice_FLASHIAP(bd_addr_t start_address, bd_size_t size)
{ {
#if COMPONENT_FLASHIAP #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) { if (ret != 0) {
tr_error("KV Config: Determination of internal block device bounds failed. The configured start address/size is likely invalid."); tr_error("KV Config: Determination of internal block device bounds failed. The configured start address/size is likely invalid.");
return NULL; 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 //Get the default address and size for the TDBStore
if (size == 0 && start_address == 0) { if (size == 0 && start_address == 0) {
//Calculate the block device size and start address in case default values are used. //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) { if (ret != MBED_SUCCESS) {
return MBED_ERROR_FAILED_OPERATION; 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. //Check if TDBStore has at least 2 sectors or 14 pages.
if (_calculate_blocksize_match_tdbstore(*internal_bd) != MBED_SUCCESS) { 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; return MBED_ERROR_INVALID_ARGUMENT;
} }
@ -991,3 +997,131 @@ exit:
mutex->unlock(); mutex->unlock();
return ret; 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;
}

View File

@ -16,6 +16,8 @@
#ifndef _KV_CONFIG #ifndef _KV_CONFIG
#define _KV_CONFIG #define _KV_CONFIG
#include "features/storage/blockdevice/BlockDevice.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
@ -42,6 +44,32 @@ int kv_init_storage_config();
*/ */
const char *get_filesystemstore_folder_path(); 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 #ifdef __cplusplus
} // closing brace for extern "C" } // closing brace for extern "C"
#endif #endif

View File

@ -24,6 +24,7 @@
#include "MbedCRC.h" #include "MbedCRC.h"
#include "mbed_trace.h" #include "mbed_trace.h"
#include "TDBStore.h" #include "TDBStore.h"
#include "kv_config.h"
#define TRACE_GROUP "DADK" #define TRACE_GROUP "DADK"
using namespace mbed; using namespace mbed;
@ -145,13 +146,13 @@ int get_expected_internal_TDBStore_position(uint32_t *out_tdb_start_offset, uint
int ret; int ret;
if ((tdb_start_address == 0) && (tdb_size == 0)) { 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) { if (ret != MBED_SUCCESS) {
return MBED_ERROR_FAILED_OPERATION; 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) { if (ret != MBED_SUCCESS) {
return MBED_ERROR_FAILED_OPERATION; return MBED_ERROR_FAILED_OPERATION;
} }

View File

@ -1428,135 +1428,6 @@ int TDBStore::reserved_data_get(void *reserved_data, size_t reserved_data_buf_si
return ret; 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, void TDBStore::offset_in_erase_unit(uint8_t area, uint32_t offset,
uint32_t &offset_from_start, uint32_t &dist_to_end) uint32_t &offset_from_start, uint32_t &dist_to_end)
{ {

View File

@ -37,13 +37,6 @@ public:
static const uint32_t RESERVED_AREA_SIZE = 64; 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 * @brief Class constructor
* *
@ -287,32 +280,6 @@ public:
virtual int reserved_data_get(void *reserved_data, size_t reserved_data_buf_size, virtual int reserved_data_get(void *reserved_data, size_t reserved_data_buf_size,
size_t *actual_data_size = 0); 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) #if !defined(DOXYGEN_ONLY)
private: private: