Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.
 
 
 
 
 
 

317 lignes
8.1 KiB

  1. #include "plsr_persistence.h"
  2. #include <stddef.h>
  3. #include <string.h>
  4. #define PLSR_HSD_BACKUP_MAGIC (0x504C4853UL)
  5. #define PLSR_HSD_BACKUP_VERSION (1U)
  6. #define PLSR_BACKUP_SLOT_A_OFFSET (0x0100UL)
  7. #define PLSR_BACKUP_SLOT_STRIDE (0x0200UL)
  8. typedef struct
  9. {
  10. uint32_t magic;
  11. uint16_t version;
  12. uint16_t payloadLength;
  13. uint32_t generation;
  14. PLSR_HSD_DATA data;
  15. uint32_t crc32;
  16. } PLSR_HSD_BACKUP_RECORD;
  17. #ifdef PLSR_HOST_TEST
  18. static PLSR_HSD_BACKUP_RECORD PlsrHostBackupSlots[2];
  19. #else
  20. #include "stm32f4xx.h"
  21. #endif
  22. static uint32_t PlsrPersistenceCrc32(const volatile uint8_t *data,
  23. uint32_t length)
  24. {
  25. uint32_t crc = 0xFFFFFFFFUL;
  26. uint32_t index;
  27. uint8_t bit;
  28. for (index = 0U; index < length; index++)
  29. {
  30. crc ^= data[index];
  31. for (bit = 0U; bit < 8U; bit++)
  32. {
  33. if ((crc & 1UL) != 0UL)
  34. {
  35. crc = (crc >> 1U) ^ 0xEDB88320UL;
  36. }
  37. else
  38. {
  39. crc >>= 1U;
  40. }
  41. }
  42. }
  43. return ~crc;
  44. }
  45. static volatile PLSR_HSD_BACKUP_RECORD *PlsrPersistenceGetHsdSlot(
  46. uint8_t slot)
  47. {
  48. #ifdef PLSR_HOST_TEST
  49. return &PlsrHostBackupSlots[slot];
  50. #else
  51. uint32_t offset = PLSR_BACKUP_SLOT_A_OFFSET
  52. + (uint32_t)slot * PLSR_BACKUP_SLOT_STRIDE;
  53. return (volatile PLSR_HSD_BACKUP_RECORD *)(BKPSRAM_BASE + offset);
  54. #endif
  55. }
  56. static uint8_t PlsrPersistenceHsdRecordIsValid(
  57. const volatile PLSR_HSD_BACKUP_RECORD *record)
  58. {
  59. uint32_t expectedCrc;
  60. if ((record->magic != PLSR_HSD_BACKUP_MAGIC)
  61. || (record->version != PLSR_HSD_BACKUP_VERSION)
  62. || (record->payloadLength != sizeof(PLSR_HSD_DATA)))
  63. {
  64. return 0U;
  65. }
  66. expectedCrc = PlsrPersistenceCrc32(
  67. (const volatile uint8_t *)record,
  68. (uint32_t)offsetof(PLSR_HSD_BACKUP_RECORD, crc32));
  69. return (expectedCrc == record->crc32) ? 1U : 0U;
  70. }
  71. static uint8_t PlsrPersistenceGenerationIsNewer(uint32_t left,
  72. uint32_t right)
  73. {
  74. return (((int32_t)(left - right)) > 0) ? 1U : 0U;
  75. }
  76. static void PlsrPersistenceCopyHsdFromVolatile(
  77. PLSR_HSD_DATA *destination,
  78. const volatile PLSR_HSD_DATA *source)
  79. {
  80. uint16_t index;
  81. for (index = 0U; index < PLSR_HSD_RUNTIME_COUNT; index++)
  82. {
  83. destination->runtime[index] = source->runtime[index];
  84. }
  85. for (index = 0U; index < PLSR_HSD_CONFIG_COUNT; index++)
  86. {
  87. destination->config[index] = source->config[index];
  88. }
  89. }
  90. static void PlsrPersistenceWriteRecord(
  91. volatile PLSR_HSD_BACKUP_RECORD *destination,
  92. const PLSR_HSD_BACKUP_RECORD *source)
  93. {
  94. const uint32_t *sourceWords = (const uint32_t *)source;
  95. volatile uint32_t *destinationWords = (volatile uint32_t *)destination;
  96. uint32_t wordCount = (uint32_t)(sizeof(PLSR_HSD_BACKUP_RECORD)
  97. / sizeof(uint32_t));
  98. uint32_t index;
  99. destination->magic = 0UL;
  100. #ifndef PLSR_HOST_TEST
  101. __DMB();
  102. #endif
  103. for (index = 1U; index < wordCount; index++)
  104. {
  105. destinationWords[index] = sourceWords[index];
  106. }
  107. #ifndef PLSR_HOST_TEST
  108. __DMB();
  109. #endif
  110. destination->magic = PLSR_HSD_BACKUP_MAGIC;
  111. #ifndef PLSR_HOST_TEST
  112. __DMB();
  113. #endif
  114. }
  115. PLSR_PERSISTENCE_RESULT PlsrPersistenceLoadHsd(PLSR_HSD_DATA *data)
  116. {
  117. volatile PLSR_HSD_BACKUP_RECORD *slotA;
  118. volatile PLSR_HSD_BACKUP_RECORD *slotB;
  119. const volatile PLSR_HSD_BACKUP_RECORD *selected;
  120. uint32_t generationA;
  121. uint32_t generationB;
  122. uint8_t validA;
  123. uint8_t validB;
  124. if (data == NULL)
  125. {
  126. return PLSR_PERSISTENCE_INVALID_ARGUMENT;
  127. }
  128. slotA = PlsrPersistenceGetHsdSlot(0U);
  129. slotB = PlsrPersistenceGetHsdSlot(1U);
  130. validA = PlsrPersistenceHsdRecordIsValid(slotA);
  131. validB = PlsrPersistenceHsdRecordIsValid(slotB);
  132. if ((validA == 0U) && (validB == 0U))
  133. {
  134. (void)memset(data, 0, sizeof(*data));
  135. return PLSR_PERSISTENCE_DEFAULTED;
  136. }
  137. if ((validA != 0U) && (validB != 0U))
  138. {
  139. generationA = slotA->generation;
  140. generationB = slotB->generation;
  141. selected = (PlsrPersistenceGenerationIsNewer(generationB,
  142. generationA)
  143. != 0U)
  144. ? slotB
  145. : slotA;
  146. }
  147. else
  148. {
  149. selected = (validA != 0U) ? slotA : slotB;
  150. }
  151. PlsrPersistenceCopyHsdFromVolatile(data, &selected->data);
  152. return PLSR_PERSISTENCE_OK;
  153. }
  154. PLSR_PERSISTENCE_RESULT PlsrPersistenceSaveHsd(const PLSR_HSD_DATA *data)
  155. {
  156. volatile PLSR_HSD_BACKUP_RECORD *slotA;
  157. volatile PLSR_HSD_BACKUP_RECORD *slotB;
  158. volatile PLSR_HSD_BACKUP_RECORD *target;
  159. PLSR_HSD_BACKUP_RECORD record;
  160. uint32_t newestGeneration = 0UL;
  161. uint32_t generationA;
  162. uint32_t generationB;
  163. uint8_t validA;
  164. uint8_t validB;
  165. if (data == NULL)
  166. {
  167. return PLSR_PERSISTENCE_INVALID_ARGUMENT;
  168. }
  169. if (sizeof(PLSR_HSD_BACKUP_RECORD) > PLSR_BACKUP_SLOT_STRIDE)
  170. {
  171. return PLSR_PERSISTENCE_VERIFY_FAILED;
  172. }
  173. slotA = PlsrPersistenceGetHsdSlot(0U);
  174. slotB = PlsrPersistenceGetHsdSlot(1U);
  175. validA = PlsrPersistenceHsdRecordIsValid(slotA);
  176. validB = PlsrPersistenceHsdRecordIsValid(slotB);
  177. if ((validA != 0U) && (validB != 0U))
  178. {
  179. generationA = slotA->generation;
  180. generationB = slotB->generation;
  181. if (PlsrPersistenceGenerationIsNewer(generationB,
  182. generationA)
  183. != 0U)
  184. {
  185. newestGeneration = generationB;
  186. target = slotA;
  187. }
  188. else
  189. {
  190. newestGeneration = generationA;
  191. target = slotB;
  192. }
  193. }
  194. else if (validA != 0U)
  195. {
  196. newestGeneration = slotA->generation;
  197. target = slotB;
  198. }
  199. else if (validB != 0U)
  200. {
  201. newestGeneration = slotB->generation;
  202. target = slotA;
  203. }
  204. else
  205. {
  206. target = slotA;
  207. }
  208. (void)memset(&record, 0, sizeof(record));
  209. record.magic = PLSR_HSD_BACKUP_MAGIC;
  210. record.version = PLSR_HSD_BACKUP_VERSION;
  211. record.payloadLength = (uint16_t)sizeof(PLSR_HSD_DATA);
  212. record.generation = newestGeneration + 1UL;
  213. record.data = *data;
  214. record.crc32 = PlsrPersistenceCrc32(
  215. (const volatile uint8_t *)&record,
  216. (uint32_t)offsetof(PLSR_HSD_BACKUP_RECORD, crc32));
  217. PlsrPersistenceWriteRecord(target, &record);
  218. return (PlsrPersistenceHsdRecordIsValid(target) != 0U)
  219. ? PLSR_PERSISTENCE_OK
  220. : PLSR_PERSISTENCE_VERIFY_FAILED;
  221. }
  222. void PlsrPersistenceResetHsd(void)
  223. {
  224. PlsrPersistenceGetHsdSlot(0U)->magic = 0UL;
  225. PlsrPersistenceGetHsdSlot(1U)->magic = 0UL;
  226. #ifndef PLSR_HOST_TEST
  227. __DMB();
  228. #endif
  229. }
  230. PLSR_PERSISTENCE_RESULT PlsrPersistenceLoadSfd(PLSR_SFD_DATA *data)
  231. {
  232. if (data == NULL)
  233. {
  234. return PLSR_PERSISTENCE_INVALID_ARGUMENT;
  235. }
  236. (void)memset(data, 0, sizeof(*data));
  237. return PLSR_PERSISTENCE_NOT_IMPLEMENTED;
  238. }
  239. PLSR_PERSISTENCE_RESULT PlsrPersistenceSaveSfd(const PLSR_SFD_DATA *data)
  240. {
  241. if (data == NULL)
  242. {
  243. return PLSR_PERSISTENCE_INVALID_ARGUMENT;
  244. }
  245. return PLSR_PERSISTENCE_NOT_IMPLEMENTED;
  246. }
  247. #ifdef PLSR_HOST_TEST
  248. void PlsrPersistenceTestResetStorage(void)
  249. {
  250. (void)memset(PlsrHostBackupSlots, 0, sizeof(PlsrHostBackupSlots));
  251. }
  252. void PlsrPersistenceTestCorruptNewestHsd(void)
  253. {
  254. volatile PLSR_HSD_BACKUP_RECORD *slotA = PlsrPersistenceGetHsdSlot(0U);
  255. volatile PLSR_HSD_BACKUP_RECORD *slotB = PlsrPersistenceGetHsdSlot(1U);
  256. uint8_t validA = PlsrPersistenceHsdRecordIsValid(slotA);
  257. uint8_t validB = PlsrPersistenceHsdRecordIsValid(slotB);
  258. volatile PLSR_HSD_BACKUP_RECORD *newest;
  259. if ((validA == 0U) && (validB == 0U))
  260. {
  261. return;
  262. }
  263. if ((validA != 0U) && (validB != 0U))
  264. {
  265. newest = (PlsrPersistenceGenerationIsNewer(slotB->generation,
  266. slotA->generation)
  267. != 0U)
  268. ? slotB
  269. : slotA;
  270. }
  271. else
  272. {
  273. newest = (validA != 0U) ? slotA : slotB;
  274. }
  275. newest->crc32 ^= 1UL;
  276. }
  277. #endif