eeprom_f4.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822
  1. /**
  2. ******************************************************************************
  3. * @file EEPROM/EEPROM_Emulation/src/eeprom.c
  4. * @author MCD Application Team
  5. * @brief This file provides all the EEPROM emulation firmware functions.
  6. ******************************************************************************
  7. * @attention
  8. *
  9. * <h2><center>&copy; Copyright � 2017 STMicroelectronics International N.V.
  10. * All rights reserved.</center></h2>
  11. *
  12. * Redistribution and use in source and binary forms, with or without
  13. * modification, are permitted, provided that the following conditions are met:
  14. *
  15. * 1. Redistribution of source code must retain the above copyright notice,
  16. * this list of conditions and the following disclaimer.
  17. * 2. Redistributions in binary form must reproduce the above copyright notice,
  18. * this list of conditions and the following disclaimer in the documentation
  19. * and/or other materials provided with the distribution.
  20. * 3. Neither the name of STMicroelectronics nor the names of other
  21. * contributors to this software may be used to endorse or promote products
  22. * derived from this software without specific written permission.
  23. * 4. This software, including modifications and/or derivative works of this
  24. * software, must execute solely and exclusively on microcontroller or
  25. * microprocessor devices manufactured by or for STMicroelectronics.
  26. * 5. Redistribution and use of this software other than as permitted under
  27. * this license is void and will automatically terminate your rights under
  28. * this license.
  29. *
  30. * THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS"
  31. * AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT
  32. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
  33. * PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY
  34. * RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT
  35. * SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  36. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  37. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
  38. * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  39. * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  40. * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
  41. * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  42. *
  43. ******************************************************************************
  44. */
  45. /** @addtogroup EEPROM_Emulation
  46. * @{
  47. */
  48. /* Includes ------------------------------------------------------------------*/
  49. #include "eeprom_f4.h"
  50. /* Private typedef -----------------------------------------------------------*/
  51. /* Private define ------------------------------------------------------------*/
  52. /* Private macro -------------------------------------------------------------*/
  53. /* Private variables ---------------------------------------------------------*/
  54. /* Global variable used to store variable value in read sequence */
  55. uint16_t DataVar = 0;
  56. /* Virtual address defined by the user: 0xFFFF value is prohibited */
  57. extern uint16_t VirtAddVarTab[NB_OF_VAR];
  58. /* Private function prototypes -----------------------------------------------*/
  59. /* Private functions ---------------------------------------------------------*/
  60. static HAL_StatusTypeDef EE_Format(void);
  61. static uint16_t EE_FindValidPage(uint8_t Operation);
  62. static uint16_t EE_VerifyPageFullWriteVariable(uint16_t VirtAddress, uint16_t Data);
  63. static uint16_t EE_PageTransfer(uint16_t VirtAddress, uint16_t Data);
  64. static uint16_t EE_VerifyPageFullyErased(uint32_t Address);
  65. /**
  66. * @brief Restore the pages to a known good state in case of page's status
  67. * corruption after a power loss.
  68. * @param None.
  69. * @retval - Flash error code: on write Flash error
  70. * - FLASH_COMPLETE: on success
  71. */
  72. uint16_t EE_Init(void)
  73. {
  74. uint16_t PageStatus0 = 6, PageStatus1 = 6;
  75. uint16_t VarIdx = 0;
  76. uint16_t EepromStatus = 0, ReadStatus = 0;
  77. int16_t x = -1;
  78. HAL_StatusTypeDef FlashStatus;
  79. FLASH_UnlockF4();
  80. /* Get Page0 status */
  81. PageStatus0 = (*(__IO uint16_t*)PAGE0_BASE_ADDRESS);
  82. /* Get Page1 status */
  83. PageStatus1 = (*(__IO uint16_t*)PAGE1_BASE_ADDRESS);
  84. /* Check for invalid header states and repair if necessary */
  85. switch (PageStatus0)
  86. {
  87. case ERASED:
  88. if (PageStatus1 == VALID_PAGE) /* Page0 erased, Page1 valid */
  89. {
  90. /* Erase Page0 */
  91. if(!EE_VerifyPageFullyErased(PAGE0_BASE_ADDRESS))
  92. {
  93. FlashStatus = FLASH_EraseSectorF4(PAGE0_ID);
  94. /* If erase operation was failed, a Flash error code is returned */
  95. if (FlashStatus != HAL_OK)
  96. {
  97. return FlashStatus;
  98. }
  99. }
  100. }
  101. else if (PageStatus1 == RECEIVE_DATA) /* Page0 erased, Page1 receive */
  102. {
  103. /* Erase Page0 */
  104. if(!EE_VerifyPageFullyErased(PAGE0_BASE_ADDRESS))
  105. {
  106. FlashStatus = FLASH_EraseSectorF4(PAGE1_ID);
  107. /* If erase operation was failed, a Flash error code is returned */
  108. if (FlashStatus != HAL_OK)
  109. {
  110. return FlashStatus;
  111. }
  112. }
  113. /* Mark Page1 as valid */
  114. FlashStatus = FLASH_ProgramHalfWordF4(PAGE1_BASE_ADDRESS, VALID_PAGE);
  115. /* If program operation was failed, a Flash error code is returned */
  116. if (FlashStatus != HAL_OK)
  117. {
  118. return FlashStatus;
  119. }
  120. }
  121. else /* First EEPROM access (Page0&1 are erased) or invalid state -> format EEPROM */
  122. {
  123. /* Erase both Page0 and Page1 and set Page0 as valid page */
  124. FlashStatus = EE_Format();
  125. /* If erase/program operation was failed, a Flash error code is returned */
  126. if (FlashStatus != HAL_OK)
  127. {
  128. return FlashStatus;
  129. }
  130. }
  131. break;
  132. case RECEIVE_DATA:
  133. if (PageStatus1 == VALID_PAGE) /* Page0 receive, Page1 valid */
  134. {
  135. /* Transfer data from Page1 to Page0 */
  136. for (VarIdx = 0; VarIdx < NB_OF_VAR; VarIdx++)
  137. {
  138. if (( *(__IO uint16_t*)(PAGE0_BASE_ADDRESS + 6)) == VirtAddVarTab[VarIdx])
  139. {
  140. x = VarIdx;
  141. }
  142. if (VarIdx != x)
  143. {
  144. /* Read the last variables' updates */
  145. ReadStatus = EE_ReadVariable(VirtAddVarTab[VarIdx], &DataVar);
  146. /* In case variable corresponding to the virtual address was found */
  147. if (ReadStatus != 0x1)
  148. {
  149. /* Transfer the variable to the Page0 */
  150. EepromStatus = EE_VerifyPageFullWriteVariable(VirtAddVarTab[VarIdx], DataVar);
  151. /* If program operation was failed, a Flash error code is returned */
  152. if (EepromStatus != HAL_OK)
  153. {
  154. return EepromStatus;
  155. }
  156. }
  157. }
  158. }
  159. /* Mark Page0 as valid */
  160. FlashStatus = FLASH_ProgramHalfWordF4(PAGE0_BASE_ADDRESS, VALID_PAGE);
  161. /* If program operation was failed, a Flash error code is returned */
  162. if (FlashStatus != HAL_OK)
  163. {
  164. return FlashStatus;
  165. }
  166. /* Erase Page1 */
  167. if(!EE_VerifyPageFullyErased(PAGE1_BASE_ADDRESS))
  168. {
  169. FlashStatus = FLASH_EraseSectorF4(PAGE1_ID);
  170. /* If erase operation was failed, a Flash error code is returned */
  171. if (FlashStatus != HAL_OK)
  172. {
  173. return FlashStatus;
  174. }
  175. }
  176. }
  177. else if (PageStatus1 == ERASED) /* Page0 receive, Page1 erased */
  178. {
  179. /* Erase Page1 */
  180. if(!EE_VerifyPageFullyErased(PAGE1_BASE_ADDRESS))
  181. {
  182. FlashStatus = FLASH_EraseSectorF4(PAGE1_ID);
  183. /* If erase operation was failed, a Flash error code is returned */
  184. if (FlashStatus != HAL_OK)
  185. {
  186. return FlashStatus;
  187. }
  188. }
  189. /* Mark Page0 as valid */
  190. FlashStatus = FLASH_ProgramHalfWordF4(PAGE0_BASE_ADDRESS, VALID_PAGE);
  191. /* If program operation was failed, a Flash error code is returned */
  192. if (FlashStatus != HAL_OK)
  193. {
  194. return FlashStatus;
  195. }
  196. }
  197. else /* Invalid state -> format eeprom */
  198. {
  199. /* Erase both Page0 and Page1 and set Page0 as valid page */
  200. FlashStatus = EE_Format();
  201. /* If erase/program operation was failed, a Flash error code is returned */
  202. if (FlashStatus != HAL_OK)
  203. {
  204. return FlashStatus;
  205. }
  206. }
  207. break;
  208. case VALID_PAGE:
  209. if (PageStatus1 == VALID_PAGE) /* Invalid state -> format eeprom */
  210. {
  211. /* Erase both Page0 and Page1 and set Page0 as valid page */
  212. FlashStatus = EE_Format();
  213. /* If erase/program operation was failed, a Flash error code is returned */
  214. if (FlashStatus != HAL_OK)
  215. {
  216. return FlashStatus;
  217. }
  218. }
  219. else if (PageStatus1 == ERASED) /* Page0 valid, Page1 erased */
  220. {
  221. /* Erase Page1 */
  222. if(!EE_VerifyPageFullyErased(PAGE1_BASE_ADDRESS))
  223. {
  224. FlashStatus = FLASH_EraseSectorF4(PAGE1_ID);
  225. /* If erase operation was failed, a Flash error code is returned */
  226. if (FlashStatus != HAL_OK)
  227. {
  228. return FlashStatus;
  229. }
  230. }
  231. }
  232. else /* Page0 valid, Page1 receive */
  233. {
  234. /* Transfer data from Page0 to Page1 */
  235. for (VarIdx = 0; VarIdx < NB_OF_VAR; VarIdx++)
  236. {
  237. if ((*(__IO uint16_t*)(PAGE1_BASE_ADDRESS + 6)) == VirtAddVarTab[VarIdx])
  238. {
  239. x = VarIdx;
  240. }
  241. if (VarIdx != x)
  242. {
  243. /* Read the last variables' updates */
  244. ReadStatus = EE_ReadVariable(VirtAddVarTab[VarIdx], &DataVar);
  245. /* In case variable corresponding to the virtual address was found */
  246. if (ReadStatus != 0x1)
  247. {
  248. /* Transfer the variable to the Page1 */
  249. EepromStatus = EE_VerifyPageFullWriteVariable(VirtAddVarTab[VarIdx], DataVar);
  250. /* If program operation was failed, a Flash error code is returned */
  251. if (EepromStatus != HAL_OK)
  252. {
  253. return EepromStatus;
  254. }
  255. }
  256. }
  257. }
  258. /* Mark Page1 as valid */
  259. FlashStatus = FLASH_ProgramHalfWordF4(PAGE1_BASE_ADDRESS, VALID_PAGE);
  260. /* If program operation was failed, a Flash error code is returned */
  261. if (FlashStatus != HAL_OK)
  262. {
  263. return FlashStatus;
  264. }
  265. /* Erase Page0 */
  266. if(!EE_VerifyPageFullyErased(PAGE0_BASE_ADDRESS))
  267. {
  268. FlashStatus = FLASH_EraseSectorF4(PAGE0_ID);
  269. /* If erase operation was failed, a Flash error code is returned */
  270. if (FlashStatus != HAL_OK)
  271. {
  272. return FlashStatus;
  273. }
  274. }
  275. }
  276. break;
  277. default: /* Any other state -> format eeprom */
  278. /* Erase both Page0 and Page1 and set Page0 as valid page */
  279. FlashStatus = EE_Format();
  280. /* If erase/program operation was failed, a Flash error code is returned */
  281. if (FlashStatus != HAL_OK)
  282. {
  283. return FlashStatus;
  284. }
  285. break;
  286. }
  287. return HAL_OK;
  288. }
  289. /**
  290. * @brief Verify if specified page is fully erased.
  291. * @param Address: page address
  292. * This parameter can be one of the following values:
  293. * @arg PAGE0_BASE_ADDRESS: Page0 base address
  294. * @arg PAGE1_BASE_ADDRESS: Page1 base address
  295. * @retval page fully erased status:
  296. * - 0: if Page not erased
  297. * - 1: if Page erased
  298. */
  299. uint16_t EE_VerifyPageFullyErased(uint32_t Address)
  300. {
  301. uint32_t ReadStatus = 1;
  302. uint16_t AddressValue = 0x5555;
  303. /* Check each active page address starting from end */
  304. while (Address <= PAGE0_END_ADDRESS)
  305. {
  306. /* Get the current location content to be compared with virtual address */
  307. AddressValue = (*(__IO uint16_t*)Address);
  308. /* Compare the read address with the virtual address */
  309. if (AddressValue != ERASED)
  310. {
  311. /* In case variable value is read, reset ReadStatus flag */
  312. ReadStatus = 0;
  313. break;
  314. }
  315. /* Next address location */
  316. Address = Address + 4;
  317. }
  318. /* Return ReadStatus value: (0: Page not erased, 1: Sector erased) */
  319. return ReadStatus;
  320. }
  321. /**
  322. * @brief Returns the last stored variable data, if found, which correspond to
  323. * the passed virtual address
  324. * @param VirtAddress: Variable virtual address
  325. * @param Data: Global variable contains the read variable value
  326. * @retval Success or error status:
  327. * - 0: if variable was found
  328. * - 1: if the variable was not found
  329. * - NO_VALID_PAGE: if no valid page was found.
  330. */
  331. uint16_t EE_ReadVariable(uint16_t VirtAddress, uint16_t* Data)
  332. {
  333. uint16_t ValidPage = PAGE0;
  334. uint16_t AddressValue = 0x5555, ReadStatus = 1;
  335. uint32_t Address = EEPROM_START_ADDRESS, PageStartAddress = EEPROM_START_ADDRESS;
  336. /* Get active Page for read operation */
  337. ValidPage = EE_FindValidPage(READ_FROM_VALID_PAGE);
  338. /* Check if there is no valid page */
  339. if (ValidPage == NO_VALID_PAGE)
  340. {
  341. return NO_VALID_PAGE;
  342. }
  343. /* Get the valid Page start Address */
  344. PageStartAddress = (uint32_t)(EEPROM_START_ADDRESS + (uint32_t)(ValidPage * PAGE_SIZE));
  345. /* Get the valid Page end Address */
  346. Address = (uint32_t)((EEPROM_START_ADDRESS - 2) + (uint32_t)((1 + ValidPage) * PAGE_SIZE));
  347. /* Check each active page address starting from end */
  348. while (Address > (PageStartAddress + 2))
  349. {
  350. /* Get the current location content to be compared with virtual address */
  351. AddressValue = (*(__IO uint16_t*)Address);
  352. /* Compare the read address with the virtual address */
  353. if (AddressValue == VirtAddress)
  354. {
  355. /* Get content of Address-2 which is variable value */
  356. *Data = (*(__IO uint16_t*)(Address - 2));
  357. /* In case variable value is read, reset ReadStatus flag */
  358. ReadStatus = 0;
  359. break;
  360. }
  361. else
  362. {
  363. /* Next address location */
  364. Address = Address - 4;
  365. }
  366. }
  367. /* Return ReadStatus value: (0: variable exist, 1: variable doesn't exist) */
  368. return ReadStatus;
  369. }
  370. /**
  371. * @brief Writes/upadtes variable data in EEPROM.
  372. * @param VirtAddress: Variable virtual address
  373. * @param Data: 16 bit data to be written
  374. * @retval Success or error status:
  375. * - FLASH_COMPLETE: on success
  376. * - PAGE_FULL: if valid page is full
  377. * - NO_VALID_PAGE: if no valid page was found
  378. * - Flash error code: on write Flash error
  379. */
  380. uint16_t EE_WriteVariable(uint16_t VirtAddress, uint16_t Data)
  381. {
  382. uint16_t Status = 0;
  383. /* Write the variable virtual address and value in the EEPROM */
  384. Status = EE_VerifyPageFullWriteVariable(VirtAddress, Data);
  385. /* In case the EEPROM active page is full */
  386. if (Status == PAGE_FULL)
  387. {
  388. /* Perform Page transfer */
  389. Status = EE_PageTransfer(VirtAddress, Data);
  390. }
  391. /* Return last operation status */
  392. return Status;
  393. }
  394. /**
  395. * @brief Erases PAGE and PAGE1 and writes VALID_PAGE header to PAGE
  396. * @param None
  397. * @retval Status of the last operation (Flash write or erase) done during
  398. * EEPROM formating
  399. */
  400. static HAL_StatusTypeDef EE_Format(void)
  401. {
  402. HAL_StatusTypeDef FlashStatus = HAL_OK;
  403. /* Erase Page0 */
  404. if(!EE_VerifyPageFullyErased(PAGE0_BASE_ADDRESS))
  405. {
  406. FlashStatus = FLASH_EraseSectorF4(PAGE0_ID);
  407. /* If erase operation was failed, a Flash error code is returned */
  408. if (FlashStatus != HAL_OK)
  409. {
  410. return FlashStatus;
  411. }
  412. }
  413. /* Set Page0 as valid page: Write VALID_PAGE at Page0 base address */
  414. FlashStatus = FLASH_ProgramHalfWordF4(PAGE0_BASE_ADDRESS, VALID_PAGE);
  415. /* If program operation was failed, a Flash error code is returned */
  416. if (FlashStatus != HAL_OK)
  417. {
  418. return FlashStatus;
  419. }
  420. /* Erase Page1 */
  421. if(!EE_VerifyPageFullyErased(PAGE1_BASE_ADDRESS))
  422. {
  423. FlashStatus = FLASH_EraseSectorF4(PAGE1_ID);
  424. /* If erase operation was failed, a Flash error code is returned */
  425. if (FlashStatus != HAL_OK)
  426. {
  427. return FlashStatus;
  428. }
  429. }
  430. return HAL_OK;
  431. }
  432. /**
  433. * @brief Find valid Page for write or read operation
  434. * @param Operation: operation to achieve on the valid page.
  435. * This parameter can be one of the following values:
  436. * @arg READ_FROM_VALID_PAGE: read operation from valid page
  437. * @arg WRITE_IN_VALID_PAGE: write operation from valid page
  438. * @retval Valid page number (PAGE or PAGE1) or NO_VALID_PAGE in case
  439. * of no valid page was found
  440. */
  441. static uint16_t EE_FindValidPage(uint8_t Operation)
  442. {
  443. uint16_t PageStatus0 = 6, PageStatus1 = 6;
  444. /* Get Page0 actual status */
  445. PageStatus0 = (*(__IO uint16_t*)PAGE0_BASE_ADDRESS);
  446. /* Get Page1 actual status */
  447. PageStatus1 = (*(__IO uint16_t*)PAGE1_BASE_ADDRESS);
  448. /* Write or read operation */
  449. switch (Operation)
  450. {
  451. case WRITE_IN_VALID_PAGE: /* ---- Write operation ---- */
  452. if (PageStatus1 == VALID_PAGE)
  453. {
  454. /* Page0 receiving data */
  455. if (PageStatus0 == RECEIVE_DATA)
  456. {
  457. return PAGE0; /* Page0 valid */
  458. }
  459. else
  460. {
  461. return PAGE1; /* Page1 valid */
  462. }
  463. }
  464. else if (PageStatus0 == VALID_PAGE)
  465. {
  466. /* Page1 receiving data */
  467. if (PageStatus1 == RECEIVE_DATA)
  468. {
  469. return PAGE1; /* Page1 valid */
  470. }
  471. else
  472. {
  473. return PAGE0; /* Page0 valid */
  474. }
  475. }
  476. else
  477. {
  478. return NO_VALID_PAGE; /* No valid Page */
  479. }
  480. case READ_FROM_VALID_PAGE: /* ---- Read operation ---- */
  481. if (PageStatus0 == VALID_PAGE)
  482. {
  483. return PAGE0; /* Page0 valid */
  484. }
  485. else if (PageStatus1 == VALID_PAGE)
  486. {
  487. return PAGE1; /* Page1 valid */
  488. }
  489. else
  490. {
  491. return NO_VALID_PAGE ; /* No valid Page */
  492. }
  493. default:
  494. return PAGE0; /* Page0 valid */
  495. }
  496. }
  497. /**
  498. * @brief Verify if active page is full and Writes variable in EEPROM.
  499. * @param VirtAddress: 16 bit virtual address of the variable
  500. * @param Data: 16 bit data to be written as variable value
  501. * @retval Success or error status:
  502. * - FLASH_COMPLETE: on success
  503. * - PAGE_FULL: if valid page is full
  504. * - NO_VALID_PAGE: if no valid page was found
  505. * - Flash error code: on write Flash error
  506. */
  507. static uint16_t EE_VerifyPageFullWriteVariable(uint16_t VirtAddress, uint16_t Data)
  508. {
  509. HAL_StatusTypeDef FlashStatus = HAL_OK;
  510. uint16_t ValidPage = PAGE0;
  511. uint32_t Address = EEPROM_START_ADDRESS, PageEndAddress = EEPROM_START_ADDRESS+PAGE_SIZE;
  512. /* Get valid Page for write operation */
  513. ValidPage = EE_FindValidPage(WRITE_IN_VALID_PAGE);
  514. /* Check if there is no valid page */
  515. if (ValidPage == NO_VALID_PAGE)
  516. {
  517. return NO_VALID_PAGE;
  518. }
  519. /* Get the valid Page start Address */
  520. Address = (uint32_t)(EEPROM_START_ADDRESS + (uint32_t)(ValidPage * PAGE_SIZE));
  521. /* Get the valid Page end Address */
  522. PageEndAddress = (uint32_t)((EEPROM_START_ADDRESS - 1) + (uint32_t)((ValidPage + 1) * PAGE_SIZE));
  523. /* Check each active page address starting from begining */
  524. while (Address < PageEndAddress)
  525. {
  526. /* Verify if Address and Address+2 contents are 0xFFFFFFFF */
  527. if ((*(__IO uint32_t*)Address) == 0xFFFFFFFF)
  528. {
  529. /* Set variable data */
  530. FlashStatus = FLASH_ProgramHalfWordF4(Address, Data);
  531. /* If program operation was failed, a Flash error code is returned */
  532. if (FlashStatus != HAL_OK)
  533. {
  534. return FlashStatus;
  535. }
  536. /* Set variable virtual address */
  537. FlashStatus = FLASH_ProgramHalfWordF4(Address + 2, VirtAddress);
  538. /* Return program operation status */
  539. return FlashStatus;
  540. }
  541. else
  542. {
  543. /* Next address location */
  544. Address = Address + 4;
  545. }
  546. }
  547. /* Return PAGE_FULL in case the valid page is full */
  548. return PAGE_FULL;
  549. }
  550. /**
  551. * @brief Transfers last updated variables data from the full Page to
  552. * an empty one.
  553. * @param VirtAddress: 16 bit virtual address of the variable
  554. * @param Data: 16 bit data to be written as variable value
  555. * @retval Success or error status:
  556. * - FLASH_COMPLETE: on success
  557. * - PAGE_FULL: if valid page is full
  558. * - NO_VALID_PAGE: if no valid page was found
  559. * - Flash error code: on write Flash error
  560. */
  561. static uint16_t EE_PageTransfer(uint16_t VirtAddress, uint16_t Data)
  562. {
  563. HAL_StatusTypeDef FlashStatus = HAL_OK;
  564. uint32_t NewPageAddress = EEPROM_START_ADDRESS;
  565. uint16_t OldPageId=0;
  566. uint16_t ValidPage = PAGE0, VarIdx = 0;
  567. uint16_t EepromStatus = 0, ReadStatus = 0;
  568. /* Get active Page for read operation */
  569. ValidPage = EE_FindValidPage(READ_FROM_VALID_PAGE);
  570. if (ValidPage == PAGE1) /* Page1 valid */
  571. {
  572. /* New page address where variable will be moved to */
  573. NewPageAddress = PAGE0_BASE_ADDRESS;
  574. /* Old page ID where variable will be taken from */
  575. OldPageId = PAGE1_ID;
  576. }
  577. else if (ValidPage == PAGE0) /* Page0 valid */
  578. {
  579. /* New page address where variable will be moved to */
  580. NewPageAddress = PAGE1_BASE_ADDRESS;
  581. /* Old page ID where variable will be taken from */
  582. OldPageId = PAGE0_ID;
  583. }
  584. else
  585. {
  586. return NO_VALID_PAGE; /* No valid Page */
  587. }
  588. /* Set the new Page status to RECEIVE_DATA status */
  589. FlashStatus = FLASH_ProgramHalfWordF4(NewPageAddress, RECEIVE_DATA);
  590. /* If program operation was failed, a Flash error code is returned */
  591. if (FlashStatus != HAL_OK)
  592. {
  593. return FlashStatus;
  594. }
  595. /* Write the variable passed as parameter in the new active page */
  596. EepromStatus = EE_VerifyPageFullWriteVariable(VirtAddress, Data);
  597. /* If program operation was failed, a Flash error code is returned */
  598. if (EepromStatus != HAL_OK)
  599. {
  600. return EepromStatus;
  601. }
  602. /* Transfer process: transfer variables from old to the new active page */
  603. for (VarIdx = 0; VarIdx < NB_OF_VAR; VarIdx++)
  604. {
  605. if (VirtAddVarTab[VarIdx] != VirtAddress) /* Check each variable except the one passed as parameter */
  606. {
  607. /* Read the other last variable updates */
  608. ReadStatus = EE_ReadVariable(VirtAddVarTab[VarIdx], &DataVar);
  609. /* In case variable corresponding to the virtual address was found */
  610. if (ReadStatus != 0x1)
  611. {
  612. /* Transfer the variable to the new active page */
  613. EepromStatus = EE_VerifyPageFullWriteVariable(VirtAddVarTab[VarIdx], DataVar);
  614. /* If program operation was failed, a Flash error code is returned */
  615. if (EepromStatus != HAL_OK)
  616. {
  617. return EepromStatus;
  618. }
  619. }
  620. }
  621. }
  622. /* Erase the old Page: Set old Page status to ERASED status */
  623. FlashStatus = FLASH_EraseSectorF4(OldPageId);
  624. /* If erase operation was failed, a Flash error code is returned */
  625. if (FlashStatus != HAL_OK)
  626. {
  627. return FlashStatus;
  628. }
  629. /* Set new Page status to VALID_PAGE status */
  630. FlashStatus = FLASH_ProgramHalfWordF4(NewPageAddress, VALID_PAGE);
  631. /* If program operation was failed, a Flash error code is returned */
  632. if (FlashStatus != HAL_OK)
  633. {
  634. return FlashStatus;
  635. }
  636. /* Return last operation flash status */
  637. return FlashStatus;
  638. }
  639. /* flash operation */
  640. #define EraseTimeout ((uint32_t)0x00000FFF)
  641. #define ProgramTimeout ((uint32_t)0x0000001F)
  642. #define FLASH_PSIZE_BYTE 0
  643. #define FLASH_PSIZE_HFWORD FLASH_CR_PSIZE_0
  644. #define FLASH_PSIZE_WORD FLASH_CR_PSIZE_1
  645. #define FLASH_CR_SNB_Pos 3
  646. #define FLASH_KEY1_F4 0x45670123
  647. #define FLASH_KEY2_F4 0xCDEF89AB
  648. #define ASSERT(exp) (void)((0))
  649. static void Flash_Delay(void)
  650. {
  651. __IO uint32_t i = 0;
  652. for(i = 0xFF; i != 0; i--) { }
  653. }
  654. static HAL_StatusTypeDef FLASH_GetStatus(void)
  655. {
  656. if ((FLASH->SR & FLASH_SR_BSY) == FLASH_SR_BSY)
  657. return HAL_BUSY;
  658. if ((FLASH->SR & (FLASH_SR_PGSERR|FLASH_SR_PGPERR|FLASH_SR_PGAERR)) != 0)
  659. return HAL_ERROR;
  660. if ((FLASH->SR & FLASH_SR_WRPERR) != 0 )
  661. return HAL_ERROR;
  662. if ((FLASH->SR & FLASH_SR_SOP) != 0 )
  663. return HAL_ERROR;
  664. return HAL_OK;
  665. }
  666. static HAL_StatusTypeDef FLASH_WaitForLastOperation(uint32_t timeout)
  667. {
  668. /* Check for the Flash Status */
  669. HAL_StatusTypeDef status = FLASH_GetStatus();
  670. /* Wait for a Flash operation to complete or a TIMEOUT to occur */
  671. while ((status == HAL_BUSY) && (timeout != 0x00))
  672. {
  673. Flash_Delay();
  674. status = FLASH_GetStatus();
  675. timeout--;
  676. }
  677. if (timeout == 0)
  678. status = HAL_TIMEOUT;
  679. return status;
  680. }
  681. HAL_StatusTypeDef FLASH_UnlockF4(void)
  682. {
  683. FLASH->KEYR = FLASH_KEY1_F4;
  684. FLASH->KEYR = FLASH_KEY2_F4;
  685. return HAL_OK;
  686. }
  687. HAL_StatusTypeDef FLASH_EraseSectorF4(uint32_t sector)
  688. {
  689. HAL_StatusTypeDef status = HAL_OK;
  690. /* Wait for last operation to be completed */
  691. status = FLASH_WaitForLastOperation(EraseTimeout);
  692. if(status == HAL_OK) {
  693. /* if the previous operation is completed, proceed to erase the page */
  694. CLEAR_BIT(FLASH->CR, FLASH_CR_PSIZE);
  695. FLASH->CR |= FLASH_PSIZE_WORD;
  696. CLEAR_BIT(FLASH->CR, FLASH_CR_SNB);
  697. FLASH->CR |= FLASH_CR_SER | (sector << FLASH_CR_SNB_Pos);
  698. FLASH->CR |= FLASH_CR_STRT;
  699. /* Wait for last operation to be completed */
  700. status = FLASH_WaitForLastOperation(EraseTimeout);
  701. if(status != HAL_TIMEOUT)
  702. {
  703. /* if the erase operation is completed, disable the PER Bit */
  704. FLASH->CR &= ~FLASH_CR_SNB;
  705. FLASH->CR &= ~FLASH_CR_SER;
  706. }
  707. FLASH->SR = (FLASH_SR_EOP | FLASH_SR_SOP | FLASH_SR_WRPERR);
  708. }
  709. /* Return the Erase Status */
  710. return status;
  711. }
  712. HAL_StatusTypeDef FLASH_ProgramHalfWordF4(uint32_t address, uint16_t data)
  713. {
  714. HAL_StatusTypeDef status = HAL_ERROR;
  715. if (IS_FLASH_ADDRESS(address))
  716. {
  717. /* Wait for last operation to be completed */
  718. status = FLASH_WaitForLastOperation(ProgramTimeout);
  719. if(status == HAL_OK) {
  720. // set size to byte
  721. FLASH->CR &= ~FLASH_CR_PSIZE;
  722. FLASH->CR |= FLASH_PSIZE_HFWORD;
  723. FLASH->CR |= FLASH_CR_PG;
  724. *(__IO uint16_t*)address = data;
  725. /* Wait for last operation to be completed */
  726. status = FLASH_WaitForLastOperation(ProgramTimeout);
  727. if(status != HAL_TIMEOUT)
  728. {
  729. /* if the program operation is completed, disable the PG Bit */
  730. FLASH->CR &= ~FLASH_CR_PG;
  731. }
  732. FLASH->SR = (FLASH_SR_EOP | FLASH_SR_SOP | FLASH_SR_PGSERR | FLASH_SR_PGPERR | FLASH_SR_PGAERR | FLASH_SR_WRPERR);
  733. }
  734. }
  735. return status;
  736. }
  737. /**
  738. * @}
  739. */
  740. /******************* (C) COPYRIGHT 2017 STMicroelectronics *****END OF FILE****/