Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.
 
 
 
 
 
 

1183 рядки
36 KiB

  1. #include "plsr_persistence.h"
  2. #include "plsr_build_config.h"
  3. #include <stddef.h>
  4. #include <string.h>
  5. #define PLSR_HSD_BACKUP_MAGIC (0x504C4853UL)
  6. #define PLSR_HSD_BACKUP_VERSION (2U)
  7. #define PLSR_BACKUP_SLOT_A_OFFSET (0x0100UL)
  8. #define PLSR_BACKUP_SLOT_STRIDE (0x0200UL)
  9. #define PLSR_SFD_FLASH_MAGIC (0x504C5346UL)
  10. #define PLSR_SFD_FLASH_VERSION (1U)
  11. #define PLSR_SFD_FLASH_SLOT_A_ADDRESS (0x080C0000UL)
  12. #define PLSR_SFD_FLASH_SLOT_B_ADDRESS (0x080E0000UL)
  13. #define PLSR_SFD_FLASH_SECTOR_SIZE (0x00020000UL)
  14. #define PLSR_SFD_AXIS_STRIDE (130U)
  15. #define PLSR_SFD_PARAMETER_SET_COUNT (4U)
  16. #define PLSR_SFD_PARAMETER_SET_OFFSET (50U)
  17. #define PLSR_SFD_PARAMETER_SET_STRIDE (20U)
  18. #define PLSR_SFD_DEFAULT_MAX_SPEED (100000UL)
  19. #define PLSR_SFD_DEFAULT_SPEED (1000UL)
  20. #define PLSR_SFD_DEFAULT_ACCEL_MS (100U)
  21. #define PLSR_SFD_DEFAULT_DECEL_MS (100U)
  22. #define PLSR_SFD_DEFAULT_FOLLOW (50U)
  23. #define PLSR_HSD_PARAMETER_SET_STRIDE (20U)
  24. #define PLSR_HSD_DEFAULT_BASE (460U)
  25. static const uint32_t PlsrPersistenceCrc32Nibble[16] =
  26. {
  27. 0x00000000UL, 0x1DB71064UL, 0x3B6E20C8UL, 0x26D930ACUL,
  28. 0x76DC4190UL, 0x6B6B51F4UL, 0x4DB26158UL, 0x5005713CUL,
  29. 0xEDB88320UL, 0xF00F9344UL, 0xD6D6A3E8UL, 0xCB61B38CUL,
  30. 0x9B64C2B0UL, 0x86D3D2D4UL, 0xA00AE278UL, 0xBDBDF21CUL
  31. };
  32. typedef struct
  33. {
  34. uint32_t magic;
  35. uint16_t version;
  36. uint16_t payloadLength;
  37. uint32_t generation;
  38. PLSR_HSD_DATA data;
  39. uint32_t crc32;
  40. } PLSR_HSD_BACKUP_RECORD;
  41. typedef struct
  42. {
  43. uint32_t magic;
  44. uint16_t version;
  45. uint16_t payloadLength;
  46. uint32_t generation;
  47. } PLSR_SFD_FLASH_HEADER;
  48. typedef struct
  49. {
  50. uint32_t magic;
  51. uint16_t version;
  52. uint16_t payloadLength;
  53. uint32_t generation;
  54. PLSR_SFD_DATA data;
  55. uint32_t crc32;
  56. } PLSR_SFD_FLASH_RECORD;
  57. #ifdef PLSR_HOST_TEST
  58. static PLSR_HSD_BACKUP_RECORD PlsrHostBackupSlots[2];
  59. static PLSR_SFD_FLASH_RECORD PlsrHostSfdSlots[2];
  60. static PLSR_TEST_SFD_FAULT PlsrHostSfdFault;
  61. static uint32_t PlsrHostHsdSaveCount;
  62. #else
  63. #include "stm32f4xx.h"
  64. #include "stm32f4xx_hal.h"
  65. #include "stm32f4xx_hal_flash_ex.h"
  66. #endif
  67. static PLSR_PERSISTENCE_DIAGNOSTICS PlsrPersistenceDiagnostics;
  68. static uint8_t PlsrPersistenceDiagnosticsInitialized;
  69. static void PlsrPersistenceEnsureDiagnostics(void)
  70. {
  71. if (PlsrPersistenceDiagnosticsInitialized == 0U)
  72. {
  73. (void)memset(&PlsrPersistenceDiagnostics,
  74. 0,
  75. sizeof(PlsrPersistenceDiagnostics));
  76. PlsrPersistenceDiagnostics.lastHsdLoadResult =
  77. PLSR_PERSISTENCE_NOT_IMPLEMENTED;
  78. PlsrPersistenceDiagnostics.lastSfdLoadResult =
  79. PLSR_PERSISTENCE_NOT_IMPLEMENTED;
  80. PlsrPersistenceDiagnostics.lastHsdSaveResult =
  81. PLSR_PERSISTENCE_NOT_IMPLEMENTED;
  82. PlsrPersistenceDiagnostics.lastSfdSaveResult =
  83. PLSR_PERSISTENCE_NOT_IMPLEMENTED;
  84. PlsrPersistenceDiagnostics.lastSfdEraseResult =
  85. PLSR_PERSISTENCE_NOT_IMPLEMENTED;
  86. #if PLSR_ENABLE_DESTRUCTIVE_PERSISTENCE_DIAG != 0U
  87. PlsrPersistenceDiagnostics.destructiveDiagnosticEnabled = 1U;
  88. #endif
  89. PlsrPersistenceDiagnosticsInitialized = 1U;
  90. }
  91. }
  92. static uint32_t PlsrPersistenceCrc32Update(uint32_t crc,
  93. const volatile uint8_t *data,
  94. uint32_t length)
  95. {
  96. uint32_t index;
  97. for (index = 0U; index < length; index++)
  98. {
  99. crc ^= data[index];
  100. crc = (crc >> 4U)
  101. ^ PlsrPersistenceCrc32Nibble[crc & 0x0FUL];
  102. crc = (crc >> 4U)
  103. ^ PlsrPersistenceCrc32Nibble[crc & 0x0FUL];
  104. }
  105. return crc;
  106. }
  107. static uint32_t PlsrPersistenceCrc32(const volatile uint8_t *data,
  108. uint32_t length)
  109. {
  110. return ~PlsrPersistenceCrc32Update(0xFFFFFFFFUL, data, length);
  111. }
  112. static volatile PLSR_HSD_BACKUP_RECORD *PlsrPersistenceGetHsdSlot(
  113. uint8_t slot)
  114. {
  115. #ifdef PLSR_HOST_TEST
  116. return &PlsrHostBackupSlots[slot];
  117. #else
  118. uint32_t offset = PLSR_BACKUP_SLOT_A_OFFSET
  119. + (uint32_t)slot * PLSR_BACKUP_SLOT_STRIDE;
  120. return (volatile PLSR_HSD_BACKUP_RECORD *)(BKPSRAM_BASE + offset);
  121. #endif
  122. }
  123. static uint8_t PlsrPersistenceHsdRecordIsValid(
  124. const volatile PLSR_HSD_BACKUP_RECORD *record)
  125. {
  126. uint32_t expectedCrc;
  127. if ((record->magic != PLSR_HSD_BACKUP_MAGIC)
  128. || (record->version != PLSR_HSD_BACKUP_VERSION)
  129. || (record->payloadLength != sizeof(PLSR_HSD_DATA)))
  130. {
  131. return 0U;
  132. }
  133. expectedCrc = PlsrPersistenceCrc32(
  134. (const volatile uint8_t *)record,
  135. (uint32_t)offsetof(PLSR_HSD_BACKUP_RECORD, crc32));
  136. return (expectedCrc == record->crc32) ? 1U : 0U;
  137. }
  138. static uint8_t PlsrPersistenceGenerationIsNewer(uint32_t left,
  139. uint32_t right)
  140. {
  141. return (((int32_t)(left - right)) > 0) ? 1U : 0U;
  142. }
  143. static volatile PLSR_SFD_FLASH_RECORD *PlsrPersistenceGetSfdSlot(
  144. uint8_t slot)
  145. {
  146. #ifdef PLSR_HOST_TEST
  147. return &PlsrHostSfdSlots[slot];
  148. #else
  149. uint32_t address = (slot == 0U) ? PLSR_SFD_FLASH_SLOT_A_ADDRESS
  150. : PLSR_SFD_FLASH_SLOT_B_ADDRESS;
  151. return (volatile PLSR_SFD_FLASH_RECORD *)address;
  152. #endif
  153. }
  154. static uint8_t PlsrPersistenceSfdRecordIsValid(
  155. const volatile PLSR_SFD_FLASH_RECORD *record)
  156. {
  157. uint32_t expectedCrc;
  158. if ((record->magic != PLSR_SFD_FLASH_MAGIC)
  159. || (record->version != PLSR_SFD_FLASH_VERSION)
  160. || (record->payloadLength != sizeof(PLSR_SFD_DATA)))
  161. {
  162. return 0U;
  163. }
  164. expectedCrc = PlsrPersistenceCrc32(
  165. (const volatile uint8_t *)record,
  166. (uint32_t)offsetof(PLSR_SFD_FLASH_RECORD, crc32));
  167. return (expectedCrc == record->crc32) ? 1U : 0U;
  168. }
  169. static uint8_t PlsrPersistenceNewestMask(uint8_t validA,
  170. uint8_t validB,
  171. uint32_t generationA,
  172. uint32_t generationB)
  173. {
  174. if ((validA != 0U) && (validB != 0U))
  175. {
  176. return (PlsrPersistenceGenerationIsNewer(generationB, generationA)
  177. != 0U)
  178. ? 2U
  179. : 1U;
  180. }
  181. if (validA != 0U)
  182. {
  183. return 1U;
  184. }
  185. return (validB != 0U) ? 2U : 0U;
  186. }
  187. static void PlsrPersistenceUpdateHsdDiagnostics(
  188. const volatile PLSR_HSD_BACKUP_RECORD *slotA,
  189. const volatile PLSR_HSD_BACKUP_RECORD *slotB,
  190. uint8_t validA,
  191. uint8_t validB)
  192. {
  193. uint8_t newestMask;
  194. PlsrPersistenceEnsureDiagnostics();
  195. PlsrPersistenceDiagnostics.hsdValidMask =
  196. (uint8_t)((validA != 0U ? 1U : 0U) | (validB != 0U ? 2U : 0U));
  197. PlsrPersistenceDiagnostics.hsdGeneration[0] =
  198. (validA != 0U) ? slotA->generation : 0UL;
  199. PlsrPersistenceDiagnostics.hsdGeneration[1] =
  200. (validB != 0U) ? slotB->generation : 0UL;
  201. newestMask = PlsrPersistenceNewestMask(
  202. validA,
  203. validB,
  204. PlsrPersistenceDiagnostics.hsdGeneration[0],
  205. PlsrPersistenceDiagnostics.hsdGeneration[1]);
  206. PlsrPersistenceDiagnostics.hsdNewestMask = newestMask;
  207. PlsrPersistenceDiagnostics.selectedHsdCrc32 =
  208. (newestMask == 1U) ? slotA->crc32
  209. : (newestMask == 2U) ? slotB->crc32
  210. : 0UL;
  211. }
  212. static void PlsrPersistenceUpdateSfdDiagnostics(
  213. const volatile PLSR_SFD_FLASH_RECORD *slotA,
  214. const volatile PLSR_SFD_FLASH_RECORD *slotB,
  215. uint8_t validA,
  216. uint8_t validB)
  217. {
  218. uint8_t newestMask;
  219. PlsrPersistenceEnsureDiagnostics();
  220. PlsrPersistenceDiagnostics.sfdValidMask =
  221. (uint8_t)((validA != 0U ? 1U : 0U) | (validB != 0U ? 2U : 0U));
  222. PlsrPersistenceDiagnostics.sfdGeneration[0] =
  223. (validA != 0U) ? slotA->generation : 0UL;
  224. PlsrPersistenceDiagnostics.sfdGeneration[1] =
  225. (validB != 0U) ? slotB->generation : 0UL;
  226. newestMask = PlsrPersistenceNewestMask(
  227. validA,
  228. validB,
  229. PlsrPersistenceDiagnostics.sfdGeneration[0],
  230. PlsrPersistenceDiagnostics.sfdGeneration[1]);
  231. PlsrPersistenceDiagnostics.sfdNewestMask = newestMask;
  232. PlsrPersistenceDiagnostics.selectedSfdCrc32 =
  233. (newestMask == 1U) ? slotA->crc32
  234. : (newestMask == 2U) ? slotB->crc32
  235. : 0UL;
  236. }
  237. static void PlsrPersistenceRefreshSfdDiagnostics(void)
  238. {
  239. volatile PLSR_SFD_FLASH_RECORD *slotA =
  240. PlsrPersistenceGetSfdSlot(0U);
  241. volatile PLSR_SFD_FLASH_RECORD *slotB =
  242. PlsrPersistenceGetSfdSlot(1U);
  243. PlsrPersistenceUpdateSfdDiagnostics(
  244. slotA,
  245. slotB,
  246. PlsrPersistenceSfdRecordIsValid(slotA),
  247. PlsrPersistenceSfdRecordIsValid(slotB));
  248. }
  249. static PLSR_PERSISTENCE_RESULT PlsrPersistenceCompleteSfdSave(
  250. PLSR_PERSISTENCE_RESULT result)
  251. {
  252. PlsrPersistenceEnsureDiagnostics();
  253. PlsrPersistenceDiagnostics.lastSfdSaveResult = result;
  254. PlsrPersistenceRefreshSfdDiagnostics();
  255. if (result == PLSR_PERSISTENCE_OK)
  256. {
  257. PlsrPersistenceDiagnostics.sfdSaveCount++;
  258. }
  259. return result;
  260. }
  261. static void PlsrPersistenceCopySfdFromVolatile(
  262. PLSR_SFD_DATA *destination,
  263. const volatile PLSR_SFD_DATA *source)
  264. {
  265. uint16_t index;
  266. for (index = 0U; index < PLSR_SFD_CONFIG_COUNT; index++)
  267. {
  268. destination->config[index] = source->config[index];
  269. }
  270. }
  271. static void PlsrPersistenceApplyParameterSetDefaults(uint16_t *config,
  272. uint16_t base)
  273. {
  274. /* 与信捷出厂默认一致:默认速度1000、加减速100ms、最大速度100000、
  275. * 起始/终止速度0、FOLLOW 50、前馈0、1ms刷新。 */
  276. config[base + 0U] = (uint16_t)(PLSR_SFD_DEFAULT_SPEED & 0xFFFFUL);
  277. config[base + 1U] = (uint16_t)(PLSR_SFD_DEFAULT_SPEED >> 16U);
  278. config[base + 2U] = (uint16_t)PLSR_SFD_DEFAULT_ACCEL_MS;
  279. config[base + 3U] = (uint16_t)PLSR_SFD_DEFAULT_DECEL_MS;
  280. config[base + 4U] = 0U;
  281. config[base + 5U] = 0U;
  282. config[base + 6U] = (uint16_t)(PLSR_SFD_DEFAULT_MAX_SPEED & 0xFFFFUL);
  283. config[base + 7U] = (uint16_t)(PLSR_SFD_DEFAULT_MAX_SPEED >> 16U);
  284. config[base + 8U] = 0U;
  285. config[base + 9U] = 0U;
  286. config[base + 10U] = 0U;
  287. config[base + 11U] = 0U;
  288. config[base + 12U] = (uint16_t)PLSR_SFD_DEFAULT_FOLLOW;
  289. config[base + 13U] = 0U;
  290. config[base + 14U] = 0U;
  291. config[base + 16U] = 0U;
  292. config[base + 17U] = 0U;
  293. config[base + 18U] = 0U;
  294. config[base + 19U] = 0U;
  295. }
  296. static void PlsrPersistenceApplySfdDefaults(PLSR_SFD_DATA *data)
  297. {
  298. uint16_t axisOffset;
  299. uint16_t parameterOffset;
  300. uint8_t axis;
  301. uint8_t parameterSet;
  302. (void)memset(data, 0, sizeof(*data));
  303. for (axis = 0U; axis < PLSR_AXIS_COUNT; axis++)
  304. {
  305. axisOffset = (uint16_t)((uint16_t)axis * PLSR_SFD_AXIS_STRIDE);
  306. /* 公共参数(与信捷出厂默认一致)。 */
  307. data->config[axisOffset + 0U] = 0; /* SFD900 方向逻辑/单位等 */
  308. data->config[axisOffset + 1U] = 0; /* SFD901 完成模式 */
  309. data->config[axisOffset + 2U] = 1; /* SFD902 脉冲数/1转=1 */
  310. data->config[axisOffset + 3U] = 0;
  311. data->config[axisOffset + 4U] = 1; /* SFD904 移动量/1转=1 */
  312. data->config[axisOffset + 5U] = 0;
  313. data->config[axisOffset + 6U] = 0xFF; /* SFD906 方向端子:无 */
  314. data->config[axisOffset + 7U] = 10; /* SFD907 方向延时10ms */
  315. data->config[axisOffset + 8U] = 0; /* SFD908 正向齿隙 */
  316. data->config[axisOffset + 9U] = 0; /* SFD909 负向齿隙 */
  317. data->config[axisOffset + 12U] = 0; /* SFD912 端子开关状态 */
  318. data->config[axisOffset + 13U] = 0xFF; /* SFD913 原点端子:无 */
  319. data->config[axisOffset + 14U] = 0xFF; /* SFD914 Z相端子:无 */
  320. data->config[axisOffset + 15U] = 0xFFFF; /* SFD915 极限端子:无 */
  321. data->config[axisOffset + 17U] = 0xFF; /* SFD917 CLR端子:无 */
  322. data->config[axisOffset + 18U] = 0; /* SFD918 VH */
  323. data->config[axisOffset + 19U] = 0;
  324. data->config[axisOffset + 22U] = 0; /* SFD922 VC */
  325. data->config[axisOffset + 23U] = 0;
  326. data->config[axisOffset + 24U] = 0; /* SFD924 机械原点位置 */
  327. data->config[axisOffset + 25U] = 0;
  328. data->config[axisOffset + 26U] = 0; /* SFD926 Z相个数 */
  329. data->config[axisOffset + 27U] = 20; /* SFD927 CLR延时20ms */
  330. data->config[axisOffset + 30U] = 0; /* SFD930 软限位正 */
  331. data->config[axisOffset + 31U] = 0;
  332. data->config[axisOffset + 32U] = 0; /* SFD932 软限位负 */
  333. data->config[axisOffset + 33U] = 0;
  334. data->config[axisOffset + 43U] = 0x0201; /* SFD943 默认参数块 */
  335. for (parameterSet = 0U;
  336. parameterSet < PLSR_SFD_PARAMETER_SET_COUNT;
  337. parameterSet++)
  338. {
  339. parameterOffset = (uint16_t)(
  340. axisOffset + PLSR_SFD_PARAMETER_SET_OFFSET
  341. + (uint16_t)parameterSet * PLSR_SFD_PARAMETER_SET_STRIDE);
  342. PlsrPersistenceApplyParameterSetDefaults(data->config,
  343. parameterOffset);
  344. }
  345. }
  346. }
  347. static void PlsrPersistenceApplyHsdDefaults(PLSR_HSD_DATA *data)
  348. {
  349. uint8_t axis;
  350. (void)memset(data, 0, sizeof(*data));
  351. for (axis = 0U; axis < PLSR_AXIS_COUNT; axis++)
  352. {
  353. /* config 数组索引 = HSD地址 - PLSR_HSD_CONFIG_START。 */
  354. PlsrPersistenceApplyParameterSetDefaults(
  355. data->config,
  356. (uint16_t)((uint16_t)axis * PLSR_HSD_PARAMETER_SET_STRIDE));
  357. }
  358. }
  359. static PLSR_PERSISTENCE_RESULT PlsrPersistenceBeginSfdOperation(void)
  360. {
  361. #ifdef PLSR_HOST_TEST
  362. return PLSR_PERSISTENCE_OK;
  363. #else
  364. if (HAL_FLASH_Unlock() != HAL_OK)
  365. {
  366. return PLSR_PERSISTENCE_PROGRAM_FAILED;
  367. }
  368. __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_OPERR
  369. | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR
  370. | FLASH_FLAG_PGPERR | FLASH_FLAG_PGSERR);
  371. return PLSR_PERSISTENCE_OK;
  372. #endif
  373. }
  374. static PLSR_PERSISTENCE_RESULT PlsrPersistenceEndSfdOperation(
  375. PLSR_PERSISTENCE_RESULT result)
  376. {
  377. #ifdef PLSR_HOST_TEST
  378. return result;
  379. #else
  380. if ((HAL_FLASH_Lock() != HAL_OK) && (result == PLSR_PERSISTENCE_OK))
  381. {
  382. return PLSR_PERSISTENCE_PROGRAM_FAILED;
  383. }
  384. return result;
  385. #endif
  386. }
  387. static PLSR_PERSISTENCE_RESULT PlsrPersistenceEraseSfdSlot(uint8_t slot)
  388. {
  389. #ifdef PLSR_HOST_TEST
  390. if (PlsrHostSfdFault == PLSR_TEST_SFD_FAULT_ERASE)
  391. {
  392. PlsrHostSfdFault = PLSR_TEST_SFD_FAULT_NONE;
  393. return PLSR_PERSISTENCE_ERASE_FAILED;
  394. }
  395. (void)memset(&PlsrHostSfdSlots[slot],
  396. 0xFF,
  397. sizeof(PlsrHostSfdSlots[slot]));
  398. return PLSR_PERSISTENCE_OK;
  399. #else
  400. FLASH_EraseInitTypeDef erase;
  401. uint32_t sectorError = 0xFFFFFFFFUL;
  402. erase.TypeErase = FLASH_TYPEERASE_SECTORS;
  403. erase.VoltageRange = FLASH_VOLTAGE_RANGE_3;
  404. erase.Sector = (slot == 0U) ? FLASH_SECTOR_10 : FLASH_SECTOR_11;
  405. erase.NbSectors = 1U;
  406. return (HAL_FLASHEx_Erase(&erase, &sectorError) == HAL_OK)
  407. ? PLSR_PERSISTENCE_OK
  408. : PLSR_PERSISTENCE_ERASE_FAILED;
  409. #endif
  410. }
  411. static PLSR_PERSISTENCE_RESULT PlsrPersistenceProgramSfdWord(
  412. volatile uint32_t *destination,
  413. uint32_t value)
  414. {
  415. #ifdef PLSR_HOST_TEST
  416. if (PlsrHostSfdFault == PLSR_TEST_SFD_FAULT_PROGRAM)
  417. {
  418. PlsrHostSfdFault = PLSR_TEST_SFD_FAULT_NONE;
  419. return PLSR_PERSISTENCE_PROGRAM_FAILED;
  420. }
  421. if ((*destination & value) != value)
  422. {
  423. return PLSR_PERSISTENCE_PROGRAM_FAILED;
  424. }
  425. *destination &= value;
  426. return PLSR_PERSISTENCE_OK;
  427. #else
  428. return (HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD,
  429. (uint32_t)destination,
  430. value)
  431. == HAL_OK)
  432. ? PLSR_PERSISTENCE_OK
  433. : PLSR_PERSISTENCE_PROGRAM_FAILED;
  434. #endif
  435. }
  436. static uint8_t PlsrPersistenceSfdBodyMatches(
  437. const volatile uint32_t *destination,
  438. const PLSR_SFD_FLASH_HEADER *header,
  439. const PLSR_SFD_DATA *data,
  440. uint32_t crc32)
  441. {
  442. const uint32_t *headerWords = (const uint32_t *)header;
  443. const uint32_t *dataWords = (const uint32_t *)data;
  444. uint32_t headerWordCount = (uint32_t)(sizeof(*header) / sizeof(uint32_t));
  445. uint32_t dataWordCount = (uint32_t)(sizeof(*data) / sizeof(uint32_t));
  446. uint32_t index;
  447. for (index = 1U; index < headerWordCount; index++)
  448. {
  449. if (destination[index] != headerWords[index])
  450. {
  451. return 0U;
  452. }
  453. }
  454. for (index = 0U; index < dataWordCount; index++)
  455. {
  456. if (destination[headerWordCount + index] != dataWords[index])
  457. {
  458. return 0U;
  459. }
  460. }
  461. if (destination[headerWordCount + dataWordCount] != crc32)
  462. {
  463. return 0U;
  464. }
  465. return 1U;
  466. }
  467. static void PlsrPersistenceCopyHsdFromVolatile(
  468. PLSR_HSD_DATA *destination,
  469. const volatile PLSR_HSD_DATA *source)
  470. {
  471. uint16_t index;
  472. destination->metadata = source->metadata;
  473. for (index = 0U; index < PLSR_HSD_RUNTIME_COUNT; index++)
  474. {
  475. destination->runtime[index] = source->runtime[index];
  476. }
  477. for (index = 0U; index < PLSR_HSD_CONFIG_COUNT; index++)
  478. {
  479. destination->config[index] = source->config[index];
  480. }
  481. }
  482. static void PlsrPersistenceWriteRecord(
  483. volatile PLSR_HSD_BACKUP_RECORD *destination,
  484. const PLSR_HSD_BACKUP_RECORD *source)
  485. {
  486. const uint32_t *sourceWords = (const uint32_t *)source;
  487. volatile uint32_t *destinationWords = (volatile uint32_t *)destination;
  488. uint32_t wordCount = (uint32_t)(sizeof(PLSR_HSD_BACKUP_RECORD)
  489. / sizeof(uint32_t));
  490. uint32_t index;
  491. destination->magic = 0UL;
  492. #ifndef PLSR_HOST_TEST
  493. __DMB();
  494. #endif
  495. for (index = 1U; index < wordCount; index++)
  496. {
  497. destinationWords[index] = sourceWords[index];
  498. }
  499. #ifndef PLSR_HOST_TEST
  500. __DMB();
  501. #endif
  502. destination->magic = PLSR_HSD_BACKUP_MAGIC;
  503. #ifndef PLSR_HOST_TEST
  504. __DMB();
  505. #endif
  506. }
  507. PLSR_PERSISTENCE_RESULT PlsrPersistenceLoadHsd(PLSR_HSD_DATA *data)
  508. {
  509. volatile PLSR_HSD_BACKUP_RECORD *slotA;
  510. volatile PLSR_HSD_BACKUP_RECORD *slotB;
  511. const volatile PLSR_HSD_BACKUP_RECORD *selected;
  512. uint32_t generationA;
  513. uint32_t generationB;
  514. uint8_t validA;
  515. uint8_t validB;
  516. PlsrPersistenceEnsureDiagnostics();
  517. if (data == NULL)
  518. {
  519. PlsrPersistenceDiagnostics.lastHsdLoadResult =
  520. PLSR_PERSISTENCE_INVALID_ARGUMENT;
  521. return PLSR_PERSISTENCE_INVALID_ARGUMENT;
  522. }
  523. slotA = PlsrPersistenceGetHsdSlot(0U);
  524. slotB = PlsrPersistenceGetHsdSlot(1U);
  525. validA = PlsrPersistenceHsdRecordIsValid(slotA);
  526. validB = PlsrPersistenceHsdRecordIsValid(slotB);
  527. PlsrPersistenceUpdateHsdDiagnostics(slotA, slotB, validA, validB);
  528. if ((validA == 0U) && (validB == 0U))
  529. {
  530. PlsrPersistenceApplyHsdDefaults(data);
  531. PlsrPersistenceDiagnostics.lastHsdLoadResult =
  532. PLSR_PERSISTENCE_DEFAULTED;
  533. return PLSR_PERSISTENCE_DEFAULTED;
  534. }
  535. if ((validA != 0U) && (validB != 0U))
  536. {
  537. generationA = slotA->generation;
  538. generationB = slotB->generation;
  539. selected = (PlsrPersistenceGenerationIsNewer(generationB,
  540. generationA)
  541. != 0U)
  542. ? slotB
  543. : slotA;
  544. }
  545. else
  546. {
  547. selected = (validA != 0U) ? slotA : slotB;
  548. }
  549. PlsrPersistenceCopyHsdFromVolatile(data, &selected->data);
  550. PlsrPersistenceDiagnostics.lastHsdLoadResult = PLSR_PERSISTENCE_OK;
  551. return PLSR_PERSISTENCE_OK;
  552. }
  553. PLSR_PERSISTENCE_RESULT PlsrPersistenceSaveHsd(const PLSR_HSD_DATA *data)
  554. {
  555. volatile PLSR_HSD_BACKUP_RECORD *slotA;
  556. volatile PLSR_HSD_BACKUP_RECORD *slotB;
  557. volatile PLSR_HSD_BACKUP_RECORD *target;
  558. PLSR_HSD_BACKUP_RECORD record;
  559. uint32_t newestGeneration = 0UL;
  560. uint32_t generationA;
  561. uint32_t generationB;
  562. uint8_t validA;
  563. uint8_t validB;
  564. uint8_t targetSlot;
  565. uint8_t targetValid;
  566. PlsrPersistenceEnsureDiagnostics();
  567. if (data == NULL)
  568. {
  569. PlsrPersistenceDiagnostics.lastHsdSaveResult =
  570. PLSR_PERSISTENCE_INVALID_ARGUMENT;
  571. return PLSR_PERSISTENCE_INVALID_ARGUMENT;
  572. }
  573. #ifdef PLSR_HOST_TEST
  574. PlsrHostHsdSaveCount++;
  575. #endif
  576. if (sizeof(PLSR_HSD_BACKUP_RECORD) > PLSR_BACKUP_SLOT_STRIDE)
  577. {
  578. PlsrPersistenceDiagnostics.lastHsdSaveResult =
  579. PLSR_PERSISTENCE_VERIFY_FAILED;
  580. return PLSR_PERSISTENCE_VERIFY_FAILED;
  581. }
  582. slotA = PlsrPersistenceGetHsdSlot(0U);
  583. slotB = PlsrPersistenceGetHsdSlot(1U);
  584. validA = PlsrPersistenceHsdRecordIsValid(slotA);
  585. validB = PlsrPersistenceHsdRecordIsValid(slotB);
  586. if ((validA != 0U) && (validB != 0U))
  587. {
  588. generationA = slotA->generation;
  589. generationB = slotB->generation;
  590. if (PlsrPersistenceGenerationIsNewer(generationB,
  591. generationA)
  592. != 0U)
  593. {
  594. newestGeneration = generationB;
  595. target = slotA;
  596. targetSlot = 0U;
  597. }
  598. else
  599. {
  600. newestGeneration = generationA;
  601. target = slotB;
  602. targetSlot = 1U;
  603. }
  604. }
  605. else if (validA != 0U)
  606. {
  607. newestGeneration = slotA->generation;
  608. target = slotB;
  609. targetSlot = 1U;
  610. }
  611. else if (validB != 0U)
  612. {
  613. newestGeneration = slotB->generation;
  614. target = slotA;
  615. targetSlot = 0U;
  616. }
  617. else
  618. {
  619. target = slotA;
  620. targetSlot = 0U;
  621. }
  622. (void)memset(&record, 0, sizeof(record));
  623. record.magic = PLSR_HSD_BACKUP_MAGIC;
  624. record.version = PLSR_HSD_BACKUP_VERSION;
  625. record.payloadLength = (uint16_t)sizeof(PLSR_HSD_DATA);
  626. record.generation = newestGeneration + 1UL;
  627. record.data = *data;
  628. record.crc32 = PlsrPersistenceCrc32(
  629. (const volatile uint8_t *)&record,
  630. (uint32_t)offsetof(PLSR_HSD_BACKUP_RECORD, crc32));
  631. PlsrPersistenceWriteRecord(target, &record);
  632. targetValid = PlsrPersistenceHsdRecordIsValid(target);
  633. if (targetSlot == 0U)
  634. {
  635. validA = targetValid;
  636. }
  637. else
  638. {
  639. validB = targetValid;
  640. }
  641. PlsrPersistenceUpdateHsdDiagnostics(slotA, slotB, validA, validB);
  642. PlsrPersistenceDiagnostics.lastHsdSaveResult =
  643. (targetValid != 0U) ? PLSR_PERSISTENCE_OK
  644. : PLSR_PERSISTENCE_VERIFY_FAILED;
  645. if (targetValid != 0U)
  646. {
  647. PlsrPersistenceDiagnostics.hsdSaveCount++;
  648. }
  649. return PlsrPersistenceDiagnostics.lastHsdSaveResult;
  650. }
  651. void PlsrPersistenceResetHsd(void)
  652. {
  653. volatile PLSR_HSD_BACKUP_RECORD *slotA =
  654. PlsrPersistenceGetHsdSlot(0U);
  655. volatile PLSR_HSD_BACKUP_RECORD *slotB =
  656. PlsrPersistenceGetHsdSlot(1U);
  657. slotA->magic = 0UL;
  658. slotB->magic = 0UL;
  659. #ifndef PLSR_HOST_TEST
  660. __DMB();
  661. #endif
  662. PlsrPersistenceUpdateHsdDiagnostics(slotA, slotB, 0U, 0U);
  663. }
  664. PLSR_PERSISTENCE_RESULT PlsrPersistenceLoadSfd(PLSR_SFD_DATA *data)
  665. {
  666. volatile PLSR_SFD_FLASH_RECORD *slotA;
  667. volatile PLSR_SFD_FLASH_RECORD *slotB;
  668. const volatile PLSR_SFD_FLASH_RECORD *selected;
  669. uint32_t generationA;
  670. uint32_t generationB;
  671. uint8_t validA;
  672. uint8_t validB;
  673. PlsrPersistenceEnsureDiagnostics();
  674. if (data == NULL)
  675. {
  676. PlsrPersistenceDiagnostics.lastSfdLoadResult =
  677. PLSR_PERSISTENCE_INVALID_ARGUMENT;
  678. return PLSR_PERSISTENCE_INVALID_ARGUMENT;
  679. }
  680. slotA = PlsrPersistenceGetSfdSlot(0U);
  681. slotB = PlsrPersistenceGetSfdSlot(1U);
  682. validA = PlsrPersistenceSfdRecordIsValid(slotA);
  683. validB = PlsrPersistenceSfdRecordIsValid(slotB);
  684. PlsrPersistenceUpdateSfdDiagnostics(slotA, slotB, validA, validB);
  685. if ((validA == 0U) && (validB == 0U))
  686. {
  687. PlsrPersistenceApplySfdDefaults(data);
  688. PlsrPersistenceDiagnostics.lastSfdLoadResult =
  689. PLSR_PERSISTENCE_DEFAULTED;
  690. return PLSR_PERSISTENCE_DEFAULTED;
  691. }
  692. if ((validA != 0U) && (validB != 0U))
  693. {
  694. generationA = slotA->generation;
  695. generationB = slotB->generation;
  696. selected = (PlsrPersistenceGenerationIsNewer(generationB,
  697. generationA)
  698. != 0U)
  699. ? slotB
  700. : slotA;
  701. }
  702. else
  703. {
  704. selected = (validA != 0U) ? slotA : slotB;
  705. }
  706. PlsrPersistenceCopySfdFromVolatile(data, &selected->data);
  707. PlsrPersistenceDiagnostics.lastSfdLoadResult = PLSR_PERSISTENCE_OK;
  708. return PLSR_PERSISTENCE_OK;
  709. }
  710. PLSR_PERSISTENCE_RESULT PlsrPersistenceSaveSfd(const PLSR_SFD_DATA *data)
  711. {
  712. volatile PLSR_SFD_FLASH_RECORD *slotA;
  713. volatile PLSR_SFD_FLASH_RECORD *slotB;
  714. volatile PLSR_SFD_FLASH_RECORD *target;
  715. volatile uint32_t *targetWords;
  716. const uint32_t *headerWords;
  717. const uint32_t *dataWords;
  718. PLSR_SFD_FLASH_HEADER header;
  719. PLSR_PERSISTENCE_RESULT result;
  720. uint32_t newestGeneration = 0UL;
  721. uint32_t generationA;
  722. uint32_t generationB;
  723. uint32_t headerWordCount;
  724. uint32_t dataWordCount;
  725. uint32_t crcState;
  726. uint32_t crc32;
  727. uint32_t index;
  728. uint8_t targetSlot;
  729. uint8_t validA;
  730. uint8_t validB;
  731. PlsrPersistenceEnsureDiagnostics();
  732. if (data == NULL)
  733. {
  734. PlsrPersistenceDiagnostics.lastSfdSaveResult =
  735. PLSR_PERSISTENCE_INVALID_ARGUMENT;
  736. return PLSR_PERSISTENCE_INVALID_ARGUMENT;
  737. }
  738. if (sizeof(PLSR_SFD_FLASH_RECORD) > PLSR_SFD_FLASH_SECTOR_SIZE)
  739. {
  740. PlsrPersistenceDiagnostics.lastSfdSaveResult =
  741. PLSR_PERSISTENCE_VERIFY_FAILED;
  742. return PLSR_PERSISTENCE_VERIFY_FAILED;
  743. }
  744. slotA = PlsrPersistenceGetSfdSlot(0U);
  745. slotB = PlsrPersistenceGetSfdSlot(1U);
  746. validA = PlsrPersistenceSfdRecordIsValid(slotA);
  747. validB = PlsrPersistenceSfdRecordIsValid(slotB);
  748. if ((validA != 0U) && (validB != 0U))
  749. {
  750. generationA = slotA->generation;
  751. generationB = slotB->generation;
  752. if (PlsrPersistenceGenerationIsNewer(generationB,
  753. generationA)
  754. != 0U)
  755. {
  756. newestGeneration = generationB;
  757. target = slotA;
  758. targetSlot = 0U;
  759. }
  760. else
  761. {
  762. newestGeneration = generationA;
  763. target = slotB;
  764. targetSlot = 1U;
  765. }
  766. }
  767. else if (validA != 0U)
  768. {
  769. newestGeneration = slotA->generation;
  770. target = slotB;
  771. targetSlot = 1U;
  772. }
  773. else if (validB != 0U)
  774. {
  775. newestGeneration = slotB->generation;
  776. target = slotA;
  777. targetSlot = 0U;
  778. }
  779. else
  780. {
  781. target = slotA;
  782. targetSlot = 0U;
  783. }
  784. header.magic = PLSR_SFD_FLASH_MAGIC;
  785. header.version = PLSR_SFD_FLASH_VERSION;
  786. header.payloadLength = (uint16_t)sizeof(PLSR_SFD_DATA);
  787. header.generation = newestGeneration + 1UL;
  788. crcState = PlsrPersistenceCrc32Update(
  789. 0xFFFFFFFFUL,
  790. (const volatile uint8_t *)&header,
  791. (uint32_t)sizeof(header));
  792. crcState = PlsrPersistenceCrc32Update(
  793. crcState,
  794. (const volatile uint8_t *)data,
  795. (uint32_t)sizeof(*data));
  796. crc32 = ~crcState;
  797. headerWordCount = (uint32_t)(sizeof(header) / sizeof(uint32_t));
  798. dataWordCount = (uint32_t)(sizeof(*data) / sizeof(uint32_t));
  799. headerWords = (const uint32_t *)&header;
  800. dataWords = (const uint32_t *)data;
  801. targetWords = (volatile uint32_t *)target;
  802. result = PlsrPersistenceBeginSfdOperation();
  803. if (result != PLSR_PERSISTENCE_OK)
  804. {
  805. return PlsrPersistenceCompleteSfdSave(result);
  806. }
  807. result = PlsrPersistenceEraseSfdSlot(targetSlot);
  808. if (result != PLSR_PERSISTENCE_OK)
  809. {
  810. result = PlsrPersistenceEndSfdOperation(result);
  811. return PlsrPersistenceCompleteSfdSave(result);
  812. }
  813. /* The valid magic is committed last so an interrupted write stays invalid. */
  814. for (index = 1U; index < headerWordCount; index++)
  815. {
  816. result = PlsrPersistenceProgramSfdWord(&targetWords[index],
  817. headerWords[index]);
  818. if (result != PLSR_PERSISTENCE_OK)
  819. {
  820. result = PlsrPersistenceEndSfdOperation(result);
  821. return PlsrPersistenceCompleteSfdSave(result);
  822. }
  823. }
  824. for (index = 0U; index < dataWordCount; index++)
  825. {
  826. result = PlsrPersistenceProgramSfdWord(
  827. &targetWords[headerWordCount + index],
  828. dataWords[index]);
  829. if (result != PLSR_PERSISTENCE_OK)
  830. {
  831. result = PlsrPersistenceEndSfdOperation(result);
  832. return PlsrPersistenceCompleteSfdSave(result);
  833. }
  834. }
  835. result = PlsrPersistenceProgramSfdWord(
  836. &targetWords[headerWordCount + dataWordCount],
  837. crc32);
  838. if (result != PLSR_PERSISTENCE_OK)
  839. {
  840. result = PlsrPersistenceEndSfdOperation(result);
  841. return PlsrPersistenceCompleteSfdSave(result);
  842. }
  843. #ifdef PLSR_HOST_TEST
  844. if (PlsrHostSfdFault == PLSR_TEST_SFD_FAULT_VERIFY)
  845. {
  846. targetWords[1] ^= 1UL;
  847. PlsrHostSfdFault = PLSR_TEST_SFD_FAULT_NONE;
  848. }
  849. #endif
  850. if (PlsrPersistenceSfdBodyMatches(targetWords,
  851. &header,
  852. data,
  853. crc32)
  854. == 0U)
  855. {
  856. result = PlsrPersistenceEndSfdOperation(
  857. PLSR_PERSISTENCE_VERIFY_FAILED);
  858. return PlsrPersistenceCompleteSfdSave(result);
  859. }
  860. #ifdef PLSR_HOST_TEST
  861. if (PlsrHostSfdFault == PLSR_TEST_SFD_FAULT_BEFORE_COMMIT)
  862. {
  863. PlsrHostSfdFault = PLSR_TEST_SFD_FAULT_NONE;
  864. result = PlsrPersistenceEndSfdOperation(
  865. PLSR_PERSISTENCE_PROGRAM_FAILED);
  866. return PlsrPersistenceCompleteSfdSave(result);
  867. }
  868. #endif
  869. result = PlsrPersistenceProgramSfdWord(&targetWords[0], headerWords[0]);
  870. if (result != PLSR_PERSISTENCE_OK)
  871. {
  872. result = PlsrPersistenceEndSfdOperation(result);
  873. return PlsrPersistenceCompleteSfdSave(result);
  874. }
  875. result = (PlsrPersistenceSfdRecordIsValid(target) != 0U)
  876. ? PLSR_PERSISTENCE_OK
  877. : PLSR_PERSISTENCE_VERIFY_FAILED;
  878. result = PlsrPersistenceEndSfdOperation(result);
  879. return PlsrPersistenceCompleteSfdSave(result);
  880. }
  881. PLSR_PERSISTENCE_RESULT PlsrPersistenceEraseSfd(void)
  882. {
  883. PLSR_PERSISTENCE_RESULT result;
  884. PlsrPersistenceEnsureDiagnostics();
  885. result = PlsrPersistenceBeginSfdOperation();
  886. if (result != PLSR_PERSISTENCE_OK)
  887. {
  888. PlsrPersistenceDiagnostics.lastSfdEraseResult = result;
  889. return result;
  890. }
  891. result = PlsrPersistenceEraseSfdSlot(0U);
  892. if (result == PLSR_PERSISTENCE_OK)
  893. {
  894. result = PlsrPersistenceEraseSfdSlot(1U);
  895. }
  896. result = PlsrPersistenceEndSfdOperation(result);
  897. PlsrPersistenceDiagnostics.lastSfdEraseResult = result;
  898. PlsrPersistenceRefreshSfdDiagnostics();
  899. return result;
  900. }
  901. void PlsrPersistenceGetDiagnostics(
  902. PLSR_PERSISTENCE_DIAGNOSTICS *diagnostics)
  903. {
  904. if (diagnostics == NULL)
  905. {
  906. return;
  907. }
  908. PlsrPersistenceEnsureDiagnostics();
  909. *diagnostics = PlsrPersistenceDiagnostics;
  910. }
  911. PLSR_PERSISTENCE_RESULT PlsrPersistenceDiagnosticInvalidateNewest(
  912. PLSR_PERSISTENCE_DIAG_TARGET target)
  913. {
  914. #if PLSR_ENABLE_DESTRUCTIVE_PERSISTENCE_DIAG != 0U
  915. uint32_t generationA;
  916. uint32_t generationB;
  917. uint8_t validA;
  918. uint8_t validB;
  919. PlsrPersistenceEnsureDiagnostics();
  920. if (target == PLSR_PERSISTENCE_DIAG_TARGET_HSD)
  921. {
  922. volatile PLSR_HSD_BACKUP_RECORD *slotA =
  923. PlsrPersistenceGetHsdSlot(0U);
  924. volatile PLSR_HSD_BACKUP_RECORD *slotB =
  925. PlsrPersistenceGetHsdSlot(1U);
  926. volatile PLSR_HSD_BACKUP_RECORD *newest;
  927. validA = PlsrPersistenceHsdRecordIsValid(slotA);
  928. validB = PlsrPersistenceHsdRecordIsValid(slotB);
  929. PlsrPersistenceUpdateHsdDiagnostics(slotA, slotB, validA, validB);
  930. if ((validA == 0U) || (validB == 0U))
  931. {
  932. return PLSR_PERSISTENCE_VERIFY_FAILED;
  933. }
  934. generationA = slotA->generation;
  935. generationB = slotB->generation;
  936. newest = (PlsrPersistenceGenerationIsNewer(generationB, generationA)
  937. != 0U)
  938. ? slotB
  939. : slotA;
  940. newest->magic = 0UL;
  941. #ifndef PLSR_HOST_TEST
  942. __DMB();
  943. #endif
  944. PlsrPersistenceUpdateHsdDiagnostics(
  945. slotA,
  946. slotB,
  947. (newest == slotA) ? 0U : 1U,
  948. (newest == slotB) ? 0U : 1U);
  949. return PLSR_PERSISTENCE_OK;
  950. }
  951. if (target == PLSR_PERSISTENCE_DIAG_TARGET_SFD)
  952. {
  953. volatile PLSR_SFD_FLASH_RECORD *slotA =
  954. PlsrPersistenceGetSfdSlot(0U);
  955. volatile PLSR_SFD_FLASH_RECORD *slotB =
  956. PlsrPersistenceGetSfdSlot(1U);
  957. volatile PLSR_SFD_FLASH_RECORD *newest;
  958. PLSR_PERSISTENCE_RESULT result;
  959. validA = PlsrPersistenceSfdRecordIsValid(slotA);
  960. validB = PlsrPersistenceSfdRecordIsValid(slotB);
  961. PlsrPersistenceUpdateSfdDiagnostics(slotA, slotB, validA, validB);
  962. if ((validA == 0U) || (validB == 0U))
  963. {
  964. return PLSR_PERSISTENCE_VERIFY_FAILED;
  965. }
  966. generationA = slotA->generation;
  967. generationB = slotB->generation;
  968. newest = (PlsrPersistenceGenerationIsNewer(generationB, generationA)
  969. != 0U)
  970. ? slotB
  971. : slotA;
  972. result = PlsrPersistenceBeginSfdOperation();
  973. if (result == PLSR_PERSISTENCE_OK)
  974. {
  975. result = PlsrPersistenceProgramSfdWord(
  976. (volatile uint32_t *)&newest->magic,
  977. 0UL);
  978. result = PlsrPersistenceEndSfdOperation(result);
  979. }
  980. PlsrPersistenceRefreshSfdDiagnostics();
  981. return result;
  982. }
  983. return PLSR_PERSISTENCE_INVALID_ARGUMENT;
  984. #else
  985. (void)target;
  986. return PLSR_PERSISTENCE_NOT_IMPLEMENTED;
  987. #endif
  988. }
  989. #ifdef PLSR_HOST_TEST
  990. void PlsrPersistenceTestResetStorage(void)
  991. {
  992. (void)memset(PlsrHostBackupSlots, 0, sizeof(PlsrHostBackupSlots));
  993. (void)memset(PlsrHostSfdSlots, 0xFF, sizeof(PlsrHostSfdSlots));
  994. PlsrHostSfdFault = PLSR_TEST_SFD_FAULT_NONE;
  995. PlsrHostHsdSaveCount = 0UL;
  996. PlsrPersistenceDiagnosticsInitialized = 0U;
  997. PlsrPersistenceEnsureDiagnostics();
  998. PlsrPersistenceUpdateHsdDiagnostics(
  999. PlsrPersistenceGetHsdSlot(0U),
  1000. PlsrPersistenceGetHsdSlot(1U),
  1001. 0U,
  1002. 0U);
  1003. PlsrPersistenceRefreshSfdDiagnostics();
  1004. }
  1005. uint32_t PlsrPersistenceTestGetHsdSaveCount(void)
  1006. {
  1007. return PlsrHostHsdSaveCount;
  1008. }
  1009. uint32_t PlsrPersistenceTestCrc32(const uint8_t *data, uint32_t length)
  1010. {
  1011. if ((data == NULL) && (length != 0UL))
  1012. {
  1013. return 0UL;
  1014. }
  1015. return PlsrPersistenceCrc32(data, length);
  1016. }
  1017. void PlsrPersistenceTestCorruptNewestHsd(void)
  1018. {
  1019. volatile PLSR_HSD_BACKUP_RECORD *slotA = PlsrPersistenceGetHsdSlot(0U);
  1020. volatile PLSR_HSD_BACKUP_RECORD *slotB = PlsrPersistenceGetHsdSlot(1U);
  1021. uint8_t validA = PlsrPersistenceHsdRecordIsValid(slotA);
  1022. uint8_t validB = PlsrPersistenceHsdRecordIsValid(slotB);
  1023. volatile PLSR_HSD_BACKUP_RECORD *newest;
  1024. if ((validA == 0U) && (validB == 0U))
  1025. {
  1026. return;
  1027. }
  1028. if ((validA != 0U) && (validB != 0U))
  1029. {
  1030. newest = (PlsrPersistenceGenerationIsNewer(slotB->generation,
  1031. slotA->generation)
  1032. != 0U)
  1033. ? slotB
  1034. : slotA;
  1035. }
  1036. else
  1037. {
  1038. newest = (validA != 0U) ? slotA : slotB;
  1039. }
  1040. newest->crc32 ^= 1UL;
  1041. }
  1042. void PlsrPersistenceTestCorruptNewestSfd(void)
  1043. {
  1044. volatile PLSR_SFD_FLASH_RECORD *slotA = PlsrPersistenceGetSfdSlot(0U);
  1045. volatile PLSR_SFD_FLASH_RECORD *slotB = PlsrPersistenceGetSfdSlot(1U);
  1046. uint8_t validA = PlsrPersistenceSfdRecordIsValid(slotA);
  1047. uint8_t validB = PlsrPersistenceSfdRecordIsValid(slotB);
  1048. volatile PLSR_SFD_FLASH_RECORD *newest;
  1049. if ((validA == 0U) && (validB == 0U))
  1050. {
  1051. return;
  1052. }
  1053. if ((validA != 0U) && (validB != 0U))
  1054. {
  1055. newest = (PlsrPersistenceGenerationIsNewer(slotB->generation,
  1056. slotA->generation)
  1057. != 0U)
  1058. ? slotB
  1059. : slotA;
  1060. }
  1061. else
  1062. {
  1063. newest = (validA != 0U) ? slotA : slotB;
  1064. }
  1065. newest->crc32 ^= 1UL;
  1066. }
  1067. void PlsrPersistenceTestSetSfdFault(PLSR_TEST_SFD_FAULT fault)
  1068. {
  1069. PlsrHostSfdFault = fault;
  1070. }
  1071. #endif