storage and mfs_storage: introduce, move code
storage.cpp/h is common implentation for saving/loading settings to some storage mfs_storage.cpp/h is MFS specific implementation MFS related code is moved out of flash_main.cpp. Actually we should get rid of this file when rework is finished.
This commit is contained in:
parent
efafb76043
commit
5b749d6250
|
@ -43,6 +43,8 @@ CONTROLLERS_SRC_CPP = \
|
|||
$(CONTROLLERS_DIR)/engine_cycle/aux_valves.cpp \
|
||||
$(CONTROLLERS_DIR)/engine_cycle/fuel_schedule.cpp \
|
||||
$(CONTROLLERS_DIR)/flash_main.cpp \
|
||||
$(CONTROLLERS_DIR)/storage.cpp \
|
||||
$(CONTROLLERS_DIR)/mfs_storage.cpp \
|
||||
$(CONTROLLERS_DIR)/bench_test.cpp \
|
||||
$(CONTROLLERS_DIR)/can/obd2.cpp \
|
||||
$(CONTROLLERS_DIR)/can/can_verbose.cpp \
|
||||
|
|
|
@ -22,40 +22,12 @@
|
|||
#include "tunerstudio.h"
|
||||
#endif
|
||||
|
||||
#if EFI_STORAGE_MFS == TRUE
|
||||
#include "hal_mfs.h"
|
||||
#endif
|
||||
#include "storage.h"
|
||||
|
||||
#include "runtime_state.h"
|
||||
|
||||
#ifndef EFI_STORAGE_MFS_EXTERNAL
|
||||
#define EFI_STORAGE_MFS_EXTERNAL FALSE
|
||||
#endif
|
||||
|
||||
#ifndef EFI_FLASH_WRITE_THREAD
|
||||
#define EFI_FLASH_WRITE_THREAD FALSE
|
||||
#endif
|
||||
|
||||
// Sanity check
|
||||
#if (EFI_STORAGE_MFS_EXTERNAL == TRUE) && (EFI_FLASH_WRITE_THREAD == FALSE)
|
||||
#error EFI_FLASH_WRITE_THREAD should be enabled if MFS is used for external flash
|
||||
#endif
|
||||
|
||||
static bool needToWriteConfiguration = false;
|
||||
|
||||
/* if we use ChibiOS MFS for settings */
|
||||
#if EFI_STORAGE_MFS == TRUE
|
||||
|
||||
/* Managed Flash Storage driver */
|
||||
MFSDriver mfsd;
|
||||
|
||||
#define EFI_MFS_SETTINGS_RECORD_ID 1
|
||||
|
||||
extern void boardInitMfs(void);
|
||||
extern const MFSConfig *boardGetMfsConfig(void);
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* https://sourceforge.net/p/rusefi/tickets/335/
|
||||
*
|
||||
|
@ -157,14 +129,11 @@ bool burnWithoutFlash = false;
|
|||
|
||||
void writeToFlashNow() {
|
||||
engine->configBurnTimer.reset();
|
||||
bool isSuccess = false;
|
||||
|
||||
if (burnWithoutFlash) {
|
||||
needToWriteConfiguration = false;
|
||||
return;
|
||||
}
|
||||
efiPrintf("Writing pending configuration... %d bytes", sizeof(persistentState));
|
||||
efitick_t startNt = getTimeNowNt();
|
||||
|
||||
// Set up the container
|
||||
persistentState.size = sizeof(persistentState);
|
||||
|
@ -175,20 +144,22 @@ void writeToFlashNow() {
|
|||
// we just set a long timeout of 5 secs to wait until flash is done.
|
||||
startWatchdog(WATCHDOG_FLASH_TIMEOUT_MS);
|
||||
|
||||
// Do actual write
|
||||
#if EFI_STORAGE_MFS == TRUE
|
||||
mfs_error_t err;
|
||||
/* In case of MFS:
|
||||
* do we need to have two copies?
|
||||
* do we need to protect it with CRC? */
|
||||
|
||||
err = mfsWriteRecord(&mfsd, EFI_MFS_SETTINGS_RECORD_ID,
|
||||
sizeof(persistentState), (uint8_t *)&persistentState);
|
||||
|
||||
if (err >= MFS_NO_ERROR)
|
||||
isSuccess = true;
|
||||
if (storageWrite(EFI_SETTINGS_RECORD_ID, (uint8_t *)&persistentState, sizeof(persistentState)) == StorageStatus::Ok) {
|
||||
// Never used:
|
||||
//isSuccess = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if EFI_STORAGE_INT_FLASH == TRUE
|
||||
bool isSuccess = false;
|
||||
efiPrintf("Writing pending configuration... %d bytes", sizeof(persistentState));
|
||||
efitick_t startNt = getTimeNowNt();
|
||||
|
||||
// Flash two copies
|
||||
int result1 = eraseAndFlashCopy(getFlashAddrFirstCopy(), persistentState);
|
||||
int result2 = FLASH_RETURN_SUCCESS;
|
||||
|
@ -199,23 +170,19 @@ void writeToFlashNow() {
|
|||
|
||||
// handle success/failure
|
||||
isSuccess = (result1 == FLASH_RETURN_SUCCESS) && (result2 == FLASH_RETURN_SUCCESS);
|
||||
#endif
|
||||
|
||||
// restart the watchdog with the default timeout
|
||||
startWatchdog();
|
||||
|
||||
if (isSuccess) {
|
||||
efitick_t endNt = getTimeNowNt();
|
||||
int elapsed_Ms = US2MS(NT2US(endNt - startNt));
|
||||
|
||||
#if EFI_STORAGE_MFS == TRUE
|
||||
efiPrintf("FLASH_SUCCESS after %d mS MFS status %d", elapsed_Ms, err);
|
||||
#else
|
||||
efiPrintf("FLASH_SUCCESS after %d mS", elapsed_Ms);
|
||||
#endif
|
||||
} else {
|
||||
efiPrintf("Flashing failed");
|
||||
}
|
||||
#endif
|
||||
|
||||
// restart the watchdog with the default timeout
|
||||
startWatchdog();
|
||||
|
||||
resetMaxValues();
|
||||
|
||||
|
@ -227,28 +194,20 @@ static void doResetConfiguration() {
|
|||
resetConfigurationExt(engineConfiguration->engineType);
|
||||
}
|
||||
|
||||
enum class FlashState {
|
||||
Ok,
|
||||
CrcFailed,
|
||||
IncompatibleVersion,
|
||||
// all is well, but we're on a fresh chip with blank memory
|
||||
BlankChip,
|
||||
};
|
||||
|
||||
static FlashState validatePersistentState() {
|
||||
static StorageStatus validatePersistentState() {
|
||||
auto flashCrc = persistentState.getCrc();
|
||||
|
||||
if (flashCrc != persistentState.crc) {
|
||||
// If the stored crc is all 1s, that probably means the flash is actually blank, not that the crc failed.
|
||||
if (persistentState.crc == ((decltype(persistentState.crc))-1)) {
|
||||
return FlashState::BlankChip;
|
||||
return StorageStatus::NotFound;
|
||||
} else {
|
||||
return FlashState::CrcFailed;
|
||||
return StorageStatus::CrcFailed;
|
||||
}
|
||||
} else if (persistentState.version != FLASH_DATA_VERSION || persistentState.size != sizeof(persistentState)) {
|
||||
return FlashState::IncompatibleVersion;
|
||||
return StorageStatus::IncompatibleVersion;
|
||||
} else {
|
||||
return FlashState::Ok;
|
||||
return StorageStatus::Ok;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -256,12 +215,12 @@ static FlashState validatePersistentState() {
|
|||
/**
|
||||
* Read single copy of rusEFI configuration from interan flash using custom driver
|
||||
*/
|
||||
static FlashState readOneConfigurationCopy(flashaddr_t address) {
|
||||
static StorageStatus readOneConfigurationCopy(flashaddr_t address) {
|
||||
efiPrintf("readFromFlash %x", address);
|
||||
|
||||
// error already reported, return
|
||||
if (!address) {
|
||||
return FlashState::BlankChip;
|
||||
return StorageStatus::NotFound;
|
||||
}
|
||||
|
||||
intFlashRead(address, (char *) &persistentState, sizeof(persistentState));
|
||||
|
@ -276,28 +235,23 @@ static FlashState readOneConfigurationCopy(flashaddr_t address) {
|
|||
*
|
||||
* in this method we read first copy of configuration in flash. if that first copy has CRC or other issues we read second copy.
|
||||
*/
|
||||
static FlashState readConfiguration() {
|
||||
static StorageStatus readConfiguration() {
|
||||
#if EFI_STORAGE_MFS == TRUE
|
||||
size_t settings_size = sizeof(persistentState);
|
||||
mfs_error_t err = mfsReadRecord(&mfsd, EFI_MFS_SETTINGS_RECORD_ID,
|
||||
&settings_size, (uint8_t *)&persistentState);
|
||||
StorageStatus ret = storageRead(EFI_SETTINGS_RECORD_ID, (uint8_t *)&persistentState, sizeof(persistentState));
|
||||
|
||||
if (err >= MFS_NO_ERROR) {
|
||||
// readed size is not exactly the same
|
||||
if (settings_size != sizeof(persistentState))
|
||||
return FlashState::IncompatibleVersion;
|
||||
if (ret == StorageStatus::Ok) {
|
||||
return validatePersistentState();
|
||||
} else {
|
||||
return FlashState::BlankChip;
|
||||
}
|
||||
|
||||
return ret;
|
||||
#endif
|
||||
|
||||
#if EFI_STORAGE_INT_FLASH == TRUE
|
||||
auto firstCopyAddr = getFlashAddrFirstCopy();
|
||||
|
||||
FlashState firstCopy = readOneConfigurationCopy(firstCopyAddr);
|
||||
StorageStatus firstCopy = readOneConfigurationCopy(firstCopyAddr);
|
||||
|
||||
if (firstCopy == FlashState::Ok) {
|
||||
if (firstCopy == StorageStatus::Ok) {
|
||||
// First copy looks OK, don't even need to check second copy.
|
||||
return firstCopy;
|
||||
}
|
||||
|
@ -313,26 +267,27 @@ static FlashState readConfiguration() {
|
|||
#endif
|
||||
|
||||
// In case of neither of those cases, return that things went OK?
|
||||
return FlashState::Ok;
|
||||
return StorageStatus::Ok;
|
||||
}
|
||||
|
||||
void readFromFlash() {
|
||||
FlashState result = readConfiguration();
|
||||
StorageStatus result = readConfiguration();
|
||||
|
||||
switch (result) {
|
||||
case FlashState::CrcFailed:
|
||||
case StorageStatus::CrcFailed:
|
||||
warning(ObdCode::CUSTOM_ERR_FLASH_CRC_FAILED, "flash CRC failed");
|
||||
efiPrintf("Need to reset flash to default due to CRC mismatch");
|
||||
[[fallthrough]];
|
||||
case FlashState::BlankChip:
|
||||
case StorageStatus::NotFound:
|
||||
case StorageStatus::Failed:
|
||||
resetConfigurationExt(DEFAULT_ENGINE_TYPE);
|
||||
break;
|
||||
case FlashState::IncompatibleVersion:
|
||||
case StorageStatus::IncompatibleVersion:
|
||||
// Preserve engine type from old config
|
||||
efiPrintf("Resetting due to version mismatch but preserving engine type [%d]", (int)engineConfiguration->engineType);
|
||||
resetConfigurationExt(engineConfiguration->engineType);
|
||||
break;
|
||||
case FlashState::Ok:
|
||||
case StorageStatus::Ok:
|
||||
// At this point we know that CRC and version number is what we expect. Safe to assume it's a valid configuration.
|
||||
applyNonPersistentConfiguration();
|
||||
efiPrintf("Read valid configuration from flash!");
|
||||
|
@ -349,33 +304,9 @@ static void rewriteConfig() {
|
|||
writeToFlashNow();
|
||||
}
|
||||
|
||||
#if EFI_STORAGE_MFS == TRUE
|
||||
static void eraseConfig() {
|
||||
efitick_t startNt = getTimeNowNt();
|
||||
|
||||
mfs_error_t err;
|
||||
err = mfsErase(&mfsd);
|
||||
|
||||
efitick_t endNt = getTimeNowNt();
|
||||
int elapsed_Ms = US2MS(NT2US(endNt - startNt));
|
||||
efiPrintf("erase done %d mS err %d", elapsed_Ms, err);
|
||||
}
|
||||
#endif
|
||||
|
||||
void initFlash() {
|
||||
#if EFI_STORAGE_MFS == TRUE
|
||||
boardInitMfs();
|
||||
const MFSConfig *mfsConfig = boardGetMfsConfig();
|
||||
|
||||
/* MFS */
|
||||
mfsObjectInit(&mfsd);
|
||||
mfs_error_t err = mfsStart(&mfsd, mfsConfig);
|
||||
if (err < MFS_NO_ERROR) {
|
||||
/* hm...? */
|
||||
}
|
||||
|
||||
addConsoleAction("eraseconfig", eraseConfig);
|
||||
#endif
|
||||
// Init storage(s) if any
|
||||
initStorage();
|
||||
|
||||
addConsoleAction("readconfig", readFromFlash);
|
||||
/**
|
||||
|
|
|
@ -24,3 +24,5 @@ void setNeedToWriteConfiguration();
|
|||
*/
|
||||
bool getNeedToWriteConfiguration();
|
||||
void writeToFlashIfPending();
|
||||
|
||||
void settingsLtftRequestWriteToFlash();
|
||||
|
|
|
@ -0,0 +1,98 @@
|
|||
/**
|
||||
* @file mfs_storage.cpp
|
||||
* @brief Storage interface to ChibiOS MFS driver
|
||||
*
|
||||
* @date Jan 4, 2025
|
||||
* @author Andrey Gusakov
|
||||
*/
|
||||
|
||||
#include "pch.h"
|
||||
|
||||
#include "storage.h"
|
||||
|
||||
/* if we use ChibiOS MFS for settings */
|
||||
#if EFI_STORAGE_MFS == TRUE
|
||||
|
||||
#include "hal_mfs.h"
|
||||
|
||||
/* Managed Flash Storage driver */
|
||||
MFSDriver mfsd;
|
||||
|
||||
extern void boardInitMfs(void);
|
||||
extern const MFSConfig *boardGetMfsConfig(void);
|
||||
|
||||
StorageStatus mfsStorageWrite(int id, const uint8_t *ptr, size_t size) {
|
||||
efiPrintf("Writing storage ID %d ... %d bytes", id, size);
|
||||
efitick_t startNt = getTimeNowNt();
|
||||
|
||||
// TODO: add watchdog disable and enable in case MFS is on internal flash and one bank
|
||||
mfs_error_t err = mfsWriteRecord(&mfsd, id, size, ptr);
|
||||
|
||||
efitick_t endNt = getTimeNowNt();
|
||||
int elapsed_Ms = US2MS(NT2US(endNt - startNt));
|
||||
|
||||
if (err >= MFS_NO_ERROR) {
|
||||
efiPrintf("Write done with no errors after %d mS MFS status %d", elapsed_Ms, err);
|
||||
} else {
|
||||
efiPrintf("Write FAILED after %d with MFS status %d", elapsed_Ms, err);
|
||||
|
||||
return StorageStatus::Failed;
|
||||
}
|
||||
|
||||
return StorageStatus::Ok;
|
||||
}
|
||||
|
||||
StorageStatus mfsStorageRead(int id, uint8_t *ptr, size_t size) {
|
||||
efiPrintf("Reading storage ID %d ... %d bytes", id, size);
|
||||
|
||||
size_t readed_size = size;
|
||||
mfs_error_t err = mfsReadRecord(&mfsd, id, &readed_size, ptr);
|
||||
|
||||
if (err >= MFS_NO_ERROR) {
|
||||
if (readed_size != size) {
|
||||
efiPrintf("Incorrect size expected %d readed %d", size, readed_size);
|
||||
return StorageStatus::IncompatibleVersion;
|
||||
}
|
||||
efiPrintf("Reding done with no errors and MFS status %d", err);
|
||||
} else {
|
||||
efiPrintf("Read FAILED with MFS status %d", err);
|
||||
|
||||
// TODO: or corrupted?
|
||||
return StorageStatus::NotFound;
|
||||
}
|
||||
return StorageStatus::Ok;
|
||||
}
|
||||
|
||||
StorageStatus mfsStorageFormat()
|
||||
{
|
||||
efitick_t startNt = getTimeNowNt();
|
||||
|
||||
mfs_error_t err;
|
||||
err = mfsErase(&mfsd);
|
||||
|
||||
efitick_t endNt = getTimeNowNt();
|
||||
int elapsed_Ms = US2MS(NT2US(endNt - startNt));
|
||||
efiPrintf("MFS erase done %d mS err %d", elapsed_Ms, err);
|
||||
|
||||
return (err >= MFS_NO_ERROR) ? StorageStatus::Ok : StorageStatus::Failed;
|
||||
}
|
||||
|
||||
static void eraseStorage() {
|
||||
mfsStorageFormat();
|
||||
}
|
||||
|
||||
void initStorageMfs() {
|
||||
boardInitMfs();
|
||||
const MFSConfig *mfsConfig = boardGetMfsConfig();
|
||||
|
||||
/* MFS */
|
||||
mfsObjectInit(&mfsd);
|
||||
mfs_error_t err = mfsStart(&mfsd, mfsConfig);
|
||||
if (err < MFS_NO_ERROR) {
|
||||
/* hm...? */
|
||||
}
|
||||
|
||||
addConsoleAction("erasestorage", eraseStorage);
|
||||
}
|
||||
|
||||
#endif //EFI_STORAGE_MFS
|
|
@ -0,0 +1,17 @@
|
|||
/**
|
||||
* @file mfs_storage.h
|
||||
* @brief
|
||||
*
|
||||
* @date Jan 3, 2025
|
||||
* @author Andrey Gusakov
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "flash_main.h"
|
||||
|
||||
StorageStatus mfsStorageWrite(int id, const uint8_t *ptr, size_t size);
|
||||
StorageStatus mfsStorageRead(int id, uint8_t *ptr, size_t size);
|
||||
StorageStatus mfsStorageFormat();
|
||||
|
||||
void initStorageMfs();
|
|
@ -0,0 +1,45 @@
|
|||
/**
|
||||
* @file storage.cpp
|
||||
* @brief adapter for unify access to MFS and legacy 'internal flash' storage drivers
|
||||
*
|
||||
* @date Jan 4, 2025
|
||||
* @author Andrey Gusakov
|
||||
*/
|
||||
|
||||
#include "pch.h"
|
||||
|
||||
#include "storage.h"
|
||||
|
||||
/* If any setting storage is exist */
|
||||
#if EFI_CONFIGURATION_STORAGE
|
||||
|
||||
#if EFI_STORAGE_MFS == TRUE
|
||||
#include "mfs_storage.h"
|
||||
#endif
|
||||
|
||||
StorageStatus storageWrite(int id, const uint8_t *ptr, size_t size)
|
||||
{
|
||||
#if EFI_STORAGE_MFS == TRUE
|
||||
return mfsStorageWrite(id, ptr, size);
|
||||
#endif // EFI_STORAGE_MFS
|
||||
|
||||
return StorageStatus::Failed;
|
||||
}
|
||||
|
||||
StorageStatus storageRead(int id, uint8_t *ptr, size_t size)
|
||||
{
|
||||
#if EFI_STORAGE_MFS == TRUE
|
||||
return mfsStorageRead(id, ptr, size);
|
||||
#endif // EFI_STORAGE_MFS
|
||||
|
||||
return StorageStatus::NotFound;
|
||||
}
|
||||
|
||||
void initStorage()
|
||||
{
|
||||
#if EFI_STORAGE_MFS == TRUE
|
||||
initStorageMfs();
|
||||
#endif // EFI_STORAGE_MFS
|
||||
}
|
||||
|
||||
#endif // EFI_CONFIGURATION_STORAGE
|
|
@ -0,0 +1,41 @@
|
|||
/**
|
||||
* @file storage.h
|
||||
* @brief
|
||||
*
|
||||
* @date Jan 4, 2025
|
||||
* @author Andrey Gusakov
|
||||
*/
|
||||
|
||||
#ifndef EFI_STORAGE_MFS_EXTERNAL
|
||||
#define EFI_STORAGE_MFS_EXTERNAL FALSE
|
||||
#endif
|
||||
|
||||
#ifndef EFI_FLASH_WRITE_THREAD
|
||||
#define EFI_FLASH_WRITE_THREAD FALSE
|
||||
#endif
|
||||
|
||||
// Sanity check
|
||||
#if (EFI_STORAGE_MFS_EXTERNAL == TRUE) && (EFI_FLASH_WRITE_THREAD == FALSE)
|
||||
#error EFI_FLASH_WRITE_THREAD should be enabled if MFS is used for external flash
|
||||
#endif
|
||||
|
||||
// Storage status
|
||||
enum class StorageStatus {
|
||||
Ok,
|
||||
CrcFailed,
|
||||
IncompatibleVersion,
|
||||
// all is well, but we're on a fresh chip with blank memory
|
||||
NotFound,
|
||||
// Write failed
|
||||
Failed
|
||||
};
|
||||
|
||||
StorageStatus storageWrite(int id, const uint8_t *ptr, size_t size);
|
||||
StorageStatus storageRead(int id, uint8_t *ptr, size_t size);
|
||||
|
||||
void initStorage();
|
||||
|
||||
// IDs used as MFS record ids and internal RusEFI ids
|
||||
// Convert to enum/class
|
||||
#define EFI_SETTINGS_RECORD_ID 1
|
||||
#define EFI_LTFT_RECORD_ID 2
|
Loading…
Reference in New Issue