// // Created by cfif on 07.10.22. // #include #include "InternalFlashPage.h" #include "StorageOnFlashArtery.h" 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 xStorageOnFlashArtery_DumpOn( tStorageOnFlashArtery *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; } if (sInternalFlashPage_Write(pageAddress, dataSizeOnFlash, (uint8_t *) &dataCrc, 4) != 4) { 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 xStorageOnFlashArtery_Dump(tStorageOnFlashArtery *env, void *data, size_t size) { uint32_t crc = xStorageOnFlashArtery_Crc(data, size); if (xStorageOnFlashArtery_DumpOn(env, crc, env->recoveryFlashPageAddress, data, size) != STORAGE_OK) { return STORAGE_ERR_DEVICE; } if (xStorageOnFlashArtery_DumpOn(env, crc, env->mainFlashPageAddress, data, size) != STORAGE_OK) { return STORAGE_ERR_DEVICE; } return STORAGE_OK; } eStorageStatus xStorageOnFlashArtery_Load(tStorageOnFlashArtery *env, void *data, size_t size) { 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); uint32_t mainCrcCalc = xStorageOnFlashArtery_CrcFlash((uint8_t *) env->mainFlashPageAddress, size); uint32_t mainCrcReed = iInternalFlashPage_ReadWord(env->mainFlashPageAddress + dataSizeOnFlash); 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 { sInternalFlashPage_Read(env->recoveryFlashPageAddress, 0x0, data, size); return xStorageOnFlashArtery_DumpOn(env, recoveryCrcCalc, env->mainFlashPageAddress, data, size); } } else if (recoveryCrcOk || mainCrcOk) { if (recoveryCrcOk) { sInternalFlashPage_Read(env->recoveryFlashPageAddress, 0x0, data, size); return xStorageOnFlashArtery_DumpOn(env, recoveryCrcCalc, env->mainFlashPageAddress, data, size); } else { sInternalFlashPage_Read(env->mainFlashPageAddress, 0x0, data, size); return xStorageOnFlashArtery_DumpOn(env, mainCrcCalc, env->recoveryFlashPageAddress, data, size); } } else { return STORAGE_ERR_DATA; } } void vStorageOnFlashArtery_Init( tStorageOnFlashArtery *env, uint32_t mainPage, uint32_t recoveryPage ) { env->mainFlashPageAddress = mainPage; env->recoveryFlashPageAddress = recoveryPage; } tStorageInterface xStorageOnFlashArtery_GetInterface(tStorageOnFlashArtery *env) { return (tStorageInterface) { .env = env, .load = (StorageIOTransaction) xStorageOnFlashArtery_Load, .dump = (StorageIOTransaction) xStorageOnFlashArtery_Dump, }; }