commit c40f653e2d8ebec4a04696732a8022f9addeea40 Author: cfif Date: Wed Dec 4 13:10:48 2024 +0300 Init diff --git a/Inc/StorageOnFlashNation.h b/Inc/StorageOnFlashNation.h new file mode 100644 index 0000000..a3d973b --- /dev/null +++ b/Inc/StorageOnFlashNation.h @@ -0,0 +1,27 @@ +// +// Created by cfif on 07.10.22. +// + +#ifndef STORAGE_ON_FLASH_NATION_H +#define STORAGE_ON_FLASH_NATION_H + +#include "n32g45x.h" +#include "stddef.h" +#include "StorageIO.h" + +typedef struct { + uint32_t mainFlashPageAddress; + uint32_t recoveryFlashPageAddress; +} tStorageOnFlashNation; + +void vStorageOnFlashNation_Init( + tStorageOnFlashNation *env, + uint32_t mainPage, + uint32_t recoveryPage +); + + +tStorageInterface xStorageOnFlashNation_GetInterface(tStorageOnFlashNation *env); + + +#endif //STORAGE_ON_FLASH_NATION_H diff --git a/Src/StorageOnFlashNation.c b/Src/StorageOnFlashNation.c new file mode 100644 index 0000000..192e329 --- /dev/null +++ b/Src/StorageOnFlashNation.c @@ -0,0 +1,140 @@ +// +// Created by cfif on 07.10.22. +// +#include +#include "InternalFlashPage.h" +#include "StorageOnFlashNation.h" + +static uint32_t xStorageOnFlashNation_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 xStorageOnFlashNation_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 +xStorageOnFlashNation_DumpOn( + tStorageOnFlashNation *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 = xStorageOnFlashNation_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 xStorageOnFlashNation_Dump(tStorageOnFlashNation *env, void *data, size_t size) { + + uint32_t crc = xStorageOnFlashNation_Crc(data, size); + + if (xStorageOnFlashNation_DumpOn(env, crc, env->recoveryFlashPageAddress, data, size) != STORAGE_OK) { + return STORAGE_ERR_DEVICE; + } + + if (xStorageOnFlashNation_DumpOn(env, crc, env->mainFlashPageAddress, data, size) != STORAGE_OK) { + return STORAGE_ERR_DEVICE; + } + + return STORAGE_OK; +} + + +eStorageStatus xStorageOnFlashNation_Load(tStorageOnFlashNation *env, void *data, size_t size) { + + size_t dataSizeOnFlash = (size + 3) & (~3); // выравниваем до кратного 4 (целое количество слов) + + uint32_t recoveryCrcCalc = xStorageOnFlashNation_CrcFlash((uint8_t *) env->recoveryFlashPageAddress, size); + uint32_t recoveryCrcReed = iInternalFlashPage_ReadWord(env->recoveryFlashPageAddress + dataSizeOnFlash); + + uint32_t mainCrcCalc = xStorageOnFlashNation_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 xStorageOnFlashNation_DumpOn(env, recoveryCrcCalc, env->mainFlashPageAddress, data, size); + } + } else if (recoveryCrcOk || mainCrcOk) { + if (recoveryCrcOk) { + sInternalFlashPage_Read(env->recoveryFlashPageAddress, 0x0, data, size); + return xStorageOnFlashNation_DumpOn(env, recoveryCrcCalc, env->mainFlashPageAddress, data, size); + } else { + sInternalFlashPage_Read(env->mainFlashPageAddress, 0x0, data, size); + return xStorageOnFlashNation_DumpOn(env, mainCrcCalc, env->recoveryFlashPageAddress, data, size); + } + } else { + return STORAGE_ERR_DATA; + } + +} + +void vStorageOnFlashNation_Init( + tStorageOnFlashNation *env, uint32_t mainPage, uint32_t recoveryPage +) { + env->mainFlashPageAddress = mainPage; + env->recoveryFlashPageAddress = recoveryPage; +} + +tStorageInterface xStorageOnFlashNation_GetInterface(tStorageOnFlashNation *env) { + return (tStorageInterface) { + .env = env, + .load = (StorageIOTransaction) xStorageOnFlashNation_Load, + .dump = (StorageIOTransaction) xStorageOnFlashNation_Dump, + }; +} \ No newline at end of file diff --git a/modular.json b/modular.json new file mode 100644 index 0000000..f0f0010 --- /dev/null +++ b/modular.json @@ -0,0 +1,22 @@ +{ + "dep": [ + { + "type": "git", + "provider": "NAVIGATOR_UVEOS_NATION_TELIT", + "repo": "StorageInterface" + }, + { + "type": "git", + "provider": "NAVIGATOR_UVEOS_NATION_TELIT", + "repo": "NATION_N32G45X_InternalFlashPage" + } + ], + "cmake": { + "inc_dirs": [ + "Inc" + ], + "srcs": [ + "Src/**.c" + ] + } +} \ No newline at end of file