|
- #include "plsr_persistence.h"
- #include <stddef.h>
- #include <string.h>
-
- #define PLSR_HSD_BACKUP_MAGIC (0x504C4853UL)
- #define PLSR_HSD_BACKUP_VERSION (1U)
- #define PLSR_BACKUP_SLOT_A_OFFSET (0x0100UL)
- #define PLSR_BACKUP_SLOT_STRIDE (0x0200UL)
-
- typedef struct
- {
- uint32_t magic;
- uint16_t version;
- uint16_t payloadLength;
- uint32_t generation;
- PLSR_HSD_DATA data;
- uint32_t crc32;
- } PLSR_HSD_BACKUP_RECORD;
-
- #ifdef PLSR_HOST_TEST
- static PLSR_HSD_BACKUP_RECORD PlsrHostBackupSlots[2];
- #else
- #include "stm32f4xx.h"
- #endif
-
- static uint32_t PlsrPersistenceCrc32(const volatile uint8_t *data,
- uint32_t length)
- {
- uint32_t crc = 0xFFFFFFFFUL;
- uint32_t index;
- uint8_t bit;
-
- for (index = 0U; index < length; index++)
- {
- crc ^= data[index];
- for (bit = 0U; bit < 8U; bit++)
- {
- if ((crc & 1UL) != 0UL)
- {
- crc = (crc >> 1U) ^ 0xEDB88320UL;
- }
- else
- {
- crc >>= 1U;
- }
- }
- }
-
- return ~crc;
- }
-
- static volatile PLSR_HSD_BACKUP_RECORD *PlsrPersistenceGetHsdSlot(
- uint8_t slot)
- {
- #ifdef PLSR_HOST_TEST
- return &PlsrHostBackupSlots[slot];
- #else
- uint32_t offset = PLSR_BACKUP_SLOT_A_OFFSET
- + (uint32_t)slot * PLSR_BACKUP_SLOT_STRIDE;
- return (volatile PLSR_HSD_BACKUP_RECORD *)(BKPSRAM_BASE + offset);
- #endif
- }
-
- static uint8_t PlsrPersistenceHsdRecordIsValid(
- const volatile PLSR_HSD_BACKUP_RECORD *record)
- {
- uint32_t expectedCrc;
-
- if ((record->magic != PLSR_HSD_BACKUP_MAGIC)
- || (record->version != PLSR_HSD_BACKUP_VERSION)
- || (record->payloadLength != sizeof(PLSR_HSD_DATA)))
- {
- return 0U;
- }
-
- expectedCrc = PlsrPersistenceCrc32(
- (const volatile uint8_t *)record,
- (uint32_t)offsetof(PLSR_HSD_BACKUP_RECORD, crc32));
-
- return (expectedCrc == record->crc32) ? 1U : 0U;
- }
-
- static uint8_t PlsrPersistenceGenerationIsNewer(uint32_t left,
- uint32_t right)
- {
- return (((int32_t)(left - right)) > 0) ? 1U : 0U;
- }
-
- static void PlsrPersistenceCopyHsdFromVolatile(
- PLSR_HSD_DATA *destination,
- const volatile PLSR_HSD_DATA *source)
- {
- uint16_t index;
-
- for (index = 0U; index < PLSR_HSD_RUNTIME_COUNT; index++)
- {
- destination->runtime[index] = source->runtime[index];
- }
- for (index = 0U; index < PLSR_HSD_CONFIG_COUNT; index++)
- {
- destination->config[index] = source->config[index];
- }
- }
-
- static void PlsrPersistenceWriteRecord(
- volatile PLSR_HSD_BACKUP_RECORD *destination,
- const PLSR_HSD_BACKUP_RECORD *source)
- {
- const uint32_t *sourceWords = (const uint32_t *)source;
- volatile uint32_t *destinationWords = (volatile uint32_t *)destination;
- uint32_t wordCount = (uint32_t)(sizeof(PLSR_HSD_BACKUP_RECORD)
- / sizeof(uint32_t));
- uint32_t index;
-
- destination->magic = 0UL;
- #ifndef PLSR_HOST_TEST
- __DMB();
- #endif
-
- for (index = 1U; index < wordCount; index++)
- {
- destinationWords[index] = sourceWords[index];
- }
-
- #ifndef PLSR_HOST_TEST
- __DMB();
- #endif
- destination->magic = PLSR_HSD_BACKUP_MAGIC;
- #ifndef PLSR_HOST_TEST
- __DMB();
- #endif
- }
-
- PLSR_PERSISTENCE_RESULT PlsrPersistenceLoadHsd(PLSR_HSD_DATA *data)
- {
- volatile PLSR_HSD_BACKUP_RECORD *slotA;
- volatile PLSR_HSD_BACKUP_RECORD *slotB;
- const volatile PLSR_HSD_BACKUP_RECORD *selected;
- uint32_t generationA;
- uint32_t generationB;
- uint8_t validA;
- uint8_t validB;
-
- if (data == NULL)
- {
- return PLSR_PERSISTENCE_INVALID_ARGUMENT;
- }
-
- slotA = PlsrPersistenceGetHsdSlot(0U);
- slotB = PlsrPersistenceGetHsdSlot(1U);
- validA = PlsrPersistenceHsdRecordIsValid(slotA);
- validB = PlsrPersistenceHsdRecordIsValid(slotB);
-
- if ((validA == 0U) && (validB == 0U))
- {
- (void)memset(data, 0, sizeof(*data));
- return PLSR_PERSISTENCE_DEFAULTED;
- }
-
- if ((validA != 0U) && (validB != 0U))
- {
- generationA = slotA->generation;
- generationB = slotB->generation;
- selected = (PlsrPersistenceGenerationIsNewer(generationB,
- generationA)
- != 0U)
- ? slotB
- : slotA;
- }
- else
- {
- selected = (validA != 0U) ? slotA : slotB;
- }
-
- PlsrPersistenceCopyHsdFromVolatile(data, &selected->data);
- return PLSR_PERSISTENCE_OK;
- }
-
- PLSR_PERSISTENCE_RESULT PlsrPersistenceSaveHsd(const PLSR_HSD_DATA *data)
- {
- volatile PLSR_HSD_BACKUP_RECORD *slotA;
- volatile PLSR_HSD_BACKUP_RECORD *slotB;
- volatile PLSR_HSD_BACKUP_RECORD *target;
- PLSR_HSD_BACKUP_RECORD record;
- uint32_t newestGeneration = 0UL;
- uint32_t generationA;
- uint32_t generationB;
- uint8_t validA;
- uint8_t validB;
-
- if (data == NULL)
- {
- return PLSR_PERSISTENCE_INVALID_ARGUMENT;
- }
- if (sizeof(PLSR_HSD_BACKUP_RECORD) > PLSR_BACKUP_SLOT_STRIDE)
- {
- return PLSR_PERSISTENCE_VERIFY_FAILED;
- }
-
- slotA = PlsrPersistenceGetHsdSlot(0U);
- slotB = PlsrPersistenceGetHsdSlot(1U);
- validA = PlsrPersistenceHsdRecordIsValid(slotA);
- validB = PlsrPersistenceHsdRecordIsValid(slotB);
-
- if ((validA != 0U) && (validB != 0U))
- {
- generationA = slotA->generation;
- generationB = slotB->generation;
- if (PlsrPersistenceGenerationIsNewer(generationB,
- generationA)
- != 0U)
- {
- newestGeneration = generationB;
- target = slotA;
- }
- else
- {
- newestGeneration = generationA;
- target = slotB;
- }
- }
- else if (validA != 0U)
- {
- newestGeneration = slotA->generation;
- target = slotB;
- }
- else if (validB != 0U)
- {
- newestGeneration = slotB->generation;
- target = slotA;
- }
- else
- {
- target = slotA;
- }
-
- (void)memset(&record, 0, sizeof(record));
- record.magic = PLSR_HSD_BACKUP_MAGIC;
- record.version = PLSR_HSD_BACKUP_VERSION;
- record.payloadLength = (uint16_t)sizeof(PLSR_HSD_DATA);
- record.generation = newestGeneration + 1UL;
- record.data = *data;
- record.crc32 = PlsrPersistenceCrc32(
- (const volatile uint8_t *)&record,
- (uint32_t)offsetof(PLSR_HSD_BACKUP_RECORD, crc32));
-
- PlsrPersistenceWriteRecord(target, &record);
- return (PlsrPersistenceHsdRecordIsValid(target) != 0U)
- ? PLSR_PERSISTENCE_OK
- : PLSR_PERSISTENCE_VERIFY_FAILED;
- }
-
- void PlsrPersistenceResetHsd(void)
- {
- PlsrPersistenceGetHsdSlot(0U)->magic = 0UL;
- PlsrPersistenceGetHsdSlot(1U)->magic = 0UL;
- #ifndef PLSR_HOST_TEST
- __DMB();
- #endif
- }
-
- PLSR_PERSISTENCE_RESULT PlsrPersistenceLoadSfd(PLSR_SFD_DATA *data)
- {
- if (data == NULL)
- {
- return PLSR_PERSISTENCE_INVALID_ARGUMENT;
- }
-
- (void)memset(data, 0, sizeof(*data));
- return PLSR_PERSISTENCE_NOT_IMPLEMENTED;
- }
-
- PLSR_PERSISTENCE_RESULT PlsrPersistenceSaveSfd(const PLSR_SFD_DATA *data)
- {
- if (data == NULL)
- {
- return PLSR_PERSISTENCE_INVALID_ARGUMENT;
- }
-
- return PLSR_PERSISTENCE_NOT_IMPLEMENTED;
- }
-
- #ifdef PLSR_HOST_TEST
- void PlsrPersistenceTestResetStorage(void)
- {
- (void)memset(PlsrHostBackupSlots, 0, sizeof(PlsrHostBackupSlots));
- }
-
- void PlsrPersistenceTestCorruptNewestHsd(void)
- {
- volatile PLSR_HSD_BACKUP_RECORD *slotA = PlsrPersistenceGetHsdSlot(0U);
- volatile PLSR_HSD_BACKUP_RECORD *slotB = PlsrPersistenceGetHsdSlot(1U);
- uint8_t validA = PlsrPersistenceHsdRecordIsValid(slotA);
- uint8_t validB = PlsrPersistenceHsdRecordIsValid(slotB);
- volatile PLSR_HSD_BACKUP_RECORD *newest;
-
- if ((validA == 0U) && (validB == 0U))
- {
- return;
- }
- if ((validA != 0U) && (validB != 0U))
- {
- newest = (PlsrPersistenceGenerationIsNewer(slotB->generation,
- slotA->generation)
- != 0U)
- ? slotB
- : slotA;
- }
- else
- {
- newest = (validA != 0U) ? slotA : slotB;
- }
-
- newest->crc32 ^= 1UL;
- }
- #endif
|