My Marlin configs for Fabrikator Mini and CTC i3 Pro B
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.

eeprom_emul.cpp 22KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535
  1. /**
  2. ******************************************************************************
  3. * @file eeprom_emul.cpp
  4. * @author MCD Application Team
  5. * @version V1.2.6
  6. * @date 04-November-2016
  7. * @brief This file provides all the EEPROM emulation firmware functions.
  8. ******************************************************************************
  9. * @attention
  10. *
  11. * Copyright © 2016 STMicroelectronics International N.V.
  12. * All rights reserved.
  13. *
  14. * Redistribution and use in source and binary forms, with or without
  15. * modification, are permitted, provided that the following conditions are met:
  16. *
  17. * 1. Redistribution of source code must retain the above copyright notice,
  18. * this list of conditions and the following disclaimer.
  19. * 2. Redistributions in binary form must reproduce the above copyright notice,
  20. * this list of conditions and the following disclaimer in the documentation
  21. * and/or other materials provided with the distribution.
  22. * 3. Neither the name of STMicroelectronics nor the names of other
  23. * contributors to this software may be used to endorse or promote products
  24. * derived from this software without specific written permission.
  25. * 4. This software, including modifications and/or derivative works of this
  26. * software, must execute solely and exclusively on microcontroller or
  27. * microprocessor devices manufactured by or for STMicroelectronics.
  28. * 5. Redistribution and use of this software other than as permitted under
  29. * this license is void and will automatically terminate your rights under
  30. * this license.
  31. *
  32. * THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS"
  33. * AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT
  34. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
  35. * PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY
  36. * RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT
  37. * SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  38. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  39. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
  40. * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  41. * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  42. * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
  43. * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  44. *
  45. ******************************************************************************
  46. */
  47. /** @addtogroup EEPROM_Emulation
  48. * @{
  49. */
  50. #if defined(STM32GENERIC) && (defined(STM32F4) || defined(STM32F7))
  51. #include "../../inc/MarlinConfig.h"
  52. #if ENABLED(FLASH_EEPROM_EMULATION)
  53. /* Includes ------------------------------------------------------------------*/
  54. #include "eeprom_emul.h"
  55. /* Private variables ---------------------------------------------------------*/
  56. /* Global variable used to store variable value in read sequence */
  57. uint16_t DataVar = 0;
  58. /* Virtual address defined by the user: 0xFFFF value is prohibited */
  59. uint16_t VirtAddVarTab[NB_OF_VAR];
  60. /* Private function prototypes -----------------------------------------------*/
  61. static HAL_StatusTypeDef EE_Format();
  62. static uint16_t EE_FindValidPage(uint8_t Operation);
  63. static uint16_t EE_VerifyPageFullWriteVariable(uint16_t VirtAddress, uint16_t Data);
  64. static uint16_t EE_PageTransfer(uint16_t VirtAddress, uint16_t Data);
  65. static uint16_t EE_VerifyPageFullyErased(uint32_t Address);
  66. /**
  67. * @brief Restore the pages to a known good state in case of page's status
  68. * corruption after a power loss.
  69. * @param None.
  70. * @retval - Flash error code: on write Flash error
  71. * - FLASH_COMPLETE: on success
  72. */
  73. /* Private functions ---------------------------------------------------------*/
  74. uint16_t EE_Initialize() {
  75. /* Get Page0 and Page1 status */
  76. uint16_t PageStatus0 = (*(__IO uint16_t*)PAGE0_BASE_ADDRESS),
  77. PageStatus1 = (*(__IO uint16_t*)PAGE1_BASE_ADDRESS);
  78. FLASH_EraseInitTypeDef pEraseInit;
  79. pEraseInit.TypeErase = TYPEERASE_SECTORS;
  80. pEraseInit.Sector = PAGE0_ID;
  81. pEraseInit.NbSectors = 1;
  82. pEraseInit.VoltageRange = VOLTAGE_RANGE;
  83. HAL_StatusTypeDef FlashStatus; // = HAL_OK
  84. /* Check for invalid header states and repair if necessary */
  85. uint32_t SectorError;
  86. switch (PageStatus0) {
  87. case ERASED:
  88. if (PageStatus1 == VALID_PAGE) { /* Page0 erased, Page1 valid */
  89. /* Erase Page0 */
  90. if (!EE_VerifyPageFullyErased(PAGE0_BASE_ADDRESS)) {
  91. /* As the last operation, simply return the result */
  92. return HAL_FLASHEx_Erase(&pEraseInit, &SectorError);
  93. }
  94. }
  95. else if (PageStatus1 == RECEIVE_DATA) { /* Page0 erased, Page1 receive */
  96. /* Erase Page0 */
  97. if (!EE_VerifyPageFullyErased(PAGE0_BASE_ADDRESS)) {
  98. HAL_StatusTypeDef fStat = HAL_FLASHEx_Erase(&pEraseInit, &SectorError);
  99. /* If erase operation was failed, a Flash error code is returned */
  100. if (fStat != HAL_OK) return fStat;
  101. }
  102. /* Mark Page1 as valid */
  103. /* As the last operation, simply return the result */
  104. return HAL_FLASH_Program(TYPEPROGRAM_HALFWORD, PAGE1_BASE_ADDRESS, VALID_PAGE);
  105. }
  106. else { /* First EEPROM access (Page0&1 are erased) or invalid state -> format EEPROM */
  107. /* Erase both Page0 and Page1 and set Page0 as valid page */
  108. /* As the last operation, simply return the result */
  109. return EE_Format();
  110. }
  111. break;
  112. case RECEIVE_DATA:
  113. if (PageStatus1 == VALID_PAGE) { /* Page0 receive, Page1 valid */
  114. /* Transfer data from Page1 to Page0 */
  115. int16_t x = -1;
  116. for (uint16_t VarIdx = 0; VarIdx < NB_OF_VAR; VarIdx++) {
  117. if (( *(__IO uint16_t*)(PAGE0_BASE_ADDRESS + 6)) == VirtAddVarTab[VarIdx])
  118. x = VarIdx;
  119. if (VarIdx != x) {
  120. /* Read the last variables' updates */
  121. uint16_t ReadStatus = EE_ReadVariable(VirtAddVarTab[VarIdx], &DataVar);
  122. /* In case variable corresponding to the virtual address was found */
  123. if (ReadStatus != 0x1) {
  124. /* Transfer the variable to the Page0 */
  125. uint16_t EepromStatus = EE_VerifyPageFullWriteVariable(VirtAddVarTab[VarIdx], DataVar);
  126. /* If program operation was failed, a Flash error code is returned */
  127. if (EepromStatus != HAL_OK) return EepromStatus;
  128. }
  129. }
  130. }
  131. /* Mark Page0 as valid */
  132. FlashStatus = HAL_FLASH_Program(TYPEPROGRAM_HALFWORD, PAGE0_BASE_ADDRESS, VALID_PAGE);
  133. /* If program operation was failed, a Flash error code is returned */
  134. if (FlashStatus != HAL_OK) return FlashStatus;
  135. pEraseInit.Sector = PAGE1_ID;
  136. pEraseInit.NbSectors = 1;
  137. pEraseInit.VoltageRange = VOLTAGE_RANGE;
  138. /* Erase Page1 */
  139. if (!EE_VerifyPageFullyErased(PAGE1_BASE_ADDRESS)) {
  140. /* As the last operation, simply return the result */
  141. return HAL_FLASHEx_Erase(&pEraseInit, &SectorError);
  142. }
  143. }
  144. else if (PageStatus1 == ERASED) { /* Page0 receive, Page1 erased */
  145. pEraseInit.Sector = PAGE1_ID;
  146. pEraseInit.NbSectors = 1;
  147. pEraseInit.VoltageRange = VOLTAGE_RANGE;
  148. /* Erase Page1 */
  149. if (!EE_VerifyPageFullyErased(PAGE1_BASE_ADDRESS)) {
  150. HAL_StatusTypeDef fStat = HAL_FLASHEx_Erase(&pEraseInit, &SectorError);
  151. /* If erase operation was failed, a Flash error code is returned */
  152. if (fStat != HAL_OK) return fStat;
  153. }
  154. /* Mark Page0 as valid */
  155. /* As the last operation, simply return the result */
  156. return HAL_FLASH_Program(TYPEPROGRAM_HALFWORD, PAGE0_BASE_ADDRESS, VALID_PAGE);
  157. }
  158. else { /* Invalid state -> format eeprom */
  159. /* Erase both Page0 and Page1 and set Page0 as valid page */
  160. /* As the last operation, simply return the result */
  161. return EE_Format();
  162. }
  163. break;
  164. case VALID_PAGE:
  165. if (PageStatus1 == VALID_PAGE) { /* Invalid state -> format eeprom */
  166. /* Erase both Page0 and Page1 and set Page0 as valid page */
  167. FlashStatus = EE_Format();
  168. /* If erase/program operation was failed, a Flash error code is returned */
  169. if (FlashStatus != HAL_OK) return FlashStatus;
  170. }
  171. else if (PageStatus1 == ERASED) { /* Page0 valid, Page1 erased */
  172. pEraseInit.Sector = PAGE1_ID;
  173. pEraseInit.NbSectors = 1;
  174. pEraseInit.VoltageRange = VOLTAGE_RANGE;
  175. /* Erase Page1 */
  176. if (!EE_VerifyPageFullyErased(PAGE1_BASE_ADDRESS)) {
  177. FlashStatus = HAL_FLASHEx_Erase(&pEraseInit, &SectorError);
  178. /* If erase operation was failed, a Flash error code is returned */
  179. if (FlashStatus != HAL_OK) return FlashStatus;
  180. }
  181. }
  182. else { /* Page0 valid, Page1 receive */
  183. /* Transfer data from Page0 to Page1 */
  184. int16_t x = -1;
  185. for (uint16_t VarIdx = 0; VarIdx < NB_OF_VAR; VarIdx++) {
  186. if ((*(__IO uint16_t*)(PAGE1_BASE_ADDRESS + 6)) == VirtAddVarTab[VarIdx])
  187. x = VarIdx;
  188. if (VarIdx != x) {
  189. /* Read the last variables' updates */
  190. uint16_t ReadStatus = EE_ReadVariable(VirtAddVarTab[VarIdx], &DataVar);
  191. /* In case variable corresponding to the virtual address was found */
  192. if (ReadStatus != 0x1) {
  193. /* Transfer the variable to the Page1 */
  194. uint16_t EepromStatus = EE_VerifyPageFullWriteVariable(VirtAddVarTab[VarIdx], DataVar);
  195. /* If program operation was failed, a Flash error code is returned */
  196. if (EepromStatus != HAL_OK) return EepromStatus;
  197. }
  198. }
  199. }
  200. /* Mark Page1 as valid */
  201. FlashStatus = HAL_FLASH_Program(TYPEPROGRAM_HALFWORD, PAGE1_BASE_ADDRESS, VALID_PAGE);
  202. /* If program operation was failed, a Flash error code is returned */
  203. if (FlashStatus != HAL_OK) return FlashStatus;
  204. pEraseInit.Sector = PAGE0_ID;
  205. pEraseInit.NbSectors = 1;
  206. pEraseInit.VoltageRange = VOLTAGE_RANGE;
  207. /* Erase Page0 */
  208. if (!EE_VerifyPageFullyErased(PAGE0_BASE_ADDRESS)) {
  209. /* As the last operation, simply return the result */
  210. return HAL_FLASHEx_Erase(&pEraseInit, &SectorError);
  211. }
  212. }
  213. break;
  214. default: /* Any other state -> format eeprom */
  215. /* Erase both Page0 and Page1 and set Page0 as valid page */
  216. /* As the last operation, simply return the result */
  217. return EE_Format();
  218. }
  219. return HAL_OK;
  220. }
  221. /**
  222. * @brief Verify if specified page is fully erased.
  223. * @param Address: page address
  224. * This parameter can be one of the following values:
  225. * @arg PAGE0_BASE_ADDRESS: Page0 base address
  226. * @arg PAGE1_BASE_ADDRESS: Page1 base address
  227. * @retval page fully erased status:
  228. * - 0: if Page not erased
  229. * - 1: if Page erased
  230. */
  231. uint16_t EE_VerifyPageFullyErased(uint32_t Address) {
  232. uint32_t ReadStatus = 1;
  233. /* Check each active page address starting from end */
  234. while (Address <= PAGE0_END_ADDRESS) {
  235. /* Get the current location content to be compared with virtual address */
  236. uint16_t AddressValue = (*(__IO uint16_t*)Address);
  237. /* Compare the read address with the virtual address */
  238. if (AddressValue != ERASED) {
  239. /* In case variable value is read, reset ReadStatus flag */
  240. ReadStatus = 0;
  241. break;
  242. }
  243. /* Next address location */
  244. Address += 4;
  245. }
  246. /* Return ReadStatus value: (0: Page not erased, 1: Sector erased) */
  247. return ReadStatus;
  248. }
  249. /**
  250. * @brief Returns the last stored variable data, if found, which correspond to
  251. * the passed virtual address
  252. * @param VirtAddress: Variable virtual address
  253. * @param Data: Global variable contains the read variable value
  254. * @retval Success or error status:
  255. * - 0: if variable was found
  256. * - 1: if the variable was not found
  257. * - NO_VALID_PAGE: if no valid page was found.
  258. */
  259. uint16_t EE_ReadVariable(uint16_t VirtAddress, uint16_t* Data) {
  260. uint16_t ReadStatus = 1;
  261. /* Get active Page for read operation */
  262. uint16_t ValidPage = EE_FindValidPage(READ_FROM_VALID_PAGE);
  263. /* Check if there is no valid page */
  264. if (ValidPage == NO_VALID_PAGE) return NO_VALID_PAGE;
  265. /* Get the valid Page start and end Addresses */
  266. uint32_t PageStartAddress = uint32_t(EEPROM_START_ADDRESS) + uint32_t(ValidPage * (PAGE_SIZE)),
  267. Address = PageStartAddress + PAGE_SIZE - 2;
  268. /* Check each active page address starting from end */
  269. while (Address > PageStartAddress + 2) {
  270. /* Get the current location content to be compared with virtual address */
  271. uint16_t AddressValue = (*(__IO uint16_t*)Address);
  272. /* Compare the read address with the virtual address */
  273. if (AddressValue == VirtAddress) {
  274. /* Get content of Address-2 which is variable value */
  275. *Data = (*(__IO uint16_t*)(Address - 2));
  276. /* In case variable value is read, reset ReadStatus flag */
  277. ReadStatus = 0;
  278. break;
  279. }
  280. else /* Next address location */
  281. Address -= 4;
  282. }
  283. /* Return ReadStatus value: (0: variable exist, 1: variable doesn't exist) */
  284. return ReadStatus;
  285. }
  286. /**
  287. * @brief Writes/upadtes variable data in EEPROM.
  288. * @param VirtAddress: Variable virtual address
  289. * @param Data: 16 bit data to be written
  290. * @retval Success or error status:
  291. * - FLASH_COMPLETE: on success
  292. * - PAGE_FULL: if valid page is full
  293. * - NO_VALID_PAGE: if no valid page was found
  294. * - Flash error code: on write Flash error
  295. */
  296. uint16_t EE_WriteVariable(uint16_t VirtAddress, uint16_t Data) {
  297. /* Write the variable virtual address and value in the EEPROM */
  298. uint16_t Status = EE_VerifyPageFullWriteVariable(VirtAddress, Data);
  299. /* In case the EEPROM active page is full */
  300. if (Status == PAGE_FULL) /* Perform Page transfer */
  301. Status = EE_PageTransfer(VirtAddress, Data);
  302. /* Return last operation status */
  303. return Status;
  304. }
  305. /**
  306. * @brief Erases PAGE and PAGE1 and writes VALID_PAGE header to PAGE
  307. * @param None
  308. * @retval Status of the last operation (Flash write or erase) done during
  309. * EEPROM formatting
  310. */
  311. static HAL_StatusTypeDef EE_Format() {
  312. FLASH_EraseInitTypeDef pEraseInit;
  313. pEraseInit.TypeErase = FLASH_TYPEERASE_SECTORS;
  314. pEraseInit.Sector = PAGE0_ID;
  315. pEraseInit.NbSectors = 1;
  316. pEraseInit.VoltageRange = VOLTAGE_RANGE;
  317. HAL_StatusTypeDef FlashStatus; // = HAL_OK
  318. /* Erase Page0 */
  319. if (!EE_VerifyPageFullyErased(PAGE0_BASE_ADDRESS)) {
  320. uint32_t SectorError;
  321. FlashStatus = HAL_FLASHEx_Erase(&pEraseInit, &SectorError);
  322. /* If erase operation was failed, a Flash error code is returned */
  323. if (FlashStatus != HAL_OK) return FlashStatus;
  324. }
  325. /* Set Page0 as valid page: Write VALID_PAGE at Page0 base address */
  326. FlashStatus = HAL_FLASH_Program(TYPEPROGRAM_HALFWORD, PAGE0_BASE_ADDRESS, VALID_PAGE);
  327. /* If program operation was failed, a Flash error code is returned */
  328. if (FlashStatus != HAL_OK) return FlashStatus;
  329. pEraseInit.Sector = PAGE1_ID;
  330. /* Erase Page1 */
  331. if (!EE_VerifyPageFullyErased(PAGE1_BASE_ADDRESS)) {
  332. /* As the last operation, just return the result code */
  333. uint32_t SectorError;
  334. return HAL_FLASHEx_Erase(&pEraseInit, &SectorError);
  335. }
  336. return HAL_OK;
  337. }
  338. /**
  339. * @brief Find valid Page for write or read operation
  340. * @param Operation: operation to achieve on the valid page.
  341. * This parameter can be one of the following values:
  342. * @arg READ_FROM_VALID_PAGE: read operation from valid page
  343. * @arg WRITE_IN_VALID_PAGE: write operation from valid page
  344. * @retval Valid page number (PAGE or PAGE1) or NO_VALID_PAGE in case
  345. * of no valid page was found
  346. */
  347. static uint16_t EE_FindValidPage(uint8_t Operation) {
  348. /* Get Page0 and Page1 actual status */
  349. uint16_t PageStatus0 = (*(__IO uint16_t*)PAGE0_BASE_ADDRESS),
  350. PageStatus1 = (*(__IO uint16_t*)PAGE1_BASE_ADDRESS);
  351. /* Write or read operation */
  352. switch (Operation) {
  353. case WRITE_IN_VALID_PAGE: /* ---- Write operation ---- */
  354. if (PageStatus1 == VALID_PAGE) {
  355. /* Page0 receiving data */
  356. return (PageStatus0 == RECEIVE_DATA) ? PAGE0 : PAGE1;
  357. }
  358. else if (PageStatus0 == VALID_PAGE) {
  359. /* Page1 receiving data */
  360. return (PageStatus1 == RECEIVE_DATA) ? PAGE1 : PAGE0;
  361. }
  362. else
  363. return NO_VALID_PAGE; /* No valid Page */
  364. case READ_FROM_VALID_PAGE: /* ---- Read operation ---- */
  365. if (PageStatus0 == VALID_PAGE)
  366. return PAGE0; /* Page0 valid */
  367. else if (PageStatus1 == VALID_PAGE)
  368. return PAGE1; /* Page1 valid */
  369. else
  370. return NO_VALID_PAGE; /* No valid Page */
  371. default:
  372. return PAGE0; /* Page0 valid */
  373. }
  374. }
  375. /**
  376. * @brief Verify if active page is full and Writes variable in EEPROM.
  377. * @param VirtAddress: 16 bit virtual address of the variable
  378. * @param Data: 16 bit data to be written as variable value
  379. * @retval Success or error status:
  380. * - FLASH_COMPLETE: on success
  381. * - PAGE_FULL: if valid page is full
  382. * - NO_VALID_PAGE: if no valid page was found
  383. * - Flash error code: on write Flash error
  384. */
  385. static uint16_t EE_VerifyPageFullWriteVariable(uint16_t VirtAddress, uint16_t Data) {
  386. /* Get valid Page for write operation */
  387. uint16_t ValidPage = EE_FindValidPage(WRITE_IN_VALID_PAGE);
  388. /* Check if there is no valid page */
  389. if (ValidPage == NO_VALID_PAGE) return NO_VALID_PAGE;
  390. /* Get the valid Page start and end Addresses */
  391. uint32_t Address = uint32_t(EEPROM_START_ADDRESS) + uint32_t(ValidPage * (PAGE_SIZE)),
  392. PageEndAddress = Address + PAGE_SIZE - 1;
  393. /* Check each active page address starting from begining */
  394. while (Address < PageEndAddress) {
  395. /* Verify if Address and Address+2 contents are 0xFFFFFFFF */
  396. if ((*(__IO uint32_t*)Address) == 0xFFFFFFFF) {
  397. /* Set variable data */
  398. HAL_StatusTypeDef FlashStatus = HAL_FLASH_Program(TYPEPROGRAM_HALFWORD, Address, Data);
  399. /* If program operation was failed, a Flash error code is returned */
  400. if (FlashStatus != HAL_OK) return FlashStatus;
  401. /* Set variable virtual address, return status */
  402. return HAL_FLASH_Program(TYPEPROGRAM_HALFWORD, Address + 2, VirtAddress);
  403. }
  404. else /* Next address location */
  405. Address += 4;
  406. }
  407. /* Return PAGE_FULL in case the valid page is full */
  408. return PAGE_FULL;
  409. }
  410. /**
  411. * @brief Transfers last updated variables data from the full Page to
  412. * an empty one.
  413. * @param VirtAddress: 16 bit virtual address of the variable
  414. * @param Data: 16 bit data to be written as variable value
  415. * @retval Success or error status:
  416. * - FLASH_COMPLETE: on success
  417. * - PAGE_FULL: if valid page is full
  418. * - NO_VALID_PAGE: if no valid page was found
  419. * - Flash error code: on write Flash error
  420. */
  421. static uint16_t EE_PageTransfer(uint16_t VirtAddress, uint16_t Data) {
  422. /* Get active Page for read operation */
  423. uint16_t ValidPage = EE_FindValidPage(READ_FROM_VALID_PAGE);
  424. uint32_t NewPageAddress = EEPROM_START_ADDRESS;
  425. uint16_t OldPageId = 0;
  426. if (ValidPage == PAGE1) { /* Page1 valid */
  427. /* New page address where variable will be moved to */
  428. NewPageAddress = PAGE0_BASE_ADDRESS;
  429. /* Old page ID where variable will be taken from */
  430. OldPageId = PAGE1_ID;
  431. }
  432. else if (ValidPage == PAGE0) { /* Page0 valid */
  433. /* New page address where variable will be moved to */
  434. NewPageAddress = PAGE1_BASE_ADDRESS;
  435. /* Old page ID where variable will be taken from */
  436. OldPageId = PAGE0_ID;
  437. }
  438. else
  439. return NO_VALID_PAGE; /* No valid Page */
  440. /* Set the new Page status to RECEIVE_DATA status */
  441. HAL_StatusTypeDef FlashStatus = HAL_FLASH_Program(TYPEPROGRAM_HALFWORD, NewPageAddress, RECEIVE_DATA);
  442. /* If program operation was failed, a Flash error code is returned */
  443. if (FlashStatus != HAL_OK) return FlashStatus;
  444. /* Write the variable passed as parameter in the new active page */
  445. uint16_t EepromStatus = EE_VerifyPageFullWriteVariable(VirtAddress, Data);
  446. /* If program operation was failed, a Flash error code is returned */
  447. if (EepromStatus != HAL_OK) return EepromStatus;
  448. /* Transfer process: transfer variables from old to the new active page */
  449. for (uint16_t VarIdx = 0; VarIdx < NB_OF_VAR; VarIdx++) {
  450. if (VirtAddVarTab[VarIdx] != VirtAddress) { /* Check each variable except the one passed as parameter */
  451. /* Read the other last variable updates */
  452. uint16_t ReadStatus = EE_ReadVariable(VirtAddVarTab[VarIdx], &DataVar);
  453. /* In case variable corresponding to the virtual address was found */
  454. if (ReadStatus != 0x1) {
  455. /* Transfer the variable to the new active page */
  456. EepromStatus = EE_VerifyPageFullWriteVariable(VirtAddVarTab[VarIdx], DataVar);
  457. /* If program operation was failed, a Flash error code is returned */
  458. if (EepromStatus != HAL_OK) return EepromStatus;
  459. }
  460. }
  461. }
  462. FLASH_EraseInitTypeDef pEraseInit;
  463. pEraseInit.TypeErase = TYPEERASE_SECTORS;
  464. pEraseInit.Sector = OldPageId;
  465. pEraseInit.NbSectors = 1;
  466. pEraseInit.VoltageRange = VOLTAGE_RANGE;
  467. /* Erase the old Page: Set old Page status to ERASED status */
  468. uint32_t SectorError;
  469. FlashStatus = HAL_FLASHEx_Erase(&pEraseInit, &SectorError);
  470. /* If erase operation was failed, a Flash error code is returned */
  471. if (FlashStatus != HAL_OK) return FlashStatus;
  472. /* Set new Page status to VALID_PAGE status */
  473. /* As the last operation, just return the result code */
  474. return HAL_FLASH_Program(TYPEPROGRAM_HALFWORD, NewPageAddress, VALID_PAGE);
  475. }
  476. #endif // FLASH_EEPROM_EMULATION
  477. #endif // STM32GENERIC && (STM32F4 || STM32F7)
  478. /**
  479. * @}
  480. */
  481. /******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/