You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

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