当前位置:   article > 正文

FLASH模拟EEPROM的方法_eeprom有page0吗

eeprom有page0吗

工业中经常使用EEPROM(电可擦除可编程存储器)来存储更新数据,为降低成本,可以使用FLASH代替。

 EEPROM 仿真可以通过多种方式实现,但要注意 Flash 限制和产品要求。下面详述的方法要求为非易失性数据分配至少两个相同大小的 Flash 扇区:一个在开始时擦除,支持逐字编程;另一个在需要对前一扇区执行垃圾回收时接管工作。占用每扇区前半个字(16 位)的头字段指示扇区的状态。在本文档的其余部分,将每一个扇区视为一页,这些页分别称为Page0 和 Page1。

0x08000001(0xFFFF|0xFFFF)
虚拟地址11
虚拟地址22
虚拟地址33
虚拟地址44

 写入数据

0x000x040x080x0C········0x3FF00x3FF40x3FF80x3FFC
16位地址16位数据16位地址16位数据16位地址16位数据          16位地址16位数据

 flash默认擦除状态,0xFFFF,从头向后检查,检查到数据地址位0xFFFF,即填入地址并写入数据。

写满后,将该Page的有效数据,都刷新到新的Page,并写入该新的数据。

读数据

从后向前对比,当查询地址与flash中地址一致,取出该值,跳出循环。

  1. /**
  2. ******************************************************************************
  3. * @file EEPROM/EEPROM_Emulation/inc/eeprom.h
  4. * @author MCD Application Team
  5. * @version V1.3.2
  6. * @date 13-November-2015
  7. * @brief This file contains all the functions prototypes for the EEPROM
  8. * emulation firmware library.
  9. ******************************************************************************
  10. * @attention
  11. *
  12. * <h2><center>&copy; COPYRIGHT(c) 2015 STMicroelectronics</center></h2>
  13. *
  14. * Redistribution and use in source and binary forms, with or without modification,
  15. * are permitted provided that the following conditions are met:
  16. * 1. Redistributions of source code must retain the above copyright notice,
  17. * this list of conditions and the following disclaimer.
  18. * 2. Redistributions in binary form must reproduce the above copyright notice,
  19. * this list of conditions and the following disclaimer in the documentation
  20. * and/or other materials provided with the distribution.
  21. * 3. Neither the name of STMicroelectronics nor the names of its contributors
  22. * may be used to endorse or promote products derived from this software
  23. * without specific prior written permission.
  24. *
  25. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  26. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  27. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  28. * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
  29. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  30. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  31. * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  32. * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  33. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  34. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  35. *
  36. ******************************************************************************
  37. */
  38. //
  39. /***********************************************************************************
  40. * Copyright (C),2008-2020,Terry Tech.Co.,Ltd
  41. * File name: feeprom.h
  42. * Author: Terry Version: 1.0
  43. * Description: stm32F103 一页1K, 待存储的数据 < 256 个 uint6_t 个数据,
  44. * 不增大Page的情况下(2 page情况下),参数数量原则越少越好
  45. * 建议参数20个以内,这样使用寿命约为 10 X 10000 即10万次
  46. * Others:
  47. * Function List:
  48. *
  49. */
  50. /* Define to prevent recursive inclusion -------------------------------------*/
  51. #ifndef __EEPROM_H
  52. #define __EEPROM_H
  53. /* Includes ------------------------------------------------------------------*/
  54. #include "stm32f1xx_hal.h"
  55. /* Exported constants --------------------------------------------------------*/
  56. /* EEPROM emulation firmware error codes */
  57. #define EE_OK (uint32_t)HAL_OK
  58. #define EE_ERROR (uint32_t)HAL_ERROR
  59. #define EE_BUSY (uint32_t)HAL_BUSY
  60. #define EE_TIMEOUT (uint32_t)HAL_TIMEOUT
  61. /* Define the size of the sectors to be used */
  62. #define PAGE_SIZE (uint32_t)0x400 /* Page size = 1KByte */
  63. /* Device voltage range supposed to be [2.7V to 3.6V], the operation will
  64. be done by word */
  65. //#define VOLTAGE_RANGE (uint8_t)VOLTAGE_RANGE_3
  66. /* EEPROM start address in Flash */
  67. #define EEPROM_START_ADDRESS ((uint32_t)0x08018000) /* EEPROM emulation start address:
  68. from sector2 : after 1KByte of used
  69. Flash memory */
  70. /* Pages 0 and 1 base and end addresses */
  71. #define PAGE0_BASE_ADDRESS ((uint32_t)(EEPROM_START_ADDRESS + 0x000))
  72. #define PAGE0_END_ADDRESS ((uint32_t)(EEPROM_START_ADDRESS + (PAGE_SIZE - 1)))
  73. //#define PAGE0_ID FLASH_SECTOR_2
  74. #define PAGE1_BASE_ADDRESS ((uint32_t)(EEPROM_START_ADDRESS + PAGE_SIZE))
  75. #define PAGE1_END_ADDRESS ((uint32_t)(EEPROM_START_ADDRESS + (2 * PAGE_SIZE - 1)))
  76. //#define PAGE1_ID FLASH_SECTOR_3
  77. // 更多页的负载均衡使用方法,此处略过 Terry 2020.03.01
  78. //
  79. //
  80. /* Used Flash pages for EEPROM emulation */
  81. #define PAGE0 ((uint16_t)0x0000)
  82. #define PAGE1 ((uint16_t)0x0001) /* Page nb between PAGE0_BASE_ADDRESS & PAGE1_BASE_ADDRESS*/
  83. /* No valid page define */
  84. #define NO_VALID_PAGE ((uint16_t)0x00AB)
  85. /* Page status definitions */
  86. #define ERASED ((uint16_t)0xFFFF) /* Page is empty */
  87. #define RECEIVE_DATA ((uint16_t)0xEEEE) /* Page is marked to receive data */
  88. #define VALID_PAGE ((uint16_t)0x0000) /* Page containing valid data */
  89. /* Valid pages in read and write defines */
  90. #define READ_FROM_VALID_PAGE ((uint8_t)0x00)
  91. #define WRITE_IN_VALID_PAGE ((uint8_t)0x01)
  92. /* Page full define */
  93. #define PAGE_FULL ((uint8_t)0x80)
  94. /* Variables' number */
  95. #define NB_OF_VAR ((uint8_t)0x03)
  96. /* Exported types ------------------------------------------------------------*/
  97. #define EE_UNLOCK() HAL_FLASH_Unlock()
  98. #define EE_LOCK() HAL_FLASH_Lock()
  99. /* Exported macro ------------------------------------------------------------*/
  100. /* Exported functions ------------------------------------------------------- */
  101. uint16_t EE_Init(void);
  102. uint16_t EE_ReadVariable(uint16_t VirtAddress, uint16_t* Data);
  103. uint16_t EE_WriteVariable(uint16_t VirtAddress, uint16_t Data);
  104. #endif /* __EEPROM_H */
  105. /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

 

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

 stm32 flash 每个扇区的读写次数大约1万次,当存储数据较多时,可以增加每组Flash 页的数量,实现损耗均衡,增加Flash可擦写次数。

 

本文内容由网友自发贡献,转载请注明出处:https://www.wpsshop.cn/w/小小林熬夜学编程/article/detail/676306
推荐阅读
相关标签
  

闽ICP备14008679号