No puede seleccionar más de 25 temas Los temas deben comenzar con una letra o número, pueden incluir guiones ('-') y pueden tener hasta 35 caracteres de largo.
 
 
 
 
 
 

800 líneas
22 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. #define PLSR_SFD_FLASH_MAGIC (0x504C5346UL)
  9. #define PLSR_SFD_FLASH_VERSION (1U)
  10. #define PLSR_SFD_FLASH_SLOT_A_ADDRESS (0x080C0000UL)
  11. #define PLSR_SFD_FLASH_SLOT_B_ADDRESS (0x080E0000UL)
  12. #define PLSR_SFD_FLASH_SECTOR_SIZE (0x00020000UL)
  13. #define PLSR_SFD_AXIS_STRIDE (130U)
  14. #define PLSR_SFD_PARAMETER_SET_COUNT (4U)
  15. #define PLSR_SFD_PARAMETER_SET_OFFSET (50U)
  16. #define PLSR_SFD_PARAMETER_SET_STRIDE (20U)
  17. #define PLSR_SFD_DEFAULT_MAX_SPEED (100000UL)
  18. typedef struct
  19. {
  20. uint32_t magic;
  21. uint16_t version;
  22. uint16_t payloadLength;
  23. uint32_t generation;
  24. PLSR_HSD_DATA data;
  25. uint32_t crc32;
  26. } PLSR_HSD_BACKUP_RECORD;
  27. typedef struct
  28. {
  29. uint32_t magic;
  30. uint16_t version;
  31. uint16_t payloadLength;
  32. uint32_t generation;
  33. } PLSR_SFD_FLASH_HEADER;
  34. typedef struct
  35. {
  36. uint32_t magic;
  37. uint16_t version;
  38. uint16_t payloadLength;
  39. uint32_t generation;
  40. PLSR_SFD_DATA data;
  41. uint32_t crc32;
  42. } PLSR_SFD_FLASH_RECORD;
  43. #ifdef PLSR_HOST_TEST
  44. static PLSR_HSD_BACKUP_RECORD PlsrHostBackupSlots[2];
  45. static PLSR_SFD_FLASH_RECORD PlsrHostSfdSlots[2];
  46. static PLSR_TEST_SFD_FAULT PlsrHostSfdFault;
  47. #else
  48. #include "stm32f4xx.h"
  49. #include "stm32f4xx_hal.h"
  50. #include "stm32f4xx_hal_flash_ex.h"
  51. #endif
  52. static uint32_t PlsrPersistenceCrc32Update(uint32_t crc,
  53. const volatile uint8_t *data,
  54. uint32_t length)
  55. {
  56. uint32_t index;
  57. uint8_t bit;
  58. for (index = 0U; index < length; index++)
  59. {
  60. crc ^= data[index];
  61. for (bit = 0U; bit < 8U; bit++)
  62. {
  63. if ((crc & 1UL) != 0UL)
  64. {
  65. crc = (crc >> 1U) ^ 0xEDB88320UL;
  66. }
  67. else
  68. {
  69. crc >>= 1U;
  70. }
  71. }
  72. }
  73. return crc;
  74. }
  75. static uint32_t PlsrPersistenceCrc32(const volatile uint8_t *data,
  76. uint32_t length)
  77. {
  78. return ~PlsrPersistenceCrc32Update(0xFFFFFFFFUL, data, length);
  79. }
  80. static volatile PLSR_HSD_BACKUP_RECORD *PlsrPersistenceGetHsdSlot(
  81. uint8_t slot)
  82. {
  83. #ifdef PLSR_HOST_TEST
  84. return &PlsrHostBackupSlots[slot];
  85. #else
  86. uint32_t offset = PLSR_BACKUP_SLOT_A_OFFSET
  87. + (uint32_t)slot * PLSR_BACKUP_SLOT_STRIDE;
  88. return (volatile PLSR_HSD_BACKUP_RECORD *)(BKPSRAM_BASE + offset);
  89. #endif
  90. }
  91. static uint8_t PlsrPersistenceHsdRecordIsValid(
  92. const volatile PLSR_HSD_BACKUP_RECORD *record)
  93. {
  94. uint32_t expectedCrc;
  95. if ((record->magic != PLSR_HSD_BACKUP_MAGIC)
  96. || (record->version != PLSR_HSD_BACKUP_VERSION)
  97. || (record->payloadLength != sizeof(PLSR_HSD_DATA)))
  98. {
  99. return 0U;
  100. }
  101. expectedCrc = PlsrPersistenceCrc32(
  102. (const volatile uint8_t *)record,
  103. (uint32_t)offsetof(PLSR_HSD_BACKUP_RECORD, crc32));
  104. return (expectedCrc == record->crc32) ? 1U : 0U;
  105. }
  106. static uint8_t PlsrPersistenceGenerationIsNewer(uint32_t left,
  107. uint32_t right)
  108. {
  109. return (((int32_t)(left - right)) > 0) ? 1U : 0U;
  110. }
  111. static volatile PLSR_SFD_FLASH_RECORD *PlsrPersistenceGetSfdSlot(
  112. uint8_t slot)
  113. {
  114. #ifdef PLSR_HOST_TEST
  115. return &PlsrHostSfdSlots[slot];
  116. #else
  117. uint32_t address = (slot == 0U) ? PLSR_SFD_FLASH_SLOT_A_ADDRESS
  118. : PLSR_SFD_FLASH_SLOT_B_ADDRESS;
  119. return (volatile PLSR_SFD_FLASH_RECORD *)address;
  120. #endif
  121. }
  122. static uint8_t PlsrPersistenceSfdRecordIsValid(
  123. const volatile PLSR_SFD_FLASH_RECORD *record)
  124. {
  125. uint32_t expectedCrc;
  126. if ((record->magic != PLSR_SFD_FLASH_MAGIC)
  127. || (record->version != PLSR_SFD_FLASH_VERSION)
  128. || (record->payloadLength != sizeof(PLSR_SFD_DATA)))
  129. {
  130. return 0U;
  131. }
  132. expectedCrc = PlsrPersistenceCrc32(
  133. (const volatile uint8_t *)record,
  134. (uint32_t)offsetof(PLSR_SFD_FLASH_RECORD, crc32));
  135. return (expectedCrc == record->crc32) ? 1U : 0U;
  136. }
  137. static void PlsrPersistenceCopySfdFromVolatile(
  138. PLSR_SFD_DATA *destination,
  139. const volatile PLSR_SFD_DATA *source)
  140. {
  141. uint16_t index;
  142. for (index = 0U; index < PLSR_SFD_CONFIG_COUNT; index++)
  143. {
  144. destination->config[index] = source->config[index];
  145. }
  146. }
  147. static void PlsrPersistenceApplySfdDefaults(PLSR_SFD_DATA *data)
  148. {
  149. uint16_t axisOffset;
  150. uint16_t parameterOffset;
  151. uint8_t axis;
  152. uint8_t parameterSet;
  153. (void)memset(data, 0, sizeof(*data));
  154. for (axis = 0U; axis < PLSR_AXIS_COUNT; axis++)
  155. {
  156. axisOffset = (uint16_t)((uint16_t)axis * PLSR_SFD_AXIS_STRIDE);
  157. /* Explicit Xinje defaults from the SFD parameter table. */
  158. data->config[axisOffset + 7U] = 10;
  159. data->config[axisOffset + 27U] = 20;
  160. data->config[axisOffset + 43U] = 0x0201;
  161. for (parameterSet = 0U;
  162. parameterSet < PLSR_SFD_PARAMETER_SET_COUNT;
  163. parameterSet++)
  164. {
  165. parameterOffset = (uint16_t)(
  166. axisOffset + PLSR_SFD_PARAMETER_SET_OFFSET
  167. + (uint16_t)parameterSet * PLSR_SFD_PARAMETER_SET_STRIDE);
  168. data->config[parameterOffset + 6U] =
  169. (int32_t)(PLSR_SFD_DEFAULT_MAX_SPEED & 0xFFFFUL);
  170. data->config[parameterOffset + 7U] =
  171. (int32_t)(PLSR_SFD_DEFAULT_MAX_SPEED >> 16U);
  172. }
  173. }
  174. }
  175. static PLSR_PERSISTENCE_RESULT PlsrPersistenceBeginSfdOperation(void)
  176. {
  177. #ifdef PLSR_HOST_TEST
  178. return PLSR_PERSISTENCE_OK;
  179. #else
  180. if (HAL_FLASH_Unlock() != HAL_OK)
  181. {
  182. return PLSR_PERSISTENCE_PROGRAM_FAILED;
  183. }
  184. __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_OPERR
  185. | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR
  186. | FLASH_FLAG_PGPERR | FLASH_FLAG_PGSERR);
  187. return PLSR_PERSISTENCE_OK;
  188. #endif
  189. }
  190. static PLSR_PERSISTENCE_RESULT PlsrPersistenceEndSfdOperation(
  191. PLSR_PERSISTENCE_RESULT result)
  192. {
  193. #ifdef PLSR_HOST_TEST
  194. return result;
  195. #else
  196. if ((HAL_FLASH_Lock() != HAL_OK) && (result == PLSR_PERSISTENCE_OK))
  197. {
  198. return PLSR_PERSISTENCE_PROGRAM_FAILED;
  199. }
  200. return result;
  201. #endif
  202. }
  203. static PLSR_PERSISTENCE_RESULT PlsrPersistenceEraseSfdSlot(uint8_t slot)
  204. {
  205. #ifdef PLSR_HOST_TEST
  206. if (PlsrHostSfdFault == PLSR_TEST_SFD_FAULT_ERASE)
  207. {
  208. PlsrHostSfdFault = PLSR_TEST_SFD_FAULT_NONE;
  209. return PLSR_PERSISTENCE_ERASE_FAILED;
  210. }
  211. (void)memset(&PlsrHostSfdSlots[slot],
  212. 0xFF,
  213. sizeof(PlsrHostSfdSlots[slot]));
  214. return PLSR_PERSISTENCE_OK;
  215. #else
  216. FLASH_EraseInitTypeDef erase;
  217. uint32_t sectorError = 0xFFFFFFFFUL;
  218. erase.TypeErase = FLASH_TYPEERASE_SECTORS;
  219. erase.VoltageRange = FLASH_VOLTAGE_RANGE_3;
  220. erase.Sector = (slot == 0U) ? FLASH_SECTOR_10 : FLASH_SECTOR_11;
  221. erase.NbSectors = 1U;
  222. return (HAL_FLASHEx_Erase(&erase, &sectorError) == HAL_OK)
  223. ? PLSR_PERSISTENCE_OK
  224. : PLSR_PERSISTENCE_ERASE_FAILED;
  225. #endif
  226. }
  227. static PLSR_PERSISTENCE_RESULT PlsrPersistenceProgramSfdWord(
  228. volatile uint32_t *destination,
  229. uint32_t value)
  230. {
  231. #ifdef PLSR_HOST_TEST
  232. if (PlsrHostSfdFault == PLSR_TEST_SFD_FAULT_PROGRAM)
  233. {
  234. PlsrHostSfdFault = PLSR_TEST_SFD_FAULT_NONE;
  235. return PLSR_PERSISTENCE_PROGRAM_FAILED;
  236. }
  237. if ((*destination & value) != value)
  238. {
  239. return PLSR_PERSISTENCE_PROGRAM_FAILED;
  240. }
  241. *destination &= value;
  242. return PLSR_PERSISTENCE_OK;
  243. #else
  244. return (HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD,
  245. (uint32_t)destination,
  246. value)
  247. == HAL_OK)
  248. ? PLSR_PERSISTENCE_OK
  249. : PLSR_PERSISTENCE_PROGRAM_FAILED;
  250. #endif
  251. }
  252. static uint8_t PlsrPersistenceSfdBodyMatches(
  253. const volatile uint32_t *destination,
  254. const PLSR_SFD_FLASH_HEADER *header,
  255. const PLSR_SFD_DATA *data,
  256. uint32_t crc32)
  257. {
  258. const uint32_t *headerWords = (const uint32_t *)header;
  259. const uint32_t *dataWords = (const uint32_t *)data;
  260. uint32_t headerWordCount = (uint32_t)(sizeof(*header) / sizeof(uint32_t));
  261. uint32_t dataWordCount = (uint32_t)(sizeof(*data) / sizeof(uint32_t));
  262. uint32_t index;
  263. for (index = 1U; index < headerWordCount; index++)
  264. {
  265. if (destination[index] != headerWords[index])
  266. {
  267. return 0U;
  268. }
  269. }
  270. for (index = 0U; index < dataWordCount; index++)
  271. {
  272. if (destination[headerWordCount + index] != dataWords[index])
  273. {
  274. return 0U;
  275. }
  276. }
  277. if (destination[headerWordCount + dataWordCount] != crc32)
  278. {
  279. return 0U;
  280. }
  281. return 1U;
  282. }
  283. static void PlsrPersistenceCopyHsdFromVolatile(
  284. PLSR_HSD_DATA *destination,
  285. const volatile PLSR_HSD_DATA *source)
  286. {
  287. uint16_t index;
  288. for (index = 0U; index < PLSR_HSD_RUNTIME_COUNT; index++)
  289. {
  290. destination->runtime[index] = source->runtime[index];
  291. }
  292. for (index = 0U; index < PLSR_HSD_CONFIG_COUNT; index++)
  293. {
  294. destination->config[index] = source->config[index];
  295. }
  296. }
  297. static void PlsrPersistenceWriteRecord(
  298. volatile PLSR_HSD_BACKUP_RECORD *destination,
  299. const PLSR_HSD_BACKUP_RECORD *source)
  300. {
  301. const uint32_t *sourceWords = (const uint32_t *)source;
  302. volatile uint32_t *destinationWords = (volatile uint32_t *)destination;
  303. uint32_t wordCount = (uint32_t)(sizeof(PLSR_HSD_BACKUP_RECORD)
  304. / sizeof(uint32_t));
  305. uint32_t index;
  306. destination->magic = 0UL;
  307. #ifndef PLSR_HOST_TEST
  308. __DMB();
  309. #endif
  310. for (index = 1U; index < wordCount; index++)
  311. {
  312. destinationWords[index] = sourceWords[index];
  313. }
  314. #ifndef PLSR_HOST_TEST
  315. __DMB();
  316. #endif
  317. destination->magic = PLSR_HSD_BACKUP_MAGIC;
  318. #ifndef PLSR_HOST_TEST
  319. __DMB();
  320. #endif
  321. }
  322. PLSR_PERSISTENCE_RESULT PlsrPersistenceLoadHsd(PLSR_HSD_DATA *data)
  323. {
  324. volatile PLSR_HSD_BACKUP_RECORD *slotA;
  325. volatile PLSR_HSD_BACKUP_RECORD *slotB;
  326. const volatile PLSR_HSD_BACKUP_RECORD *selected;
  327. uint32_t generationA;
  328. uint32_t generationB;
  329. uint8_t validA;
  330. uint8_t validB;
  331. if (data == NULL)
  332. {
  333. return PLSR_PERSISTENCE_INVALID_ARGUMENT;
  334. }
  335. slotA = PlsrPersistenceGetHsdSlot(0U);
  336. slotB = PlsrPersistenceGetHsdSlot(1U);
  337. validA = PlsrPersistenceHsdRecordIsValid(slotA);
  338. validB = PlsrPersistenceHsdRecordIsValid(slotB);
  339. if ((validA == 0U) && (validB == 0U))
  340. {
  341. (void)memset(data, 0, sizeof(*data));
  342. return PLSR_PERSISTENCE_DEFAULTED;
  343. }
  344. if ((validA != 0U) && (validB != 0U))
  345. {
  346. generationA = slotA->generation;
  347. generationB = slotB->generation;
  348. selected = (PlsrPersistenceGenerationIsNewer(generationB,
  349. generationA)
  350. != 0U)
  351. ? slotB
  352. : slotA;
  353. }
  354. else
  355. {
  356. selected = (validA != 0U) ? slotA : slotB;
  357. }
  358. PlsrPersistenceCopyHsdFromVolatile(data, &selected->data);
  359. return PLSR_PERSISTENCE_OK;
  360. }
  361. PLSR_PERSISTENCE_RESULT PlsrPersistenceSaveHsd(const PLSR_HSD_DATA *data)
  362. {
  363. volatile PLSR_HSD_BACKUP_RECORD *slotA;
  364. volatile PLSR_HSD_BACKUP_RECORD *slotB;
  365. volatile PLSR_HSD_BACKUP_RECORD *target;
  366. PLSR_HSD_BACKUP_RECORD record;
  367. uint32_t newestGeneration = 0UL;
  368. uint32_t generationA;
  369. uint32_t generationB;
  370. uint8_t validA;
  371. uint8_t validB;
  372. if (data == NULL)
  373. {
  374. return PLSR_PERSISTENCE_INVALID_ARGUMENT;
  375. }
  376. if (sizeof(PLSR_HSD_BACKUP_RECORD) > PLSR_BACKUP_SLOT_STRIDE)
  377. {
  378. return PLSR_PERSISTENCE_VERIFY_FAILED;
  379. }
  380. slotA = PlsrPersistenceGetHsdSlot(0U);
  381. slotB = PlsrPersistenceGetHsdSlot(1U);
  382. validA = PlsrPersistenceHsdRecordIsValid(slotA);
  383. validB = PlsrPersistenceHsdRecordIsValid(slotB);
  384. if ((validA != 0U) && (validB != 0U))
  385. {
  386. generationA = slotA->generation;
  387. generationB = slotB->generation;
  388. if (PlsrPersistenceGenerationIsNewer(generationB,
  389. generationA)
  390. != 0U)
  391. {
  392. newestGeneration = generationB;
  393. target = slotA;
  394. }
  395. else
  396. {
  397. newestGeneration = generationA;
  398. target = slotB;
  399. }
  400. }
  401. else if (validA != 0U)
  402. {
  403. newestGeneration = slotA->generation;
  404. target = slotB;
  405. }
  406. else if (validB != 0U)
  407. {
  408. newestGeneration = slotB->generation;
  409. target = slotA;
  410. }
  411. else
  412. {
  413. target = slotA;
  414. }
  415. (void)memset(&record, 0, sizeof(record));
  416. record.magic = PLSR_HSD_BACKUP_MAGIC;
  417. record.version = PLSR_HSD_BACKUP_VERSION;
  418. record.payloadLength = (uint16_t)sizeof(PLSR_HSD_DATA);
  419. record.generation = newestGeneration + 1UL;
  420. record.data = *data;
  421. record.crc32 = PlsrPersistenceCrc32(
  422. (const volatile uint8_t *)&record,
  423. (uint32_t)offsetof(PLSR_HSD_BACKUP_RECORD, crc32));
  424. PlsrPersistenceWriteRecord(target, &record);
  425. return (PlsrPersistenceHsdRecordIsValid(target) != 0U)
  426. ? PLSR_PERSISTENCE_OK
  427. : PLSR_PERSISTENCE_VERIFY_FAILED;
  428. }
  429. void PlsrPersistenceResetHsd(void)
  430. {
  431. PlsrPersistenceGetHsdSlot(0U)->magic = 0UL;
  432. PlsrPersistenceGetHsdSlot(1U)->magic = 0UL;
  433. #ifndef PLSR_HOST_TEST
  434. __DMB();
  435. #endif
  436. }
  437. PLSR_PERSISTENCE_RESULT PlsrPersistenceLoadSfd(PLSR_SFD_DATA *data)
  438. {
  439. volatile PLSR_SFD_FLASH_RECORD *slotA;
  440. volatile PLSR_SFD_FLASH_RECORD *slotB;
  441. const volatile PLSR_SFD_FLASH_RECORD *selected;
  442. uint32_t generationA;
  443. uint32_t generationB;
  444. uint8_t validA;
  445. uint8_t validB;
  446. if (data == NULL)
  447. {
  448. return PLSR_PERSISTENCE_INVALID_ARGUMENT;
  449. }
  450. slotA = PlsrPersistenceGetSfdSlot(0U);
  451. slotB = PlsrPersistenceGetSfdSlot(1U);
  452. validA = PlsrPersistenceSfdRecordIsValid(slotA);
  453. validB = PlsrPersistenceSfdRecordIsValid(slotB);
  454. if ((validA == 0U) && (validB == 0U))
  455. {
  456. PlsrPersistenceApplySfdDefaults(data);
  457. return PLSR_PERSISTENCE_DEFAULTED;
  458. }
  459. if ((validA != 0U) && (validB != 0U))
  460. {
  461. generationA = slotA->generation;
  462. generationB = slotB->generation;
  463. selected = (PlsrPersistenceGenerationIsNewer(generationB,
  464. generationA)
  465. != 0U)
  466. ? slotB
  467. : slotA;
  468. }
  469. else
  470. {
  471. selected = (validA != 0U) ? slotA : slotB;
  472. }
  473. PlsrPersistenceCopySfdFromVolatile(data, &selected->data);
  474. return PLSR_PERSISTENCE_OK;
  475. }
  476. PLSR_PERSISTENCE_RESULT PlsrPersistenceSaveSfd(const PLSR_SFD_DATA *data)
  477. {
  478. volatile PLSR_SFD_FLASH_RECORD *slotA;
  479. volatile PLSR_SFD_FLASH_RECORD *slotB;
  480. volatile PLSR_SFD_FLASH_RECORD *target;
  481. volatile uint32_t *targetWords;
  482. const uint32_t *headerWords;
  483. const uint32_t *dataWords;
  484. PLSR_SFD_FLASH_HEADER header;
  485. PLSR_PERSISTENCE_RESULT result;
  486. uint32_t newestGeneration = 0UL;
  487. uint32_t generationA;
  488. uint32_t generationB;
  489. uint32_t headerWordCount;
  490. uint32_t dataWordCount;
  491. uint32_t crcState;
  492. uint32_t crc32;
  493. uint32_t index;
  494. uint8_t targetSlot;
  495. uint8_t validA;
  496. uint8_t validB;
  497. if (data == NULL)
  498. {
  499. return PLSR_PERSISTENCE_INVALID_ARGUMENT;
  500. }
  501. if (sizeof(PLSR_SFD_FLASH_RECORD) > PLSR_SFD_FLASH_SECTOR_SIZE)
  502. {
  503. return PLSR_PERSISTENCE_VERIFY_FAILED;
  504. }
  505. slotA = PlsrPersistenceGetSfdSlot(0U);
  506. slotB = PlsrPersistenceGetSfdSlot(1U);
  507. validA = PlsrPersistenceSfdRecordIsValid(slotA);
  508. validB = PlsrPersistenceSfdRecordIsValid(slotB);
  509. if ((validA != 0U) && (validB != 0U))
  510. {
  511. generationA = slotA->generation;
  512. generationB = slotB->generation;
  513. if (PlsrPersistenceGenerationIsNewer(generationB,
  514. generationA)
  515. != 0U)
  516. {
  517. newestGeneration = generationB;
  518. target = slotA;
  519. targetSlot = 0U;
  520. }
  521. else
  522. {
  523. newestGeneration = generationA;
  524. target = slotB;
  525. targetSlot = 1U;
  526. }
  527. }
  528. else if (validA != 0U)
  529. {
  530. newestGeneration = slotA->generation;
  531. target = slotB;
  532. targetSlot = 1U;
  533. }
  534. else if (validB != 0U)
  535. {
  536. newestGeneration = slotB->generation;
  537. target = slotA;
  538. targetSlot = 0U;
  539. }
  540. else
  541. {
  542. target = slotA;
  543. targetSlot = 0U;
  544. }
  545. header.magic = PLSR_SFD_FLASH_MAGIC;
  546. header.version = PLSR_SFD_FLASH_VERSION;
  547. header.payloadLength = (uint16_t)sizeof(PLSR_SFD_DATA);
  548. header.generation = newestGeneration + 1UL;
  549. crcState = PlsrPersistenceCrc32Update(
  550. 0xFFFFFFFFUL,
  551. (const volatile uint8_t *)&header,
  552. (uint32_t)sizeof(header));
  553. crcState = PlsrPersistenceCrc32Update(
  554. crcState,
  555. (const volatile uint8_t *)data,
  556. (uint32_t)sizeof(*data));
  557. crc32 = ~crcState;
  558. headerWordCount = (uint32_t)(sizeof(header) / sizeof(uint32_t));
  559. dataWordCount = (uint32_t)(sizeof(*data) / sizeof(uint32_t));
  560. headerWords = (const uint32_t *)&header;
  561. dataWords = (const uint32_t *)data;
  562. targetWords = (volatile uint32_t *)target;
  563. result = PlsrPersistenceBeginSfdOperation();
  564. if (result != PLSR_PERSISTENCE_OK)
  565. {
  566. return result;
  567. }
  568. result = PlsrPersistenceEraseSfdSlot(targetSlot);
  569. if (result != PLSR_PERSISTENCE_OK)
  570. {
  571. return PlsrPersistenceEndSfdOperation(result);
  572. }
  573. /* The valid magic is committed last so an interrupted write stays invalid. */
  574. for (index = 1U; index < headerWordCount; index++)
  575. {
  576. result = PlsrPersistenceProgramSfdWord(&targetWords[index],
  577. headerWords[index]);
  578. if (result != PLSR_PERSISTENCE_OK)
  579. {
  580. return PlsrPersistenceEndSfdOperation(result);
  581. }
  582. }
  583. for (index = 0U; index < dataWordCount; index++)
  584. {
  585. result = PlsrPersistenceProgramSfdWord(
  586. &targetWords[headerWordCount + index],
  587. dataWords[index]);
  588. if (result != PLSR_PERSISTENCE_OK)
  589. {
  590. return PlsrPersistenceEndSfdOperation(result);
  591. }
  592. }
  593. result = PlsrPersistenceProgramSfdWord(
  594. &targetWords[headerWordCount + dataWordCount],
  595. crc32);
  596. if (result != PLSR_PERSISTENCE_OK)
  597. {
  598. return PlsrPersistenceEndSfdOperation(result);
  599. }
  600. #ifdef PLSR_HOST_TEST
  601. if (PlsrHostSfdFault == PLSR_TEST_SFD_FAULT_VERIFY)
  602. {
  603. targetWords[1] ^= 1UL;
  604. PlsrHostSfdFault = PLSR_TEST_SFD_FAULT_NONE;
  605. }
  606. #endif
  607. if (PlsrPersistenceSfdBodyMatches(targetWords,
  608. &header,
  609. data,
  610. crc32)
  611. == 0U)
  612. {
  613. return PlsrPersistenceEndSfdOperation(
  614. PLSR_PERSISTENCE_VERIFY_FAILED);
  615. }
  616. #ifdef PLSR_HOST_TEST
  617. if (PlsrHostSfdFault == PLSR_TEST_SFD_FAULT_BEFORE_COMMIT)
  618. {
  619. PlsrHostSfdFault = PLSR_TEST_SFD_FAULT_NONE;
  620. return PlsrPersistenceEndSfdOperation(
  621. PLSR_PERSISTENCE_PROGRAM_FAILED);
  622. }
  623. #endif
  624. result = PlsrPersistenceProgramSfdWord(&targetWords[0], headerWords[0]);
  625. if (result != PLSR_PERSISTENCE_OK)
  626. {
  627. return PlsrPersistenceEndSfdOperation(result);
  628. }
  629. result = (PlsrPersistenceSfdRecordIsValid(target) != 0U)
  630. ? PLSR_PERSISTENCE_OK
  631. : PLSR_PERSISTENCE_VERIFY_FAILED;
  632. return PlsrPersistenceEndSfdOperation(result);
  633. }
  634. PLSR_PERSISTENCE_RESULT PlsrPersistenceEraseSfd(void)
  635. {
  636. PLSR_PERSISTENCE_RESULT result;
  637. result = PlsrPersistenceBeginSfdOperation();
  638. if (result != PLSR_PERSISTENCE_OK)
  639. {
  640. return result;
  641. }
  642. result = PlsrPersistenceEraseSfdSlot(0U);
  643. if (result == PLSR_PERSISTENCE_OK)
  644. {
  645. result = PlsrPersistenceEraseSfdSlot(1U);
  646. }
  647. return PlsrPersistenceEndSfdOperation(result);
  648. }
  649. #ifdef PLSR_HOST_TEST
  650. void PlsrPersistenceTestResetStorage(void)
  651. {
  652. (void)memset(PlsrHostBackupSlots, 0, sizeof(PlsrHostBackupSlots));
  653. (void)memset(PlsrHostSfdSlots, 0xFF, sizeof(PlsrHostSfdSlots));
  654. PlsrHostSfdFault = PLSR_TEST_SFD_FAULT_NONE;
  655. }
  656. void PlsrPersistenceTestCorruptNewestHsd(void)
  657. {
  658. volatile PLSR_HSD_BACKUP_RECORD *slotA = PlsrPersistenceGetHsdSlot(0U);
  659. volatile PLSR_HSD_BACKUP_RECORD *slotB = PlsrPersistenceGetHsdSlot(1U);
  660. uint8_t validA = PlsrPersistenceHsdRecordIsValid(slotA);
  661. uint8_t validB = PlsrPersistenceHsdRecordIsValid(slotB);
  662. volatile PLSR_HSD_BACKUP_RECORD *newest;
  663. if ((validA == 0U) && (validB == 0U))
  664. {
  665. return;
  666. }
  667. if ((validA != 0U) && (validB != 0U))
  668. {
  669. newest = (PlsrPersistenceGenerationIsNewer(slotB->generation,
  670. slotA->generation)
  671. != 0U)
  672. ? slotB
  673. : slotA;
  674. }
  675. else
  676. {
  677. newest = (validA != 0U) ? slotA : slotB;
  678. }
  679. newest->crc32 ^= 1UL;
  680. }
  681. void PlsrPersistenceTestCorruptNewestSfd(void)
  682. {
  683. volatile PLSR_SFD_FLASH_RECORD *slotA = PlsrPersistenceGetSfdSlot(0U);
  684. volatile PLSR_SFD_FLASH_RECORD *slotB = PlsrPersistenceGetSfdSlot(1U);
  685. uint8_t validA = PlsrPersistenceSfdRecordIsValid(slotA);
  686. uint8_t validB = PlsrPersistenceSfdRecordIsValid(slotB);
  687. volatile PLSR_SFD_FLASH_RECORD *newest;
  688. if ((validA == 0U) && (validB == 0U))
  689. {
  690. return;
  691. }
  692. if ((validA != 0U) && (validB != 0U))
  693. {
  694. newest = (PlsrPersistenceGenerationIsNewer(slotB->generation,
  695. slotA->generation)
  696. != 0U)
  697. ? slotB
  698. : slotA;
  699. }
  700. else
  701. {
  702. newest = (validA != 0U) ? slotA : slotB;
  703. }
  704. newest->crc32 ^= 1UL;
  705. }
  706. void PlsrPersistenceTestSetSfdFault(PLSR_TEST_SFD_FAULT fault)
  707. {
  708. PlsrHostSfdFault = fault;
  709. }
  710. #endif