rusefi-1/firmware/hw_layer/ports/cypress/backup_ram.cpp

81 lines
2.4 KiB
C++
Raw Normal View History

2020-09-07 08:57:20 -07:00
/**
* @file backup_ram.cpp
* @brief NVRAM emulation using Internal Flash (flash_int driver)
2020-09-07 08:57:20 -07:00
*
* @date May 22, 2020
*/
#include "pch.h"
2020-09-07 08:57:20 -07:00
#include "backup_ram.h"
#include "flash_int.h"
2020-09-07 08:57:20 -07:00
#define BACKUP_NOT_INITIALIZED 0xFFFF
#define BACKUP_SAVED 0x5555
#define BACKUP_PENDING 0x0000
// we store the flash state at 0 index + all backup variables
static volatile uint32_t backupRam[BACKUP_RAM_NUM + 1];
static bool wasLoaded = false;
// these offsets are indices in the 'BACKUP_FLASH_ADDR' (32-bit array)
static const int backupStateOffset = 0, backupDataOffset = 1;
const size_t backupSize = (BACKUP_RAM_NUM + 1) * sizeof(uint32_t);
static void backupInit(void) {
static_assert(backupSize <= BACKUP_FLASH_SIZE, "Backup flash overflow");
// first, load the whole buffer into the memory
intFlashRead((flashaddr_t)BACKUP_FLASH_ADDR, (char *)backupRam, backupSize);
2020-09-07 08:57:20 -07:00
// check if we have a reliable properly saved data
if (backupRam[backupStateOffset] != BACKUP_SAVED) {
// zero is the default value
memset((void *)backupRam, 0, backupSize);
}
// we cannot trust the saved data anymore, until it's saved in backupRamFlush()
// so we mark is as 'pending'
backupRam[backupStateOffset] = BACKUP_PENDING;
intFlashWrite(BACKUP_FLASH_ADDR + backupStateOffset, (char *)backupRam, sizeof(backupRam[backupStateOffset]));
2020-09-07 08:57:20 -07:00
wasLoaded = true;
}
uint32_t backupRamLoad(backup_ram_e idx) {
// this is executed only once during the firmware init
if (!wasLoaded) {
backupInit();
}
return backupRam[idx + backupDataOffset];
}
void backupRamSave(backup_ram_e idx, uint32_t value) {
// this is executed only once during the firmware init
if (!wasLoaded) {
backupInit();
}
backupRam[idx + backupDataOffset] = value;
}
void backupRamFlush(void) {
// todo: implement an incremental "append-to-the-end" algorithm to minimize sector erasings?
// Enter the critical zone
syssts_t sts = chSysGetStatusAndLockX();
// rewrite the whole sector
intFlashErase((flashaddr_t)BACKUP_FLASH_ADDR, BACKUP_FLASH_SIZE);
2020-09-07 08:57:20 -07:00
// mark the data as valid & saved
backupRam[backupStateOffset] = BACKUP_SAVED;
// save the data to the flash
intFlashWrite((flashaddr_t)BACKUP_FLASH_ADDR, (char *)backupRam, backupSize);
2020-09-07 08:57:20 -07:00
// Leaving the critical zone
chSysRestoreStatusX(sts);
// there should not be any backup-RAM activity after this call
// but if there is, at least try to reinitialize...
wasLoaded = false;
}