StorageOnFlash_Flagchip_FC7240/Src/StorageOnFlashFlagchip.c

157 lines
5.3 KiB
C

//
// Created by cfif on 07.10.22.
//
#include "InternalFlashPage.h"
#include "StorageOnFlashFlagchip.h"
#define LOGGER env->logger
#define LOG_SIGN "Storage"
static uint32_t xStorageOnFlashArtery_Crc(uint8_t *data, size_t len) {
uint32_t crc = 0;
uint8_t *end = data + len;
while (data < end) {
crc += *data;
++data;
}
return crc;
}
static uint32_t xStorageOnFlashArtery_CrcFlash(uint8_t *addressOnFlash, size_t len) {
uint32_t crc = 0;
size_t left = len;
uint8_t *end = addressOnFlash + len;
uint32_t word;
while (addressOnFlash < end) {
word = iInternalFlashPage_ReadWord((uint32_t) addressOnFlash);
for (uint8_t sub_byte = 0; (sub_byte < 4) && (left); ++sub_byte) {
crc += ((uint8_t *) &word)[sub_byte];
--left;
}
addressOnFlash += 4;
}
return crc;
}
static eStorageStatus
xStorageOnFlashFlagchip_DumpOn(
tStorageOnFlashFlagchip *env,
uint32_t dataCrc,
uint32_t pageAddress,
void *data,
size_t size
) {
// if (!bInternalFlashPage_Clear(pageAddress)) {
// return STORAGE_ERR_DEVICE;
// }
//
// size_t dataSizeOnFlash = sInternalFlashPage_Write(pageAddress, 0x0, env->data, env->size);
size_t dataSizeOnFlash = bInternalFlashPage_DumpFromRam(pageAddress, data, size);
if (dataSizeOnFlash < size) {
return STORAGE_ERR_DEVICE;
}
uint64_t dataCrc64 = dataCrc;
if (sInternalFlashPage_Write(pageAddress, dataSizeOnFlash, (uint8_t *) &dataCrc64, 8) != 8) {
return STORAGE_ERR_DEVICE;
}
uint32_t flashCalcCrc = xStorageOnFlashArtery_CrcFlash((uint8_t *) pageAddress, size );
uint32_t flashReedCrc = iInternalFlashPage_ReadWord(pageAddress + dataSizeOnFlash);
if ((flashCalcCrc == flashReedCrc) && (flashCalcCrc == dataCrc)) {
return STORAGE_OK;
} else {
return STORAGE_ERR_DATA;
}
}
static uint8_t xStorageOnFlashFlagchip_Dump(tStorageOnFlashFlagchip *env, void *data, size_t size) {
size = size - 8;
uint32_t crc = xStorageOnFlashArtery_Crc(data, size);
if (xStorageOnFlashFlagchip_DumpOn(env, crc, env->recoveryFlashPageAddress, data, size) != STORAGE_OK) {
return STORAGE_ERR_DEVICE;
}
if (xStorageOnFlashFlagchip_DumpOn(env, crc, env->mainFlashPageAddress, data, size) != STORAGE_OK) {
return STORAGE_ERR_DEVICE;
}
return STORAGE_OK;
}
eStorageStatus xStorageOnFlashFlagchip_Load(tStorageOnFlashFlagchip *env, void *data, size_t size) {
size = size - 8;
size_t dataSizeOnFlash = size;//(size + 3) & (~3); // выравниваем до кратного 4 (целое количество слов)
uint32_t recoveryCrcCalc = xStorageOnFlashArtery_CrcFlash((uint8_t *) env->recoveryFlashPageAddress, size);
uint32_t recoveryCrcReed = iInternalFlashPage_ReadWord(env->recoveryFlashPageAddress + dataSizeOnFlash);
LoggerFormatInfo(LOGGER, LOG_SIGN, "Crc recovery page (calc): 0x%08X", recoveryCrcCalc)
LoggerFormatInfo(LOGGER, LOG_SIGN, "Crc recovery page (flash): 0x%08X", recoveryCrcReed)
uint32_t mainCrcCalc = xStorageOnFlashArtery_CrcFlash((uint8_t *) env->mainFlashPageAddress, size);
uint32_t mainCrcReed = iInternalFlashPage_ReadWord(env->mainFlashPageAddress + dataSizeOnFlash);
LoggerFormatInfo(LOGGER, LOG_SIGN, "Crc main page (calc): 0x%08X", mainCrcCalc)
LoggerFormatInfo(LOGGER, LOG_SIGN, "Crc main page (flash): 0x%08X", mainCrcReed)
bool recoveryCrcOk = (recoveryCrcCalc == recoveryCrcReed);
bool mainCrcOk = (mainCrcReed == mainCrcCalc);
if (recoveryCrcOk && mainCrcOk) {
if (recoveryCrcReed == mainCrcReed) {
sInternalFlashPage_Read(env->mainFlashPageAddress, 0x0, data, size);
return STORAGE_OK;
} else {
LoggerInfoStatic(LOGGER, LOG_SIGN, "Data recovery main page (main page <- recovery) ")
sInternalFlashPage_Read(env->recoveryFlashPageAddress, 0x0, data, size);
return xStorageOnFlashFlagchip_DumpOn(env, recoveryCrcCalc, env->mainFlashPageAddress, data, size);
}
} else if (recoveryCrcOk || mainCrcOk) {
if (recoveryCrcOk) {
LoggerInfoStatic(LOGGER, LOG_SIGN, "Data recovery main page (main page <- recovery)")
sInternalFlashPage_Read(env->recoveryFlashPageAddress, 0x0, data, size);
return xStorageOnFlashFlagchip_DumpOn(env, recoveryCrcCalc, env->mainFlashPageAddress, data, size);
} else {
LoggerInfoStatic(LOGGER, LOG_SIGN, "Data recovery recovery page (main page -> recovery)")
sInternalFlashPage_Read(env->mainFlashPageAddress, 0x0, data, size);
return xStorageOnFlashFlagchip_DumpOn(env, mainCrcCalc, env->recoveryFlashPageAddress, data, size);
}
} else {
return STORAGE_ERR_DATA;
}
}
void vStorageOnFlashFlagchip_Init(
tStorageOnFlashFlagchip *env, uint32_t mainPage, uint32_t recoveryPage
) {
env->mainFlashPageAddress = mainPage;
env->recoveryFlashPageAddress = recoveryPage;
}
tStorageInterface xStorageOnFlashFlagchip_GetInterface(tStorageOnFlashFlagchip *env) {
return (tStorageInterface) {
.env = env,
.load = (StorageIOTransaction) xStorageOnFlashFlagchip_Load,
.dump = (StorageIOTransaction) xStorageOnFlashFlagchip_Dump
};
}