Skip to content

Commit 28c5913

Browse files
authored
⚡️ STM32H7 Flash Wear Leveling (#27634)
1 parent 55add90 commit 28c5913

File tree

2 files changed

+43
-20
lines changed

2 files changed

+43
-20
lines changed

Marlin/src/HAL/STM32/eeprom_flash.cpp

+41-18
Original file line numberDiff line numberDiff line change
@@ -74,21 +74,21 @@
7474
#define EEPROM_SLOTS ((FLASH_UNIT_SIZE) / (MARLIN_EEPROM_SIZE))
7575
#define SLOT_ADDRESS(slot) (FLASH_ADDRESS_START + (slot * (MARLIN_EEPROM_SIZE)))
7676

77-
#define UNLOCK_FLASH() if (!flash_unlocked) { \
78-
HAL_FLASH_Unlock(); \
79-
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | \
80-
FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR | FLASH_FLAG_PGSERR); \
81-
flash_unlocked = true; \
82-
}
83-
#define LOCK_FLASH() if (flash_unlocked) { HAL_FLASH_Lock(); flash_unlocked = false; }
77+
#ifdef STM32H7xx
78+
#define FLASHWORD_SIZE 32U // STM32H7xx a FLASHWORD is 32 bytes (256 bits)
79+
#define FLASH_FLAGS_TO_CLEAR (FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | FLASH_FLAG_PGSERR)
80+
#else
81+
#define FLASHWORD_SIZE 4U // STM32F4xx a FLASHWORD is 4 bytes sizeof(uint32_t)
82+
#define FLASH_FLAGS_TO_CLEAR (FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR | FLASH_FLAG_PGSERR)
83+
#endif
8484

8585
#define EMPTY_UINT32 ((uint32_t)-1)
8686
#define EMPTY_UINT8 ((uint8_t)-1)
8787

8888
static uint8_t ram_eeprom[MARLIN_EEPROM_SIZE] __attribute__((aligned(4))) = {0};
8989
static int current_slot = -1;
9090

91-
static_assert(0 == MARLIN_EEPROM_SIZE % 4, "MARLIN_EEPROM_SIZE must be a multiple of 4"); // Ensure copying as uint32_t is safe
91+
static_assert(0 == MARLIN_EEPROM_SIZE % FLASHWORD_SIZE, "MARLIN_EEPROM_SIZE must be a multiple of the FLASHWORD size"); // Ensure copying as uint32_t is safe
9292
static_assert(0 == FLASH_UNIT_SIZE % MARLIN_EEPROM_SIZE, "MARLIN_EEPROM_SIZE must divide evenly into your FLASH_UNIT_SIZE");
9393
static_assert(FLASH_UNIT_SIZE >= MARLIN_EEPROM_SIZE, "FLASH_UNIT_SIZE must be greater than or equal to your MARLIN_EEPROM_SIZE");
9494
static_assert(IS_FLASH_SECTOR(FLASH_SECTOR), "FLASH_SECTOR is invalid");
@@ -147,11 +147,15 @@ bool PersistentStore::access_start() {
147147
bool PersistentStore::access_finish() {
148148

149149
if (eeprom_data_written) {
150+
150151
#ifdef STM32F4xx
151152
// MCU may come up with flash error bits which prevent some flash operations.
152153
// Clear flags prior to flash operations to prevent errors.
153154
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR | FLASH_FLAG_PGSERR);
154155
#endif
156+
#ifdef STM32H7xx
157+
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | FLASH_FLAG_PGSERR);
158+
#endif
155159

156160
#if ENABLED(FLASH_EEPROM_LEVELING)
157161

@@ -170,7 +174,12 @@ bool PersistentStore::access_finish() {
170174
EraseInitStruct.NbSectors = 1;
171175

172176
current_slot = EEPROM_SLOTS - 1;
173-
UNLOCK_FLASH();
177+
178+
if (!flash_unlocked) {
179+
HAL_FLASH_Unlock();
180+
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAGS_TO_CLEAR);
181+
flash_unlocked = true;
182+
}
174183

175184
TERN_(HAS_PAUSE_SERVO_OUTPUT, PAUSE_SERVO_OUTPUT());
176185
hal.isr_off();
@@ -181,26 +190,37 @@ bool PersistentStore::access_finish() {
181190
DEBUG_ECHOLNPGM("HAL_FLASHEx_Erase=", status);
182191
DEBUG_ECHOLNPGM("GetError=", HAL_FLASH_GetError());
183192
DEBUG_ECHOLNPGM("SectorError=", SectorError);
184-
LOCK_FLASH();
193+
if (flash_unlocked) {
194+
HAL_FLASH_Lock();
195+
flash_unlocked = false;
196+
}
185197
return false;
186198
}
187199
}
188200

189-
UNLOCK_FLASH();
201+
if (!flash_unlocked) {
202+
HAL_FLASH_Unlock();
203+
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAGS_TO_CLEAR);
204+
flash_unlocked = true;
205+
}
190206

191207
uint32_t offset = 0,
192208
address = SLOT_ADDRESS(current_slot),
193-
address_end = address + MARLIN_EEPROM_SIZE,
194-
data = 0;
209+
address_end = address + MARLIN_EEPROM_SIZE;
195210

196211
bool success = true;
197212

198213
while (address < address_end) {
199-
memcpy(&data, ram_eeprom + offset, sizeof(data));
200-
status = HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, address, data);
214+
#ifdef STM32H7xx
215+
status = HAL_FLASH_Program(FLASH_TYPEPROGRAM_FLASHWORD, address, uint32_t(ram_eeprom + offset));
216+
#else
217+
//memcpy(&data, ram_eeprom + offset, sizeof(data)); // IRON, IMPROVED
218+
//status = HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, address, data);
219+
status = HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, address, *(uint32_t*)(ram_eeprom + offset)); // IRON, OPTIMIZED
220+
#endif
201221
if (status == HAL_OK) {
202-
address += sizeof(uint32_t);
203-
offset += sizeof(uint32_t);
222+
address += FLASHWORD_SIZE;
223+
offset += FLASHWORD_SIZE;
204224
}
205225
else {
206226
DEBUG_ECHOLNPGM("HAL_FLASH_Program=", status);
@@ -211,7 +231,10 @@ bool PersistentStore::access_finish() {
211231
}
212232
}
213233

214-
LOCK_FLASH();
234+
if (flash_unlocked) {
235+
HAL_FLASH_Lock();
236+
flash_unlocked = false;
237+
}
215238

216239
if (success) {
217240
eeprom_data_written = false;

Marlin/src/HAL/STM32/inc/SanityCheck.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,8 @@
3636
#error "SDCARD_EEPROM_EMULATION requires SDSUPPORT. Enable SDSUPPORT or choose another EEPROM emulation."
3737
#endif
3838

39-
#if !defined(STM32F4xx) && ENABLED(FLASH_EEPROM_LEVELING)
40-
#error "FLASH_EEPROM_LEVELING is currently only supported on STM32F4 hardware."
39+
#if NONE(STM32F4xx, STM32H7xx) && ENABLED(FLASH_EEPROM_LEVELING)
40+
#error "FLASH_EEPROM_LEVELING is currently only supported on STM32F4/H7 hardware." // IRON
4141
#endif
4242

4343
#if ENABLED(SERIAL_STATS_MAX_RX_QUEUED)

0 commit comments

Comments
 (0)