mbed library sources. Supersedes mbed-src.

Dependents:   Nucleo_Hello_Encoder BLE_iBeaconScan AM1805_DEMO DISCO-F429ZI_ExportTemplate1 ... more

Revision:
189:f392fc9709a3
Parent:
188:bcfe06ba3d64
diff -r bcfe06ba3d64 -r f392fc9709a3 drivers/FlashIAP.cpp
--- a/drivers/FlashIAP.cpp	Thu Nov 08 11:46:34 2018 +0000
+++ b/drivers/FlashIAP.cpp	Wed Feb 20 22:31:08 2019 +0000
@@ -25,12 +25,16 @@
 #include <algorithm>
 #include "FlashIAP.h"
 #include "platform/mbed_assert.h"
+#include "platform/ScopedRamExecutionLock.h"
+#include "platform/ScopedRomWriteLock.h"
 
 
-#ifdef DEVICE_FLASH
+#if DEVICE_FLASH
 
 namespace mbed {
 
+const unsigned int num_write_retries = 16;
+
 SingletonPtr<PlatformMutex> FlashIAP::_mutex;
 
 static inline bool is_aligned(uint32_t number, uint32_t alignment)
@@ -56,8 +60,12 @@
 {
     int ret = 0;
     _mutex->lock();
-    if (flash_init(&_flash)) {
-        ret = -1;
+    {
+        ScopedRamExecutionLock make_ram_executable;
+        ScopedRomWriteLock make_rom_writable;
+        if (flash_init(&_flash)) {
+            ret = -1;
+        }
     }
     uint32_t page_size = get_page_size();
     _page_buf = new uint8_t[page_size];
@@ -70,8 +78,12 @@
 {
     int ret = 0;
     _mutex->lock();
-    if (flash_free(&_flash)) {
-        ret = -1;
+    {
+        ScopedRamExecutionLock make_ram_executable;
+        ScopedRomWriteLock make_rom_writable;
+        if (flash_free(&_flash)) {
+            ret = -1;
+        }
     }
     delete[] _page_buf;
     _mutex->unlock();
@@ -83,7 +95,11 @@
 {
     int32_t ret = -1;
     _mutex->lock();
-    ret = flash_read(&_flash, addr, (uint8_t *) buffer, size);
+    {
+        ScopedRamExecutionLock make_ram_executable;
+        ScopedRomWriteLock make_rom_writable;
+        ret = flash_read(&_flash, addr, (uint8_t *) buffer, size);
+    }
     _mutex->unlock();
     return ret;
 }
@@ -105,7 +121,7 @@
 
     int ret = 0;
     _mutex->lock();
-    while (size) {
+    while (size && !ret) {
         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);
         chunk = std::min(current_sector_size - (addr % current_sector_size), size);
@@ -126,9 +142,19 @@
             prog_buf = buf;
             prog_size = chunk;
         }
-        if (flash_program_page(&_flash, addr, prog_buf, prog_size)) {
-            ret = -1;
-            break;
+        {
+            // Few boards may fail the write 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;
+                ScopedRomWriteLock make_rom_writable;
+                ret = flash_program_page(&_flash, addr, prog_buf, prog_size);
+                if (ret) {
+                    ret = -1;
+                } else {
+                    break;
+                }
+            }
         }
         size -= chunk;
         addr += chunk;
@@ -169,11 +195,18 @@
 
     int32_t ret = 0;
     _mutex->lock();
-    while (size) {
-        ret = flash_erase_sector(&_flash, addr);
-        if (ret != 0) {
-            ret = -1;
-            break;
+    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;
+            ScopedRomWriteLock make_rom_writable;
+            ret = flash_erase_sector(&_flash, addr);
+            if (ret) {
+                ret = -1;
+            } else {
+                break;
+            }
         }
         current_sector_size = flash_get_sector_size(&_flash, addr);
         size -= current_sector_size;
@@ -203,6 +236,11 @@
     return flash_get_size(&_flash);
 }
 
+uint8_t FlashIAP::get_erase_value() const
+{
+    return flash_get_erase_value(&_flash);
+}
+
 }
 
 #endif