Merge pull request #9548 from davidsaada/david_flashiap_retries

FlashIAP driver: Add retries to erase and program operations.
pull/9682/head
Cruz Monrreal 2019-01-30 17:32:19 -06:00 committed by GitHub
commit 87e57d3ced
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 25 additions and 34 deletions

View File

@ -33,6 +33,8 @@
namespace mbed { namespace mbed {
const unsigned int num_write_retries = 16;
SingletonPtr<PlatformMutex> FlashIAP::_mutex; SingletonPtr<PlatformMutex> FlashIAP::_mutex;
static inline bool is_aligned(uint32_t number, uint32_t alignment) static inline bool is_aligned(uint32_t number, uint32_t alignment)
@ -119,7 +121,7 @@ int FlashIAP::program(const void *buffer, uint32_t addr, uint32_t size)
int ret = 0; int ret = 0;
_mutex->lock(); _mutex->lock();
while (size) { while (size && !ret) {
uint32_t current_sector_size = flash_get_sector_size(&_flash, addr); uint32_t current_sector_size = flash_get_sector_size(&_flash, addr);
bool unaligned_src = (((size_t) buf / sizeof(uint32_t) * sizeof(uint32_t)) != (size_t) buf); bool unaligned_src = (((size_t) buf / sizeof(uint32_t) * sizeof(uint32_t)) != (size_t) buf);
chunk = std::min(current_sector_size - (addr % current_sector_size), size); chunk = std::min(current_sector_size - (addr % current_sector_size), size);
@ -141,11 +143,17 @@ int FlashIAP::program(const void *buffer, uint32_t addr, uint32_t size)
prog_size = chunk; prog_size = chunk;
} }
{ {
ScopedRamExecutionLock make_ram_executable; // Few boards may fail the write actions due to HW limitations (like critical drivers that
ScopedRomWriteLock make_rom_writable; // disable flash operations). Just retry a few times until success.
if (flash_program_page(&_flash, addr, prog_buf, prog_size)) { for (unsigned int retry = 0; retry < num_write_retries; retry++) {
ret = -1; ScopedRamExecutionLock make_ram_executable;
break; ScopedRomWriteLock make_rom_writable;
ret = flash_program_page(&_flash, addr, prog_buf, prog_size);
if (ret) {
ret = -1;
} else {
break;
}
} }
} }
size -= chunk; size -= chunk;
@ -187,15 +195,18 @@ int FlashIAP::erase(uint32_t addr, uint32_t size)
int32_t ret = 0; int32_t ret = 0;
_mutex->lock(); _mutex->lock();
while (size) { while (size && !ret) {
{ // Few boards may fail the erase actions due to HW limitations (like critical drivers that
// disable flash operations). Just retry a few times until success.
for (unsigned int retry = 0; retry < num_write_retries; retry++) {
ScopedRamExecutionLock make_ram_executable; ScopedRamExecutionLock make_ram_executable;
ScopedRomWriteLock make_rom_writable; ScopedRomWriteLock make_rom_writable;
ret = flash_erase_sector(&_flash, addr); ret = flash_erase_sector(&_flash, addr);
} if (ret) {
if (ret != 0) { ret = -1;
ret = -1; } else {
break; break;
}
} }
current_sector_size = flash_get_sector_size(&_flash, addr); current_sector_size = flash_get_sector_size(&_flash, addr);
size -= current_sector_size; size -= current_sector_size;

View File

@ -72,8 +72,6 @@ typedef struct {
static const uint32_t min_area_size = 4096; static const uint32_t min_area_size = 4096;
static const uint32_t max_data_size = 4096; static const uint32_t max_data_size = 4096;
static const int num_write_retries = 16;
static const uint8_t blank_flash_val = 0xFF; static const uint8_t blank_flash_val = 0xFF;
typedef enum { typedef enum {
@ -234,31 +232,13 @@ int NVStore::flash_read_area(uint8_t area, uint32_t offset, uint32_t size, void
int NVStore::flash_write_area(uint8_t area, uint32_t offset, uint32_t size, const void *buf) int NVStore::flash_write_area(uint8_t area, uint32_t offset, uint32_t size, const void *buf)
{ {
int ret; int ret = _flash->program(buf, _flash_area_params[area].address + offset, size);
// On some boards, write action can fail due to HW limitations (like critical drivers
// that disable all other actions). Just retry a few times until success.
for (int i = 0; i < num_write_retries; i++) {
ret = _flash->program(buf, _flash_area_params[area].address + offset, size);
if (!ret) {
return ret;
}
wait_ms(1);
}
return ret; return ret;
} }
int NVStore::flash_erase_area(uint8_t area) int NVStore::flash_erase_area(uint8_t area)
{ {
int ret; int ret = _flash->erase(_flash_area_params[area].address, _flash_area_params[area].size);
// On some boards, write action can fail due to HW limitations (like critical drivers
// that disable all other actions). Just retry a few times until success.
for (int i = 0; i < num_write_retries; i++) {
ret = _flash->erase(_flash_area_params[area].address, _flash_area_params[area].size);
if (!ret) {
return ret;
}
wait_ms(1);
}
return ret; return ret;
} }