From f5a529951944da4bf981230a837afc107801b443 Mon Sep 17 00:00:00 2001 From: cfif Date: Mon, 2 Jun 2025 13:26:41 +0300 Subject: [PATCH] Init --- VarTabDumpObserver.c | 248 ++++++++++++++++++++++++++++++++++++++++++ VarsTabDumpObserver.h | 57 ++++++++++ modular.json | 22 ++++ 3 files changed, 327 insertions(+) create mode 100644 VarTabDumpObserver.c create mode 100644 VarsTabDumpObserver.h create mode 100644 modular.json diff --git a/VarTabDumpObserver.c b/VarTabDumpObserver.c new file mode 100644 index 0000000..3071198 --- /dev/null +++ b/VarTabDumpObserver.c @@ -0,0 +1,248 @@ +// +// Created by xemon on 19.12.22. +// + +#include +#include "VarsTabDumpObserver.h" +#include "SystemDelayInterface.h" +#include "string.h" + +#ifdef STORAGE_ARTERY_CHECK_CLEAR + +#include "StorageOnFlashArtery.h" + +#endif + + +#define LOGGER env->logger +#define LOG_SIGN "Хран.Наб." + +void VarsTabDumpObserver_Init( + tVarsTabDumpObserver *env, + tStorageInterface *interface, + uint32_t delay, + void *data, + size_t size, + tVariablesTable *VarsTab, + uint32_t trackableGroup +) { + env->interface = interface; + env->trackableVarsTab = VarsTab; + env->trackableGroup = trackableGroup; + + env->data = data; + env->size = size; + + env->delay = delay; + env->dumpAfter = 0; + env->access = osMutexNew(NULL); + env->accessDumper = osMutexNew(NULL); + + InitThreadAtrStatic(&env->thread.attr, "Data", env->thread.controlBlock, env->thread.stack, osPriorityNormal); + env->thread.id = 0; +} + + +bool VarsTabDumpObserver_Load(tVarsTabDumpObserver *env) { + + if (osMutexAcquire(env->accessDumper, 100) == osOK) { + eStorageStatus dumpStatus = StorageLoad(env->interface, env->data, env->size); + osMutexRelease(env->accessDumper); + + if (dumpStatus == STORAGE_ERR_DEVICE) { + LoggerInfoStatic(LOGGER, LOG_SIGN, "Ошибка ПЗУ") + env->health = false; + return false; + } else if (dumpStatus == STORAGE_OK) { + env->health = true; + LoggerInfoStatic(LOGGER, LOG_SIGN, "Данные успешно загружены из ПЗУ") + return true; + } + LoggerInfoStatic(LOGGER, LOG_SIGN, "Ошибка данных при загрузке из ПЗУ") + return false; + } else { + LoggerErrorStatic(LOGGER, LOG_SIGN, "Ошибка чтения ПЗУ!!!") + LoggerErrorStatic(LOGGER, LOG_SIGN, "Ошибка параллельного доступа") + return false; + } + +} + +bool VarsTabDumpObserver_Dump(tVarsTabDumpObserver *env) { + LoggerInfoStatic(LOGGER, LOG_SIGN, "Попытка записи в ПЗУ...") + + +#ifdef STORAGE_ARTERY_CHECK_CLEAR + tStorageOnFlashArtery *storageOnFlashArteryCheckClear = env->interface->env; + + int isMainFlashPageAddressCheckClear = memcmp((uint8_t *) storageOnFlashArteryCheckClear->mainFlashPageAddress, + env->data, env->size); + int isRecoveryFlashPageAddressCheckClear = memcmp( + (uint8_t *) storageOnFlashArteryCheckClear->recoveryFlashPageAddress, env->data, env->size); + + if ((isMainFlashPageAddressCheckClear == 0) && (isRecoveryFlashPageAddressCheckClear == 0)) { + LoggerInfoStatic(LOGGER, LOG_SIGN, "Запись в ПЗУ не требуется (1)") + return true; + } +#endif + + if (env->logger) { + env->logger->logging( + env->logger->env, "Хран.Наб.", + sizeof("Хран.Наб.") - 1, + LOGLEVEL_INFO, + "Запись в ПЗУ...", + sizeof("Запись в ПЗУ...") - 1, true + ); + } + + if (osMutexAcquire(env->accessDumper, 100) == osOK) { + +#ifdef STORAGE_ARTERY_CHECK_WRITE_SECTORS + tStorageOnFlashArtery *storageOnFlashArteryCheckWriteSectors = env->interface->env; + + uint8_t maxCountWriteSectors = 0; + + uint8_t countSectorsFullSize = env->size / FLASH_PAGE_SIZE; + uint16_t countSectorTailSize = env->size % FLASH_PAGE_SIZE; + + for (uint8_t i = 0; i < countSectorsFullSize; ++i) { + + int isMainFlashPageAddressCheckWriteSectors = + memcmp((uint8_t *) (i * FLASH_PAGE_SIZE + + storageOnFlashArteryCheckWriteSectors->mainFlashPageAddress), + i * FLASH_PAGE_SIZE + env->data, FLASH_PAGE_SIZE); + + int isRecoveryFlashPageAddressCheckWriteSectors = + memcmp((uint8_t *) (i * FLASH_PAGE_SIZE + + storageOnFlashArteryCheckWriteSectors->recoveryFlashPageAddress), + i * FLASH_PAGE_SIZE + env->data, FLASH_PAGE_SIZE); + + if ((isMainFlashPageAddressCheckWriteSectors != 0) || (isRecoveryFlashPageAddressCheckWriteSectors != 0)) { + maxCountWriteSectors = i; + LoggerStrFormatInfo(LOGGER, LOG_SIGN, "Сектор %d, требуется запись в ПЗУ", maxCountWriteSectors) + } + + } + + if (countSectorTailSize > 0) { + + int isMainFlashPageAddressCheckWriteSectors = + memcmp((uint8_t *) (countSectorsFullSize * FLASH_PAGE_SIZE + + storageOnFlashArteryCheckWriteSectors->mainFlashPageAddress), + countSectorsFullSize * FLASH_PAGE_SIZE + env->data, countSectorTailSize); + + int isRecoveryFlashPageAddressCheckWriteSectors = + memcmp((uint8_t *) (countSectorsFullSize * FLASH_PAGE_SIZE + + storageOnFlashArteryCheckWriteSectors->recoveryFlashPageAddress), + countSectorsFullSize * FLASH_PAGE_SIZE + env->data, countSectorTailSize); + + if ((isMainFlashPageAddressCheckWriteSectors != 0) || (isRecoveryFlashPageAddressCheckWriteSectors != 0)) { + maxCountWriteSectors = countSectorsFullSize + 1; + LoggerStrFormatInfo(LOGGER, LOG_SIGN, "Сектор %d, требуется запись в ПЗУ", maxCountWriteSectors) + } + + } + + if (maxCountWriteSectors == 0) { + LoggerInfoStatic(LOGGER, LOG_SIGN, "Запись в ПЗУ не требуется (2)") + osMutexRelease(env->accessDumper); + return true; + } + + eStorageStatus result; + + if (maxCountWriteSectors > countSectorsFullSize) { + result = StorageDump(env->interface, env->data, env->size); + } else { + result = StorageDump(env->interface, env->data, maxCountWriteSectors * FLASH_PAGE_SIZE); + } + + +#endif + +#ifndef STORAGE_ARTERY_CHECK_WRITE_SECTORS + eStorageStatus result = StorageDump(env->interface, env->data, env->size); +#endif + osMutexRelease(env->accessDumper); + + env->health = (result == STORAGE_OK); + + if (env->health) { + LoggerInfoStatic(LOGGER, LOG_SIGN, "Успешно записано в ПЗУ") + return true; + } else { + LoggerErrorStatic(LOGGER, LOG_SIGN, "Ошибка записи в ПЗУ!!!") + if (result == STORAGE_ERR_DATA) { + LoggerErrorStatic(LOGGER, LOG_SIGN, "Ошибка контрольной суммы") + } else { + LoggerErrorStatic(LOGGER, LOG_SIGN, "Ошибка ПЗУ") + } + return false; + } + + } else { + LoggerErrorStatic(LOGGER, LOG_SIGN, "Ошибка записи в ПЗУ!!!") + LoggerErrorStatic(LOGGER, LOG_SIGN, "Ошибка паралельного доступа") + return false; + } +} + + +static bool VarsTabDumpObserver_IsNowDumpRequired(tVarsTabDumpObserver *env) { + return env->dumpAfter < SystemGetMs(); +} + +void VarsTabDumpObserver_RequireDump(tVarsTabDumpObserver *env) { + if (osMutexAcquire(env->access, 1) == osOK) { + env->dumpAfter = SystemGetMs() + env->delay; + osMutexRelease(env->access); + } +} + +void DeviceStorageProcessing(tVarsTabDumpObserver *env) { + if (VariablesTable_TakeChange(env->trackableVarsTab, env->trackableGroup)) { + LoggerInfoStatic(LOGGER, LOG_SIGN, "Обнаружены изменения, необходима запись в ПЗУ") + VarsTabDumpObserver_RequireDump(env); + } + + if (env->dumpAfter && VarsTabDumpObserver_IsNowDumpRequired(env)) { + if (osMutexAcquire(env->access, 1) == osOK) { + if (VarsTabDumpObserver_IsNowDumpRequired(env)) { + VarsTabDumpObserver_Dump(env); + env->dumpAfter = 0; + } + osMutexRelease(env->access); + } + } +} + +static _Noreturn void VarsTabDumpObserver_Thread(tVarsTabDumpObserver *env) { + for (;;) { + DeviceStorageProcessing(env); + SystemDelayMs(100); + } +} + +void VarsTabDumpObserver_StartThread(tVarsTabDumpObserver *env) { + ThreadBlock_Start(env->thread, env, VarsTabDumpObserver_Thread); +} + +void VarsTabDumpObserver_StopThread(tVarsTabDumpObserver *env) { + ThreadBlock_Stop(env->thread); +} + + +void VarsTabDumpObserver_Flush(tVarsTabDumpObserver *env) { + if (env->dumpAfter) { + LoggerInfoStatic(LOGGER, LOG_SIGN, "Есть изменения, записываем в ПЗУ") + if (osMutexAcquire(env->access, 10000) == osOK) { + VarsTabDumpObserver_Dump(env); + env->dumpAfter = 0; + osMutexRelease(env->access); + } + } +} + + + diff --git a/VarsTabDumpObserver.h b/VarsTabDumpObserver.h new file mode 100644 index 0000000..380bbe0 --- /dev/null +++ b/VarsTabDumpObserver.h @@ -0,0 +1,57 @@ +// +// Created by xemon on 19.12.22. +// + +#ifndef UVEOS_ON_NATION_VarsTabDumpOBSERVER_H +#define UVEOS_ON_NATION_VarsTabDumpOBSERVER_H + +#include +#include "VariablesTable.h" +#include "LoggerInterface.h" + +typedef struct { + tLoggerInterface *logger; + tStorageInterface *interface; + tVariablesTable *trackableVarsTab; + uint32_t trackableGroup; + void *data; + size_t size; + + bool health; + + osMutexId_t access; + osMutexId_t accessDumper; + uint32_t dumpAfter; + uint32_t delay; + + struct { + osThreadId_t id; + uint32_t stack[256]; + StaticTask_t controlBlock; + osThreadAttr_t attr; + } thread; +} tVarsTabDumpObserver; + +void VarsTabDumpObserver_Init( + tVarsTabDumpObserver *env, + tStorageInterface *interface, + uint32_t delay, + void *data, + size_t size, + tVariablesTable *VarsTab, + uint32_t trackableGroup +); + +bool VarsTabDumpObserver_Load(tVarsTabDumpObserver *env); + +bool VarsTabDumpObserver_Dump(tVarsTabDumpObserver *env); + +void VarsTabDumpObserver_RequireDump(tVarsTabDumpObserver *env); + +void VarsTabDumpObserver_StartThread(tVarsTabDumpObserver *env); + +void VarsTabDumpObserver_StopThread(tVarsTabDumpObserver *env); + +void VarsTabDumpObserver_Flush(tVarsTabDumpObserver *env); + +#endif //UVEOS_ON_NATION_VarsTabDumpOBSERVER_H diff --git a/modular.json b/modular.json new file mode 100644 index 0000000..1668049 --- /dev/null +++ b/modular.json @@ -0,0 +1,22 @@ +{ + "dep": [ + { + "type": "git", + "provider": "Smart_Components_Aurus", + "repo": "VariablesTable" + }, + { + "type": "git", + "provider": "Smart_Components_Aurus", + "repo": "StorageInterface" + } + ], + "cmake": { + "inc_dirs": [ + "./" + ], + "srcs": [ + "./**.c" + ] + } +} \ No newline at end of file