Support load/save configuration to external flash
Fixes to 6a3e7d8e6 as the flash partition code had changed during the merge to master.
This commit is contained in:
parent
a6c07b046b
commit
cf1ce1a67b
1
Makefile
1
Makefile
|
@ -677,6 +677,5 @@ check-platform-included:
|
|||
# rebuild everything when makefile changes
|
||||
$(TARGET_OBJS): Makefile $(TARGET_DIR)/target.mk $(wildcard make/*)
|
||||
|
||||
|
||||
# include auto-generated dependencies
|
||||
-include $(TARGET_DEPS)
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#include "pg/pg.h"
|
||||
#include "fc/config.h"
|
||||
|
||||
#include "drivers/flash.h"
|
||||
#include "drivers/system.h"
|
||||
|
||||
static uint16_t eepromConfigSize;
|
||||
|
@ -78,6 +79,35 @@ typedef struct {
|
|||
uint32_t word;
|
||||
} PG_PACKED packingTest_t;
|
||||
|
||||
#ifdef EEPROM_IN_EXTERNAL_FLASH
|
||||
bool loadEEPROMFromExternalFlash(void)
|
||||
{
|
||||
const flashPartition_t *flashPartition = flashPartitionFindByType(FLASH_PARTITION_TYPE_CONFIG);
|
||||
const flashGeometry_t *flashGeometry = flashGetGeometry();
|
||||
|
||||
uint32_t flashStartAddress = flashPartition->startSector * flashGeometry->sectorSize;
|
||||
|
||||
uint32_t totalBytesRead = 0;
|
||||
uint32_t bytesRead = 0;
|
||||
|
||||
bool success;
|
||||
|
||||
do {
|
||||
bytesRead = flashReadBytes(flashStartAddress + totalBytesRead, &eepromData[totalBytesRead], EEPROM_SIZE - totalBytesRead);
|
||||
totalBytesRead += bytesRead;
|
||||
success = (totalBytesRead == EEPROM_SIZE);
|
||||
} while (!success && bytesRead);
|
||||
|
||||
return success;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef EEPROM_IN_FILE
|
||||
void loadEEPROMFromFile(void) {
|
||||
FLASH_Unlock(); // load existing config file into eepromData
|
||||
}
|
||||
#endif
|
||||
|
||||
void initEEPROM(void)
|
||||
{
|
||||
// Verify that this architecture packs as expected.
|
||||
|
@ -89,7 +119,15 @@ void initEEPROM(void)
|
|||
STATIC_ASSERT(sizeof(configRecord_t) == 6, record_size_failed);
|
||||
|
||||
#ifdef EEPROM_IN_FILE
|
||||
FLASH_Unlock(); // load existing config file into eepromData
|
||||
loadEEPROMFromFile();
|
||||
#endif
|
||||
|
||||
#ifdef EEPROM_IN_EXTERNAL_FLASH
|
||||
bool eepromLoaded = loadEEPROMFromExternalFlash();
|
||||
if (!eepromLoaded) {
|
||||
// Flash read failed - just die now
|
||||
failureMode(FAILURE_FLASH_READ_FAILED);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -159,6 +197,11 @@ uint16_t getEEPROMConfigSize(void)
|
|||
|
||||
size_t getEEPROMStorageSize(void)
|
||||
{
|
||||
#if defined(EEPROM_IN_EXTERNAL_FLASH)
|
||||
|
||||
const flashPartition_t *flashPartition = flashPartitionFindByType(FLASH_PARTITION_TYPE_CONFIG);
|
||||
return FLASH_PARTITION_SECTOR_COUNT(flashPartition) * flashGetGeometry()->sectorSize;
|
||||
#endif
|
||||
#ifdef EEPROM_IN_RAM
|
||||
return EEPROM_SIZE;
|
||||
#else
|
||||
|
@ -268,9 +311,15 @@ void writeConfigToEEPROM(void)
|
|||
for (int attempt = 0; attempt < 3 && !success; attempt++) {
|
||||
if (writeSettingsToEEPROM()) {
|
||||
success = true;
|
||||
|
||||
#ifdef EEPROM_IN_EXTERNAL_FLASH
|
||||
// copy it back from flash to the in-memory buffer.
|
||||
success = loadEEPROMFromExternalFlash();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (success && isEEPROMVersionValid() && isEEPROMStructureValid()) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -23,9 +23,13 @@
|
|||
#include "platform.h"
|
||||
|
||||
#include "drivers/system.h"
|
||||
#include "drivers/flash.h"
|
||||
|
||||
#include "config/config_streamer.h"
|
||||
|
||||
#if defined(STM32H750xx) && !(defined(EEPROM_IN_EXTERNAL_FLASH) || defined(EEPROM_IN_RAM))
|
||||
#error "STM32750xx only has one flash page which contains the bootloader, no spare flash pages available, use external storage for persistent config or ram for target testing"
|
||||
#endif
|
||||
// @todo this is not strictly correct for F4/F7, where sector sizes are variable
|
||||
#if !defined(FLASH_PAGE_SIZE)
|
||||
// F1
|
||||
|
@ -74,12 +78,11 @@ void config_streamer_init(config_streamer_t *c)
|
|||
|
||||
void config_streamer_start(config_streamer_t *c, uintptr_t base, int size)
|
||||
{
|
||||
// base must start at FLASH_PAGE_SIZE boundary
|
||||
// base must start at FLASH_PAGE_SIZE boundary when using embedded flash.
|
||||
c->address = base;
|
||||
c->size = size;
|
||||
if (!c->unlocked) {
|
||||
|
||||
#if defined(EEPROM_IN_RAM)
|
||||
#if defined(EEPROM_IN_RAM) || defined(EEPROM_IN_EXTERNAL_FLASH)
|
||||
// NOP
|
||||
#elif defined(EEPROM_IN_FLASH) || defined(EEPROM_IN_FILE)
|
||||
#if defined(STM32F7) || defined(STM32H7)
|
||||
|
@ -91,7 +94,7 @@ void config_streamer_start(config_streamer_t *c, uintptr_t base, int size)
|
|||
c->unlocked = true;
|
||||
}
|
||||
|
||||
#if defined(EEPROM_IN_RAM) || defined(EEPROM_IN_FILE)
|
||||
#if defined(EEPROM_IN_RAM) || defined(EEPROM_IN_FILE) || defined(EEPROM_IN_EXTERNAL_FLASH)
|
||||
// NOP
|
||||
#elif defined(EEPROM_IN_FLASH)
|
||||
#if defined(STM32F10X)
|
||||
|
@ -113,7 +116,7 @@ void config_streamer_start(config_streamer_t *c, uintptr_t base, int size)
|
|||
c->err = 0;
|
||||
}
|
||||
|
||||
#if defined(EEPROM_IN_RAM)
|
||||
#if defined(EEPROM_IN_RAM) || defined(EEPROM_IN_EXTERNAL_FLASH)
|
||||
// No flash sector method required.
|
||||
#elif defined(EEPROM_IN_FLASH)
|
||||
#if defined(STM32F745xx) || defined(STM32F746xx) || defined(STM32F765xx)
|
||||
|
@ -342,12 +345,48 @@ static void getFLASHSectorForEEPROM(uint32_t *bank, uint32_t *sector)
|
|||
#endif
|
||||
#endif
|
||||
|
||||
// FIXME the return values are currently magic numbers
|
||||
static int write_word(config_streamer_t *c, config_streamer_buffer_align_type_t *buffer)
|
||||
{
|
||||
if (c->err != 0) {
|
||||
return c->err;
|
||||
}
|
||||
#if defined(EEPROM_IN_RAM)
|
||||
#if defined(EEPROM_IN_EXTERNAL_FLASH)
|
||||
|
||||
uint32_t dataOffset = (uint32_t)(c->address - (uintptr_t)&eepromData[0]);
|
||||
|
||||
const flashPartition_t *flashPartition = flashPartitionFindByType(FLASH_PARTITION_TYPE_CONFIG);
|
||||
const flashGeometry_t *flashGeometry = flashGetGeometry();
|
||||
|
||||
uint32_t flashStartAddress = flashPartition->startSector * flashGeometry->sectorSize;
|
||||
uint32_t flashOverflowAddress = ((flashPartition->endSector + 1) * flashGeometry->sectorSize); // +1 to sector for inclusive
|
||||
|
||||
uint32_t flashAddress = flashStartAddress + dataOffset;
|
||||
if (flashAddress + CONFIG_STREAMER_BUFFER_SIZE > flashOverflowAddress) {
|
||||
return -3; // address is past end of partition
|
||||
}
|
||||
|
||||
uint32_t flashSectorSize = flashGeometry->sectorSize;
|
||||
uint32_t flashPageSize = flashGeometry->pageSize;
|
||||
|
||||
bool onPageBoundary = (flashAddress % flashPageSize == 0);
|
||||
if (onPageBoundary) {
|
||||
|
||||
bool firstPage = (flashAddress == flashStartAddress);
|
||||
if (!firstPage) {
|
||||
flashPageProgramFinish();
|
||||
}
|
||||
|
||||
if (flashAddress % flashSectorSize == 0) {
|
||||
flashEraseSector(flashAddress);
|
||||
}
|
||||
|
||||
flashPageProgramBegin(flashAddress);
|
||||
}
|
||||
|
||||
flashPageProgramContinue((uint8_t *)buffer, CONFIG_STREAMER_BUFFER_SIZE);
|
||||
|
||||
#elif defined(EEPROM_IN_RAM)
|
||||
if (c->address == (uintptr_t)&eepromData[0]) {
|
||||
memset(eepromData, 0, sizeof(eepromData));
|
||||
}
|
||||
|
@ -470,7 +509,9 @@ int config_streamer_flush(config_streamer_t *c)
|
|||
int config_streamer_finish(config_streamer_t *c)
|
||||
{
|
||||
if (c->unlocked) {
|
||||
#if defined(EEPROM_IN_RAM)
|
||||
#if defined(EEPROM_IN_EXTERNAL_FLASH)
|
||||
flashFlush();
|
||||
#elif defined(EEPROM_IN_RAM)
|
||||
// NOP
|
||||
#elif defined(EEPROM_IN_FILE)
|
||||
FLASH_Lock();
|
||||
|
|
|
@ -26,7 +26,10 @@
|
|||
// Streams data out to the EEPROM, padding to the write size as
|
||||
// needed, and updating the checksum as it goes.
|
||||
|
||||
#ifdef STM32H7
|
||||
#ifdef EEPROM_IN_EXTERNAL_FLASH
|
||||
#define CONFIG_STREAMER_BUFFER_SIZE 8 // Must not be greater than the smallest flash page size of all compiled-in flash devices.
|
||||
typedef uint32_t config_streamer_buffer_align_type_t;
|
||||
#elif defined(STM32H7)
|
||||
#define CONFIG_STREAMER_BUFFER_SIZE 32 // Flash word = 256-bits
|
||||
typedef uint64_t config_streamer_buffer_align_type_t;
|
||||
#else
|
||||
|
|
|
@ -32,7 +32,8 @@ typedef enum {
|
|||
FAILURE_ACC_INCOMPATIBLE,
|
||||
FAILURE_INVALID_EEPROM_CONTENTS,
|
||||
FAILURE_FLASH_WRITE_FAILED,
|
||||
FAILURE_GYRO_INIT_FAILED
|
||||
FAILURE_GYRO_INIT_FAILED,
|
||||
FAILURE_FLASH_READ_FAILED
|
||||
} failureMode_e;
|
||||
|
||||
#define WARNING_FLASH_DURATION_MS 50
|
||||
|
|
|
@ -206,6 +206,46 @@ static IO_t busSwitchResetPin = IO_NONE;
|
|||
}
|
||||
#endif
|
||||
|
||||
static void configureSPIAndQuadSPI(void)
|
||||
{
|
||||
#ifdef USE_SPI
|
||||
spiPinConfigure(spiPinConfig(0));
|
||||
#endif
|
||||
|
||||
sensorsPreInit();
|
||||
|
||||
#ifdef USE_SPI
|
||||
spiPreinit();
|
||||
|
||||
#ifdef USE_SPI_DEVICE_1
|
||||
spiInit(SPIDEV_1);
|
||||
#endif
|
||||
#ifdef USE_SPI_DEVICE_2
|
||||
spiInit(SPIDEV_2);
|
||||
#endif
|
||||
#ifdef USE_SPI_DEVICE_3
|
||||
spiInit(SPIDEV_3);
|
||||
#endif
|
||||
#ifdef USE_SPI_DEVICE_4
|
||||
spiInit(SPIDEV_4);
|
||||
#endif
|
||||
#ifdef USE_SPI_DEVICE_5
|
||||
spiInit(SPIDEV_5);
|
||||
#endif
|
||||
#ifdef USE_SPI_DEVICE_6
|
||||
spiInit(SPIDEV_6);
|
||||
#endif
|
||||
#endif // USE_SPI
|
||||
|
||||
#ifdef USE_QUADSPI
|
||||
quadSpiPinConfigure(quadSpiConfig(0));
|
||||
|
||||
#ifdef USE_QUADSPI_DEVICE_1
|
||||
quadSpiInit(QUADSPIDEV_1);
|
||||
#endif
|
||||
#endif // USE_QUAD_SPI
|
||||
}
|
||||
|
||||
|
||||
void init(void)
|
||||
{
|
||||
|
@ -252,6 +292,43 @@ void init(void)
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef EEPROM_IN_EXTERNAL_FLASH
|
||||
|
||||
//
|
||||
// Config on external flash presents an issue with pin configuration since the pin and flash configs for the
|
||||
// external flash are in the config which is on a chip which we can't read yet!
|
||||
//
|
||||
// FIXME We need to add configuration into the bootloader image that can be read by the firmware.
|
||||
// it's currently possible firmware and bootloader to become mismatched if the user changes them.
|
||||
// This would cause undefined behaviour once the config is loaded. so for now, users must NOT change flash/pin configs needed for
|
||||
// the system to boot and/or to save the config.
|
||||
//
|
||||
// note that target specific FLASH/SPI/QUADSPI configs are
|
||||
// also not supported in USE_TARGET_CONFIG/targetConfigure() when using EEPROM_IN_EXTERNAL_FLASH.
|
||||
//
|
||||
|
||||
//
|
||||
// IMPORTANT: all default flash and pin configurations must be valid for the target after pgResetAll() is called.
|
||||
// Target designers must ensure other devices connected the same SPI/QUADSPI interface as the flash chip do not
|
||||
// cause communication issues with the flash chip. e.g. use external pullups on SPI/QUADSPI CS lines.
|
||||
//
|
||||
pgResetAll();
|
||||
|
||||
#ifdef TARGET_BUS_INIT
|
||||
#error "EEPROM_IN_EXTERNAL_FLASH and TARGET_BUS_INIT are mutually exclusive"
|
||||
#endif
|
||||
|
||||
configureSPIAndQuadSPI();
|
||||
|
||||
#ifndef USE_FLASH_CHIP
|
||||
#error "EEPROM_IN_EXTERNAL_FLASH requires USE_FLASH_CHIP to be defined."
|
||||
#endif
|
||||
|
||||
flashInit(flashConfig());
|
||||
|
||||
#endif // EEPROM_IN_EXTERNAL_FLASH
|
||||
|
||||
|
||||
initEEPROM();
|
||||
|
||||
ensureEEPROMStructureIsValid();
|
||||
|
@ -430,48 +507,15 @@ void init(void)
|
|||
initInverters(serialPinConfig());
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef TARGET_BUS_INIT
|
||||
targetBusInit();
|
||||
|
||||
#else
|
||||
|
||||
#ifdef USE_SPI
|
||||
spiPinConfigure(spiPinConfig(0));
|
||||
#endif
|
||||
|
||||
sensorsPreInit();
|
||||
|
||||
#ifdef USE_SPI
|
||||
spiPreinit();
|
||||
|
||||
#ifdef USE_SPI_DEVICE_1
|
||||
spiInit(SPIDEV_1);
|
||||
#endif
|
||||
#ifdef USE_SPI_DEVICE_2
|
||||
spiInit(SPIDEV_2);
|
||||
#endif
|
||||
#ifdef USE_SPI_DEVICE_3
|
||||
spiInit(SPIDEV_3);
|
||||
#endif
|
||||
#ifdef USE_SPI_DEVICE_4
|
||||
spiInit(SPIDEV_4);
|
||||
#endif
|
||||
#ifdef USE_SPI_DEVICE_5
|
||||
spiInit(SPIDEV_5);
|
||||
#endif
|
||||
#ifdef USE_SPI_DEVICE_6
|
||||
spiInit(SPIDEV_6);
|
||||
#endif
|
||||
#endif // USE_SPI
|
||||
|
||||
#ifdef USE_QUADSPI
|
||||
quadSpiPinConfigure(quadSpiConfig(0));
|
||||
|
||||
#ifdef USE_QUADSPI_DEVICE_1
|
||||
quadSpiInit(QUADSPIDEV_1);
|
||||
#endif
|
||||
#endif // USE_QUAD_SPI
|
||||
|
||||
#ifndef EEPROM_IN_EXTERNAL_FLASH
|
||||
configureSPIAndQuadSPI();
|
||||
#endif // EEPROM_IN_EXTERNAL_FLASH
|
||||
|
||||
#ifdef USE_USB_MSC
|
||||
/* MSC mode will start after init, but will not allow scheduler to run,
|
||||
|
@ -715,12 +759,14 @@ void init(void)
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifndef EEPROM_IN_EXTERNAL_FLASH
|
||||
#ifdef USE_FLASH_CHIP
|
||||
flashInit(flashConfig());
|
||||
#endif
|
||||
#endif
|
||||
#ifdef USE_FLASHFS
|
||||
flashfsInit();
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef USE_BLACKBOX
|
||||
#ifdef USE_SDCARD
|
||||
|
|
|
@ -338,7 +338,7 @@
|
|||
#undef USE_ESCSERIAL
|
||||
#endif
|
||||
|
||||
#if defined(EEPROM_IN_RAM) || defined(EEPROM_IN_FILE)
|
||||
#if defined(EEPROM_IN_RAM) || defined(EEPROM_IN_FILE) || defined(EEPROM_IN_EXTERNAL_FLASH)
|
||||
#ifndef EEPROM_SIZE
|
||||
#define EEPROM_SIZE 4096
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue