Browse Source

STM32F1 Flash-based EEPROM fixes (#16118)

randellhodges 5 years ago
parent
commit
7f8ca85e69
1 changed files with 45 additions and 25 deletions
  1. 45
    25
      Marlin/src/HAL/HAL_STM32F1/persistent_store_flash.cpp

+ 45
- 25
Marlin/src/HAL/HAL_STM32F1/persistent_store_flash.cpp View File

@@ -40,53 +40,73 @@
40 40
 #include <EEPROM.h>
41 41
 
42 42
 // Store settings in the last two pages
43
-// Flash pages must be erased before writing, so keep track.
44
-bool firstWrite = false;
43
+#define EEPROM_SIZE (EEPROM_PAGE_SIZE * 2)
44
+#define ACCESS_FINISHED(TF) do{ FLASH_Lock(); eeprom_dirty = false; return TF; }while(0)
45
+
46
+static uint8_t ram_eeprom[EEPROM_SIZE] __attribute__((aligned(4))) = {0};
47
+static bool eeprom_dirty = false;
45 48
 
46 49
 bool PersistentStore::access_start() {
47
-  firstWrite = true;
50
+  const uint32_t* source = reinterpret_cast<const uint32_t*>(EEPROM_PAGE0_BASE);
51
+  uint32_t* destination = reinterpret_cast<uint32_t*>(ram_eeprom);
52
+
53
+  static_assert(0 == EEPROM_SIZE % 4, "EEPROM_SIZE is corrupted. (Must be a multiple of 4.)"); // Ensure copying as uint32_t is safe
54
+  constexpr size_t eeprom_size_u32 = EEPROM_SIZE / 4;
55
+
56
+  for (size_t i = 0; i < eeprom_size_u32; ++i, ++destination, ++source)
57
+    *destination = *source;
58
+
59
+  eeprom_dirty = false;
48 60
   return true;
49 61
 }
50 62
 
51 63
 bool PersistentStore::access_finish() {
52
-  FLASH_Lock();
53
-  firstWrite = false;
54
-  return true;
55
-}
56 64
 
57
-bool PersistentStore::write_data(int &pos, const uint8_t *value, size_t size, uint16_t *crc) {
58
-  FLASH_Status status;
65
+  if (eeprom_dirty) {
66
+    FLASH_Status status;
59 67
 
60
-  if (firstWrite) {
68
+    // Instead of erasing all (both) pages, maybe in the loop we check what page we are in, and if the
69
+    // data has changed in that page. We then erase the first time we "detect" a change. In theory, if
70
+    // nothing changed in a page, we wouldn't need to erase/write it.
71
+    // Or, instead of checking at this point, turn eeprom_dirty into an array of bool the size of number
72
+    // of pages. Inside write_data, we set the flag to true at that time if something in that
73
+    // page changes...either way, something to look at later.
61 74
     FLASH_Unlock();
75
+
62 76
     status = FLASH_ErasePage(EEPROM_PAGE0_BASE);
63
-    if (status != FLASH_COMPLETE) return true;
77
+    if (status != FLASH_COMPLETE) ACCESS_FINISHED(true);
64 78
     status = FLASH_ErasePage(EEPROM_PAGE1_BASE);
65
-    if (status != FLASH_COMPLETE) return true;
66
-    firstWrite = false;
67
-  }
79
+    if (status != FLASH_COMPLETE) ACCESS_FINISHED(true);
80
+
81
+    const uint16_t *source = reinterpret_cast<const uint16_t*>(ram_eeprom);
82
+    for (size_t i = 0; i < EEPROM_SIZE; i += 2, ++source) {
83
+      if (FLASH_ProgramHalfWord(EEPROM_PAGE0_BASE + i, *source) != FLASH_COMPLETE)
84
+        ACCESS_FINISHED(false);
85
+    }
68 86
 
69
-  for (size_t i = 0; i < size; i++) {
70
-    if (FLASH_ProgramHalfWord(EEPROM_PAGE0_BASE + (pos + i) * 2, value[i]) != FLASH_COMPLETE)
71
-      return true;
87
+    ACCESS_FINISHED(true);
72 88
   }
73 89
 
90
+  return true;
91
+}
92
+
93
+bool PersistentStore::write_data(int &pos, const uint8_t *value, size_t size, uint16_t *crc) {
94
+  for (size_t i = 0; i < size; ++i) ram_eeprom[pos + i] = value[i];
95
+  eeprom_dirty = true;
74 96
   crc16(crc, value, size);
75 97
   pos += size;
76
-  return false;
98
+  return false;  // return true for any error
77 99
 }
78 100
 
79 101
 bool PersistentStore::read_data(int &pos, uint8_t* value, const size_t size, uint16_t *crc, const bool writing/*=true*/) {
80
-  for (size_t i = 0; i < size; i++) {
81
-    uint8_t v = *(uint16_t *)(EEPROM_PAGE0_BASE + (pos + i) * 2);
82
-    if (writing) value[i] = v;
83
-    crc16(crc, &v, 1);
84
-  }
102
+  const uint8_t * const buff = writing ? &value[0] : &ram_eeprom[pos];
103
+  if (writing) for (size_t i = 0; i < size; i++) value[i] = ram_eeprom[pos + i];
104
+  crc16(crc, buff, size);
85 105
   pos += size;
86
-  return false;
106
+  return false;  // return true for any error
87 107
 }
88 108
 
89
-size_t PersistentStore::capacity() { return size_t(E2END + 1); }
109
+size_t PersistentStore::capacity() { return EEPROM_SIZE; }
90 110
 
91 111
 #endif // EEPROM_SETTINGS && EEPROM FLASH
92 112
 #endif // __STM32F1__

Loading…
Cancel
Save