#ifndef PLSR_PERSISTENCE_H #define PLSR_PERSISTENCE_H #include "plsr_address_map.h" #include #ifdef __cplusplus extern "C" { #endif /* HSD 检查点元数据位(随 HSD 记录一起掉电保存)。 */ #define PLSR_HSD_META_POSITION_VALID (1UL << 0U) #define PLSR_HSD_META_LAST_BUSY (1UL << 1U) #define PLSR_HSD_META_REASON_MASK (0x0000003CUL) typedef struct { uint32_t metadata; uint16_t runtime[PLSR_HSD_RUNTIME_COUNT]; uint16_t config[PLSR_HSD_CONFIG_COUNT]; } PLSR_HSD_DATA; typedef struct { uint16_t config[PLSR_SFD_CONFIG_COUNT]; } PLSR_SFD_DATA; typedef enum { PLSR_PERSISTENCE_OK = 0, PLSR_PERSISTENCE_DEFAULTED, PLSR_PERSISTENCE_INVALID_ARGUMENT, PLSR_PERSISTENCE_VERIFY_FAILED, PLSR_PERSISTENCE_NOT_IMPLEMENTED, PLSR_PERSISTENCE_ERASE_FAILED, PLSR_PERSISTENCE_PROGRAM_FAILED } PLSR_PERSISTENCE_RESULT; /* Cached persistence health snapshot. Slot CRCs are evaluated only by * load/save/erase/diagnostic operations; reading this structure never scans * Backup SRAM or Flash and is therefore safe in the 1 ms Modbus poll path. */ typedef struct { uint8_t hsdValidMask; uint8_t sfdValidMask; uint8_t hsdNewestMask; uint8_t sfdNewestMask; uint8_t destructiveDiagnosticEnabled; PLSR_PERSISTENCE_RESULT lastHsdLoadResult; PLSR_PERSISTENCE_RESULT lastSfdLoadResult; PLSR_PERSISTENCE_RESULT lastHsdSaveResult; PLSR_PERSISTENCE_RESULT lastSfdSaveResult; PLSR_PERSISTENCE_RESULT lastSfdEraseResult; uint32_t hsdGeneration[2]; uint32_t sfdGeneration[2]; uint32_t hsdSaveCount; uint32_t sfdSaveCount; uint32_t selectedHsdCrc32; uint32_t selectedSfdCrc32; } PLSR_PERSISTENCE_DIAGNOSTICS; typedef enum { PLSR_PERSISTENCE_DIAG_TARGET_HSD = 1, PLSR_PERSISTENCE_DIAG_TARGET_SFD = 2 } PLSR_PERSISTENCE_DIAG_TARGET; PLSR_PERSISTENCE_RESULT PlsrPersistenceLoadHsd(PLSR_HSD_DATA *data); PLSR_PERSISTENCE_RESULT PlsrPersistenceSaveHsd(const PLSR_HSD_DATA *data); void PlsrPersistenceResetHsd(void); PLSR_PERSISTENCE_RESULT PlsrPersistenceLoadSfd(PLSR_SFD_DATA *data); PLSR_PERSISTENCE_RESULT PlsrPersistenceSaveSfd(const PLSR_SFD_DATA *data); PLSR_PERSISTENCE_RESULT PlsrPersistenceEraseSfd(void); void PlsrPersistenceGetDiagnostics(PLSR_PERSISTENCE_DIAGNOSTICS *diagnostics); /* Deliberately unavailable in normal builds. A validation build may enable * it with PLSR_ENABLE_DESTRUCTIVE_PERSISTENCE_DIAG=1; the Modbus control layer * additionally requires a double-magic, sequence/inverse handshake and all * motion axes idle. This function only invalidates the newest committed slot * and never accepts a memory address. */ PLSR_PERSISTENCE_RESULT PlsrPersistenceDiagnosticInvalidateNewest( PLSR_PERSISTENCE_DIAG_TARGET target); #ifdef PLSR_HOST_TEST typedef enum { PLSR_TEST_SFD_FAULT_NONE = 0, PLSR_TEST_SFD_FAULT_ERASE, PLSR_TEST_SFD_FAULT_PROGRAM, PLSR_TEST_SFD_FAULT_VERIFY, PLSR_TEST_SFD_FAULT_BEFORE_COMMIT } PLSR_TEST_SFD_FAULT; void PlsrPersistenceTestResetStorage(void); void PlsrPersistenceTestCorruptNewestHsd(void); void PlsrPersistenceTestCorruptNewestSfd(void); void PlsrPersistenceTestSetSfdFault(PLSR_TEST_SFD_FAULT fault); uint32_t PlsrPersistenceTestGetHsdSaveCount(void); uint32_t PlsrPersistenceTestCrc32(const uint8_t *data, uint32_t length); #endif #ifdef __cplusplus } #endif #endif /* PLSR_PERSISTENCE_H */