Improve STM32F4 Flash Behavior (#17946)

This commit is contained in:
Jason Smith
2020-05-10 23:10:20 -07:00
committed by GitHub
parent 9d545f1231
commit 25aade1cf1
4 changed files with 87 additions and 13 deletions

View File

@@ -28,10 +28,13 @@
#include "../shared/eeprom_api.h"
// Only STM32F4 can support wear leveling at this time
#ifndef STM32F4xx
#undef FLASH_EEPROM_LEVELING
#if HAS_SERVOS
#include "Servo.h"
#define PAUSE_SERVO_OUTPUT() libServo::pause_all_servos()
#define RESUME_SERVO_OUTPUT() libServo::resume_all_servos()
#else
#define PAUSE_SERVO_OUTPUT()
#define RESUME_SERVO_OUTPUT()
#endif
/**
@@ -139,6 +142,11 @@ bool PersistentStore::access_start() {
bool PersistentStore::access_finish() {
if (eeprom_data_written) {
#ifdef STM32F4xx
// MCU may come up with flash error bits which prevent some flash operations.
// Clear flags prior to flash operations to prevent errors.
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR | FLASH_FLAG_PGSERR);
#endif
#if ENABLED(FLASH_EEPROM_LEVELING)
@@ -159,7 +167,11 @@ bool PersistentStore::access_finish() {
current_slot = EEPROM_SLOTS - 1;
UNLOCK_FLASH();
PAUSE_SERVO_OUTPUT();
DISABLE_ISRS();
status = HAL_FLASHEx_Erase(&EraseInitStruct, &SectorError);
ENABLE_ISRS();
RESUME_SERVO_OUTPUT();
if (status != HAL_OK) {
DEBUG_ECHOLNPAIR("HAL_FLASHEx_Erase=", status);
DEBUG_ECHOLNPAIR("GetError=", HAL_FLASH_GetError());
@@ -204,7 +216,18 @@ bool PersistentStore::access_finish() {
return success;
#else
// The following was written for the STM32F4 but may work with other MCUs as well.
// Most STM32F4 flash does not allow reading from flash during erase operations.
// This takes about a second on a STM32F407 with a 128kB sector used as EEPROM.
// Interrupts during this time can have unpredictable results, such as killing Servo
// output. Servo output still glitches with interrupts disabled, but recovers after the
// erase.
PAUSE_SERVO_OUTPUT();
DISABLE_ISRS();
eeprom_buffer_flush();
ENABLE_ISRS();
RESUME_SERVO_OUTPUT();
eeprom_data_written = false;
#endif
}