VarTabDumpObserver/VarTabDumpObserver.c

249 lines
8.7 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// Created by xemon on 19.12.22.
//
#include <CmsisRtosThreadUtils.h>
#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);
}
}
}