357 lines
10 KiB
C++

#include "eeprom.h"
I2C_eeprom ee(0x50, EEPROM_SIZE_BYTES);
configData_t ConfigData;
persistenceData_t PersistenceData;
bool eeAvailable = false;
bool checkEEPROMavailable();
bool ValidateEEPROM_Version();
bool MigrateEEPROM(uint8_t fromVersion);
void InitEEPROM()
{
ee.begin();
eeAvailable = checkEEPROMavailable();
eeAvailable = ValidateEEPROM_Version();
}
void EEPROM_Process()
{
if (eeAvailable == false)
return;
switch (globals.requestEEAction)
{
case EE_CFG_SAVE:
StoreConfig_EEPROM();
globals.requestEEAction = EE_IDLE;
Serial.println("Stored EEPROM CFG");
break;
case EE_CFG_LOAD:
GetConfig_EEPROM();
globals.requestEEAction = EE_IDLE;
Serial.println("Loaded EEPROM CFG");
break;
case EE_CFG_FORMAT:
FormatConfig_EEPROM();
globals.requestEEAction = EE_IDLE;
globals.systemStatus = sysStat_Shutdown;
Serial.println("Formated EEPROM CFG");
break;
case EE_PDS_SAVE:
StorePersistence_EEPROM();
globals.requestEEAction = EE_IDLE;
Serial.println("Stored EEPROM PDS");
break;
case EE_PDS_LOAD:
GetPersistence_EEPROM();
globals.requestEEAction = EE_IDLE;
Serial.println("Loaded EEPROM PDS");
break;
case EE_PDS_FORMAT:
FormatPersistence_EEPROM();
globals.requestEEAction = EE_IDLE;
Serial.println("Formated EEPROM PDS");
break;
case EE_FORMAT_ALL:
FormatConfig_EEPROM();
FormatPersistence_EEPROM();
globals.requestEEAction = EE_IDLE;
Serial.println("Formated EEPROM ALL");
break;
case EE_ALL_SAVE:
StorePersistence_EEPROM();
StoreConfig_EEPROM();
globals.requestEEAction = EE_IDLE;
Serial.println("Stored EEPROM ALL");
break;
case EE_IDLE:
default:
globals.requestEEAction = EE_IDLE;
}
}
void StoreConfig_EEPROM()
{
if (eeAvailable == false)
return;
ConfigData.checksum = 0;
ConfigData.checksum = Checksum_EEPROM((uint8_t *)&ConfigData, sizeof(ConfigData));
ee.updateBlock(startofConfigData, (uint8_t *)&ConfigData, sizeof(ConfigData));
}
void GetConfig_EEPROM()
{
if (eeAvailable == false)
return;
ee.readBlock(startofConfigData, (uint8_t *)&ConfigData, sizeof(ConfigData));
uint32_t checksum = ConfigData.checksum;
ConfigData.checksum = 0;
if (Checksum_EEPROM((uint8_t *)&ConfigData, sizeof(ConfigData)) != checksum)
{
MaintainDTC(DTC_EEPROM_CFG_BAD, DTC_CRITICAL, true);
}
ConfigData.checksum = checksum;
uint32_t ConfigSanityCheckResult = ConfigSanityCheck(false);
if (ConfigSanityCheckResult > 0)
{
MaintainDTC(DTC_EEPROM_CFG_SANITY, DTC_WARN, true, ConfigSanityCheckResult);
globals.requestEEAction = EE_CFG_SAVE;
}
}
void StorePersistence_EEPROM()
{
if (eeAvailable == false)
return;
if (PersistenceData.writeCycleCounter >= 0xFFF0)
MovePersistencePage_EEPROM(false);
else
PersistenceData.writeCycleCounter++;
PersistenceData.checksum = 0;
PersistenceData.checksum = Checksum_EEPROM((uint8_t *)&PersistenceData, sizeof(PersistenceData));
ee.updateBlock(globals.eePersistanceAdress, (uint8_t *)&PersistenceData, sizeof(PersistenceData));
}
void GetPersistence_EEPROM()
{
if (eeAvailable == false)
return;
ee.readBlock(0, (uint8_t *)&globals.eePersistanceAdress, sizeof(globals.eePersistanceAdress));
// if we got the StartAdress of Persistance and it's out of Range - we Reset it and store defaults
// otherwise we Read from eeprom and check if everything is correct
if (globals.eePersistanceAdress < startofPersistence || globals.eePersistanceAdress > ee.getDeviceSize())
{
MovePersistencePage_EEPROM(true);
FormatPersistence_EEPROM();
MaintainDTC(DTC_EEPROM_PDSADRESS_BAD, DTC_CRITICAL, true);
}
else
{
ee.readBlock(globals.eePersistanceAdress, (uint8_t *)&PersistenceData, sizeof(PersistenceData));
uint32_t checksum = PersistenceData.checksum;
PersistenceData.checksum = 0;
if (Checksum_EEPROM((uint8_t *)&PersistenceData, sizeof(PersistenceData)) != checksum)
{
MaintainDTC(DTC_EEPROM_PDS_BAD, DTC_CRITICAL, true);
}
PersistenceData.checksum = checksum;
}
}
void FormatConfig_EEPROM()
{
if (eeAvailable == false)
return;
Serial.println("Formatting Config-Partition");
ConfigData = ConfigData_defaults;
StoreConfig_EEPROM();
GetConfig_EEPROM();
}
void FormatPersistence_EEPROM()
{
if (eeAvailable == false)
return;
Serial.println("Formatting Persistance-Partition");
PersistenceData = {0};
StorePersistence_EEPROM();
GetPersistence_EEPROM();
}
void MovePersistencePage_EEPROM(boolean reset)
{
if (eeAvailable == false)
return;
globals.eePersistanceAdress = +sizeof(PersistenceData);
PersistenceData.writeCycleCounter = 0;
// check if we reached the End of the EEPROM and Startover at the beginning
if ((globals.eePersistanceAdress + sizeof(PersistenceData)) > ee.getDeviceSize() || reset)
{
globals.eePersistanceAdress = startofPersistence;
}
ee.updateBlock(0, (uint8_t *)&globals.eePersistanceAdress, sizeof(globals.eePersistanceAdress));
}
uint32_t Checksum_EEPROM(uint8_t const *data, size_t len)
{
if (data == NULL)
return 0;
uint32_t crc, mask;
crc = 0xFFFFFFFF;
while (len--)
{
crc ^= *data++;
for (uint8_t k = 0; k < 8; k++)
{
mask = -(crc & 1);
crc = (crc >> 1) ^ (0xEDB88320 & mask);
}
}
return ~crc;
}
void dumpEEPROM(uint16_t memoryAddress, uint16_t length)
{
#define BLOCK_TO_LENGTH 16
if (eeAvailable == false)
return;
char ascii_buf[BLOCK_TO_LENGTH + 1];
sprintf(ascii_buf, "%*s", BLOCK_TO_LENGTH, "ASCII");
Serial.print(PSTR("\nAddress "));
for (int x = 0; x < BLOCK_TO_LENGTH; x++)
Serial.printf("%3d", x);
memoryAddress = memoryAddress / BLOCK_TO_LENGTH * BLOCK_TO_LENGTH;
length = (length + BLOCK_TO_LENGTH - 1) / BLOCK_TO_LENGTH * BLOCK_TO_LENGTH;
for (unsigned int i = 0; i < length; i++)
{
int blockpoint = memoryAddress % BLOCK_TO_LENGTH;
if (blockpoint == 0)
{
ascii_buf[BLOCK_TO_LENGTH] = 0;
Serial.printf(" %s", ascii_buf);
Serial.printf("\n0x%05X:", memoryAddress);
}
ascii_buf[blockpoint] = ee.readByte(memoryAddress);
Serial.printf(" %02X", ascii_buf[blockpoint]);
if (ascii_buf[blockpoint] < 0x20 || ascii_buf[blockpoint] > 0x7E)
ascii_buf[blockpoint] = '.';
memoryAddress++;
}
Serial.println();
}
bool checkEEPROMavailable()
{
if (!ee.isConnected())
{
MaintainDTC(DTC_NO_EEPROM_FOUND, DTC_CRITICAL, true);
return false;
}
return true;
}
uint32_t ConfigSanityCheck(bool autocorrect)
{
uint32_t setting_reset_bits = 0;
if ((ConfigData.batteryType != BATTERY_LIPO_2S) || (ConfigData.batteryType != BATTERY_LIPO_3S))
{
setting_reset_bits = setting_reset_bits | (1 << 0);
if (autocorrect)
ConfigData.batteryType = ConfigData_defaults.batteryType;
}
return setting_reset_bits;
}
bool ValidateEEPROM_Version()
{
if (eeAvailable == false)
return false;
uint8_t EEPROMVersionOnChip = ee.readByte(startofConfigData);
if (EEPROMVersionOnChip < ConfigData_defaults.EEPROM_Version)
{
Serial.printf("EEPROM Image Version is %d, but %d expected - trying to migrate\n", EEPROMVersionOnChip, ConfigData_defaults.EEPROM_Version);
if (!MigrateEEPROM(EEPROMVersionOnChip))
{
Serial.print("Error\n");
MaintainDTC(DTC_EEPROM_MIGRATE_FAILED, DTC_CRITICAL, true, EEPROMVersionOnChip);
return false;
}
else
{
Serial.print("Success\n");
}
}
return true;
}
bool MigrateEEPROM(uint8_t fromVersion)
{
uint16_t persistanceMarker_onChip;
switch (fromVersion)
{
// Version 1 EEPROM Layout: startAdress size (byte)
// const uint16_t startofConfigData = 16 16
// const uint16_t startofPersistence = 32 24
//
// typedef struct
// {
// uint8_t EEPROM_Version = 1; 16 1
// batteryType_t batteryType = BATTERY_UNDEFINED; 17 4
// bool active_faction_on_reboot = false; 21 1
// uint32_t checksum = 0; 22 4
// } configData_t;
//
// typedef struct offset
// {
// uint32_t writeCycleCounter = 0; 0 4
// uint32_t faction_1_timer = 0; 4 4
// uint32_t faction_2_timer = 0; 8 4
// uint32_t faction_3_timer = 0; 12 4
// factions_t activeFaction = NONE; 16 4
// uint32_t checksum = 0; 20 4
// } persistenceData_t;
case 1:
// Migrate Persistance-Data
ee.readBlock(0, (uint8_t *)&persistanceMarker_onChip, sizeof(uint16_t));
if (persistanceMarker_onChip < startofPersistence)
{
ee.readBlock(persistanceMarker_onChip + 0, (uint8_t *)&PersistenceData.writeCycleCounter, 4);
ee.readBlock(persistanceMarker_onChip + 4, (uint8_t *)&PersistenceData.faction_1_timer, 4);
ee.readBlock(persistanceMarker_onChip + 8, (uint8_t *)&PersistenceData.faction_2_timer, 4);
ee.readBlock(persistanceMarker_onChip + 12, (uint8_t *)&PersistenceData.faction_3_timer, 4);
ee.readBlock(persistanceMarker_onChip + 16, (uint8_t *)&PersistenceData.activeFaction, 4);
ee.readBlock(persistanceMarker_onChip + 20, (uint8_t *)&PersistenceData.checksum, 4);
MovePersistencePage_EEPROM(true);
StorePersistence_EEPROM();
}
// Migrate Config-Data and set defaults for Values which doesn't exists in this earlier Version
ConfigData.EEPROM_Version = ConfigData_defaults.EEPROM_Version;
strncpy(ConfigData.Faction_1_Name, ConfigData_defaults.Faction_1_Name, sizeof(ConfigData.Faction_1_Name));
strncpy(ConfigData.Faction_2_Name, ConfigData_defaults.Faction_2_Name, sizeof(ConfigData.Faction_2_Name));
strncpy(ConfigData.Faction_3_Name, ConfigData_defaults.Faction_3_Name, sizeof(ConfigData.Faction_3_Name));
ee.readBlock(17, (uint8_t *)&ConfigData.batteryType, 4);
ee.readBlock(21, (uint8_t *)&ConfigData.active_faction_on_reboot, 1);
StoreConfig_EEPROM();
return true;
break;
default:
return false;
break;
}
}