eeprom_stm32.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673
  1. /*
  2. * This software is experimental and a work in progress.
  3. * Under no circumstances should these files be used in relation to any critical system(s).
  4. * Use of these files is at your own risk.
  5. *
  6. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
  7. * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
  8. * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  9. * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  10. * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  11. * DEALINGS IN THE SOFTWARE.
  12. *
  13. * This files are free to use from https://github.com/rogerclarkmelbourne/Arduino_STM32 and
  14. * https://github.com/leaflabs/libmaple
  15. *
  16. * Modifications for QMK and STM32F303 by Yiancar
  17. */
  18. #include "eeprom_stm32.h"
  19. FLASH_Status EE_ErasePage(uint32_t);
  20. uint16_t EE_CheckPage(uint32_t, uint16_t);
  21. uint16_t EE_CheckErasePage(uint32_t, uint16_t);
  22. uint16_t EE_Format(void);
  23. uint32_t EE_FindValidPage(void);
  24. uint16_t EE_GetVariablesCount(uint32_t, uint16_t);
  25. uint16_t EE_PageTransfer(uint32_t, uint32_t, uint16_t);
  26. uint16_t EE_VerifyPageFullWriteVariable(uint16_t, uint16_t);
  27. uint32_t PageBase0 = EEPROM_PAGE0_BASE;
  28. uint32_t PageBase1 = EEPROM_PAGE1_BASE;
  29. uint32_t PageSize = EEPROM_PAGE_SIZE;
  30. uint16_t Status = EEPROM_NOT_INIT;
  31. // See http://www.st.com/web/en/resource/technical/document/application_note/CD00165693.pdf
  32. /**
  33. * @brief Check page for blank
  34. * @param page base address
  35. * @retval Success or error
  36. * EEPROM_BAD_FLASH: page not empty after erase
  37. * EEPROM_OK: page blank
  38. */
  39. uint16_t EE_CheckPage(uint32_t pageBase, uint16_t status)
  40. {
  41. uint32_t pageEnd = pageBase + (uint32_t)PageSize;
  42. // Page Status not EEPROM_ERASED and not a "state"
  43. if ((*(__IO uint16_t*)pageBase) != EEPROM_ERASED && (*(__IO uint16_t*)pageBase) != status)
  44. return EEPROM_BAD_FLASH;
  45. for(pageBase += 4; pageBase < pageEnd; pageBase += 4)
  46. if ((*(__IO uint32_t*)pageBase) != 0xFFFFFFFF) // Verify if slot is empty
  47. return EEPROM_BAD_FLASH;
  48. return EEPROM_OK;
  49. }
  50. /**
  51. * @brief Erase page with increment erase counter (page + 2)
  52. * @param page base address
  53. * @retval Success or error
  54. * FLASH_COMPLETE: success erase
  55. * - Flash error code: on write Flash error
  56. */
  57. FLASH_Status EE_ErasePage(uint32_t pageBase)
  58. {
  59. FLASH_Status FlashStatus;
  60. uint16_t data = (*(__IO uint16_t*)(pageBase));
  61. if ((data == EEPROM_ERASED) || (data == EEPROM_VALID_PAGE) || (data == EEPROM_RECEIVE_DATA))
  62. data = (*(__IO uint16_t*)(pageBase + 2)) + 1;
  63. else
  64. data = 0;
  65. FlashStatus = FLASH_ErasePage(pageBase);
  66. if (FlashStatus == FLASH_COMPLETE)
  67. FlashStatus = FLASH_ProgramHalfWord(pageBase + 2, data);
  68. return FlashStatus;
  69. }
  70. /**
  71. * @brief Check page for blank and erase it
  72. * @param page base address
  73. * @retval Success or error
  74. * - Flash error code: on write Flash error
  75. * - EEPROM_BAD_FLASH: page not empty after erase
  76. * - EEPROM_OK: page blank
  77. */
  78. uint16_t EE_CheckErasePage(uint32_t pageBase, uint16_t status)
  79. {
  80. uint16_t FlashStatus;
  81. if (EE_CheckPage(pageBase, status) != EEPROM_OK)
  82. {
  83. FlashStatus = EE_ErasePage(pageBase);
  84. if (FlashStatus != FLASH_COMPLETE)
  85. return FlashStatus;
  86. return EE_CheckPage(pageBase, status);
  87. }
  88. return EEPROM_OK;
  89. }
  90. /**
  91. * @brief Find valid Page for write or read operation
  92. * @param Page0: Page0 base address
  93. * Page1: Page1 base address
  94. * @retval Valid page address (PAGE0 or PAGE1) or NULL in case of no valid page was found
  95. */
  96. uint32_t EE_FindValidPage(void)
  97. {
  98. uint16_t status0 = (*(__IO uint16_t*)PageBase0); // Get Page0 actual status
  99. uint16_t status1 = (*(__IO uint16_t*)PageBase1); // Get Page1 actual status
  100. if (status0 == EEPROM_VALID_PAGE && status1 == EEPROM_ERASED)
  101. return PageBase0;
  102. if (status1 == EEPROM_VALID_PAGE && status0 == EEPROM_ERASED)
  103. return PageBase1;
  104. return 0;
  105. }
  106. /**
  107. * @brief Calculate unique variables in EEPROM
  108. * @param start: address of first slot to check (page + 4)
  109. * @param end: page end address
  110. * @param address: 16 bit virtual address of the variable to excluse (or 0XFFFF)
  111. * @retval count of variables
  112. */
  113. uint16_t EE_GetVariablesCount(uint32_t pageBase, uint16_t skipAddress)
  114. {
  115. uint16_t varAddress, nextAddress;
  116. uint32_t idx;
  117. uint32_t pageEnd = pageBase + (uint32_t)PageSize;
  118. uint16_t count = 0;
  119. for (pageBase += 6; pageBase < pageEnd; pageBase += 4)
  120. {
  121. varAddress = (*(__IO uint16_t*)pageBase);
  122. if (varAddress == 0xFFFF || varAddress == skipAddress)
  123. continue;
  124. count++;
  125. for(idx = pageBase + 4; idx < pageEnd; idx += 4)
  126. {
  127. nextAddress = (*(__IO uint16_t*)idx);
  128. if (nextAddress == varAddress)
  129. {
  130. count--;
  131. break;
  132. }
  133. }
  134. }
  135. return count;
  136. }
  137. /**
  138. * @brief Transfers last updated variables data from the full Page to an empty one.
  139. * @param newPage: new page base address
  140. * @param oldPage: old page base address
  141. * @param SkipAddress: 16 bit virtual address of the variable (or 0xFFFF)
  142. * @retval Success or error status:
  143. * - FLASH_COMPLETE: on success
  144. * - EEPROM_OUT_SIZE: if valid new page is full
  145. * - Flash error code: on write Flash error
  146. */
  147. uint16_t EE_PageTransfer(uint32_t newPage, uint32_t oldPage, uint16_t SkipAddress)
  148. {
  149. uint32_t oldEnd, newEnd;
  150. uint32_t oldIdx, newIdx, idx;
  151. uint16_t address, data, found;
  152. FLASH_Status FlashStatus;
  153. // Transfer process: transfer variables from old to the new active page
  154. newEnd = newPage + ((uint32_t)PageSize);
  155. // Find first free element in new page
  156. for (newIdx = newPage + 4; newIdx < newEnd; newIdx += 4)
  157. if ((*(__IO uint32_t*)newIdx) == 0xFFFFFFFF) // Verify if element
  158. break; // contents are 0xFFFFFFFF
  159. if (newIdx >= newEnd)
  160. return EEPROM_OUT_SIZE;
  161. oldEnd = oldPage + 4;
  162. oldIdx = oldPage + (uint32_t)(PageSize - 2);
  163. for (; oldIdx > oldEnd; oldIdx -= 4)
  164. {
  165. address = *(__IO uint16_t*)oldIdx;
  166. if (address == 0xFFFF || address == SkipAddress)
  167. continue; // it's means that power off after write data
  168. found = 0;
  169. for (idx = newPage + 6; idx < newIdx; idx += 4)
  170. if ((*(__IO uint16_t*)(idx)) == address)
  171. {
  172. found = 1;
  173. break;
  174. }
  175. if (found)
  176. continue;
  177. if (newIdx < newEnd)
  178. {
  179. data = (*(__IO uint16_t*)(oldIdx - 2));
  180. FlashStatus = FLASH_ProgramHalfWord(newIdx, data);
  181. if (FlashStatus != FLASH_COMPLETE)
  182. return FlashStatus;
  183. FlashStatus = FLASH_ProgramHalfWord(newIdx + 2, address);
  184. if (FlashStatus != FLASH_COMPLETE)
  185. return FlashStatus;
  186. newIdx += 4;
  187. }
  188. else
  189. return EEPROM_OUT_SIZE;
  190. }
  191. // Erase the old Page: Set old Page status to EEPROM_EEPROM_ERASED status
  192. data = EE_CheckErasePage(oldPage, EEPROM_ERASED);
  193. if (data != EEPROM_OK)
  194. return data;
  195. // Set new Page status
  196. FlashStatus = FLASH_ProgramHalfWord(newPage, EEPROM_VALID_PAGE);
  197. if (FlashStatus != FLASH_COMPLETE)
  198. return FlashStatus;
  199. return EEPROM_OK;
  200. }
  201. /**
  202. * @brief Verify if active page is full and Writes variable in EEPROM.
  203. * @param Address: 16 bit virtual address of the variable
  204. * @param Data: 16 bit data to be written as variable value
  205. * @retval Success or error status:
  206. * - FLASH_COMPLETE: on success
  207. * - EEPROM_PAGE_FULL: if valid page is full (need page transfer)
  208. * - EEPROM_NO_VALID_PAGE: if no valid page was found
  209. * - EEPROM_OUT_SIZE: if EEPROM size exceeded
  210. * - Flash error code: on write Flash error
  211. */
  212. uint16_t EE_VerifyPageFullWriteVariable(uint16_t Address, uint16_t Data)
  213. {
  214. FLASH_Status FlashStatus;
  215. uint32_t idx, pageBase, pageEnd, newPage;
  216. uint16_t count;
  217. // Get valid Page for write operation
  218. pageBase = EE_FindValidPage();
  219. if (pageBase == 0)
  220. return EEPROM_NO_VALID_PAGE;
  221. // Get the valid Page end Address
  222. pageEnd = pageBase + PageSize; // Set end of page
  223. for (idx = pageEnd - 2; idx > pageBase; idx -= 4)
  224. {
  225. if ((*(__IO uint16_t*)idx) == Address) // Find last value for address
  226. {
  227. count = (*(__IO uint16_t*)(idx - 2)); // Read last data
  228. if (count == Data)
  229. return EEPROM_OK;
  230. if (count == 0xFFFF)
  231. {
  232. FlashStatus = FLASH_ProgramHalfWord(idx - 2, Data); // Set variable data
  233. if (FlashStatus == FLASH_COMPLETE)
  234. return EEPROM_OK;
  235. }
  236. break;
  237. }
  238. }
  239. // Check each active page address starting from begining
  240. for (idx = pageBase + 4; idx < pageEnd; idx += 4)
  241. if ((*(__IO uint32_t*)idx) == 0xFFFFFFFF) // Verify if element
  242. { // contents are 0xFFFFFFFF
  243. FlashStatus = FLASH_ProgramHalfWord(idx, Data); // Set variable data
  244. if (FlashStatus != FLASH_COMPLETE)
  245. return FlashStatus;
  246. FlashStatus = FLASH_ProgramHalfWord(idx + 2, Address); // Set variable virtual address
  247. if (FlashStatus != FLASH_COMPLETE)
  248. return FlashStatus;
  249. return EEPROM_OK;
  250. }
  251. // Empty slot not found, need page transfer
  252. // Calculate unique variables in page
  253. count = EE_GetVariablesCount(pageBase, Address) + 1;
  254. if (count >= (PageSize / 4 - 1))
  255. return EEPROM_OUT_SIZE;
  256. if (pageBase == PageBase1)
  257. newPage = PageBase0; // New page address where variable will be moved to
  258. else
  259. newPage = PageBase1;
  260. // Set the new Page status to RECEIVE_DATA status
  261. FlashStatus = FLASH_ProgramHalfWord(newPage, EEPROM_RECEIVE_DATA);
  262. if (FlashStatus != FLASH_COMPLETE)
  263. return FlashStatus;
  264. // Write the variable passed as parameter in the new active page
  265. FlashStatus = FLASH_ProgramHalfWord(newPage + 4, Data);
  266. if (FlashStatus != FLASH_COMPLETE)
  267. return FlashStatus;
  268. FlashStatus = FLASH_ProgramHalfWord(newPage + 6, Address);
  269. if (FlashStatus != FLASH_COMPLETE)
  270. return FlashStatus;
  271. return EE_PageTransfer(newPage, pageBase, Address);
  272. }
  273. /*EEPROMClass::EEPROMClass(void)
  274. {
  275. PageBase0 = EEPROM_PAGE0_BASE;
  276. PageBase1 = EEPROM_PAGE1_BASE;
  277. PageSize = EEPROM_PAGE_SIZE;
  278. Status = EEPROM_NOT_INIT;
  279. }*/
  280. /*
  281. uint16_t EEPROM_init(uint32_t pageBase0, uint32_t pageBase1, uint32_t pageSize)
  282. {
  283. PageBase0 = pageBase0;
  284. PageBase1 = pageBase1;
  285. PageSize = pageSize;
  286. return EEPROM_init();
  287. }*/
  288. uint16_t EEPROM_init(void)
  289. {
  290. uint16_t status0 = 6, status1 = 6;
  291. FLASH_Status FlashStatus;
  292. FLASH_Unlock();
  293. Status = EEPROM_NO_VALID_PAGE;
  294. status0 = (*(__IO uint16_t *)PageBase0);
  295. status1 = (*(__IO uint16_t *)PageBase1);
  296. switch (status0)
  297. {
  298. /*
  299. Page0 Page1
  300. ----- -----
  301. EEPROM_ERASED EEPROM_VALID_PAGE Page1 valid, Page0 erased
  302. EEPROM_RECEIVE_DATA Page1 need set to valid, Page0 erased
  303. EEPROM_ERASED make EE_Format
  304. any Error: EEPROM_NO_VALID_PAGE
  305. */
  306. case EEPROM_ERASED:
  307. if (status1 == EEPROM_VALID_PAGE) // Page0 erased, Page1 valid
  308. Status = EE_CheckErasePage(PageBase0, EEPROM_ERASED);
  309. else if (status1 == EEPROM_RECEIVE_DATA) // Page0 erased, Page1 receive
  310. {
  311. FlashStatus = FLASH_ProgramHalfWord(PageBase1, EEPROM_VALID_PAGE);
  312. if (FlashStatus != FLASH_COMPLETE)
  313. Status = FlashStatus;
  314. else
  315. Status = EE_CheckErasePage(PageBase0, EEPROM_ERASED);
  316. }
  317. else if (status1 == EEPROM_ERASED) // Both in erased state so format EEPROM
  318. Status = EEPROM_format();
  319. break;
  320. /*
  321. Page0 Page1
  322. ----- -----
  323. EEPROM_RECEIVE_DATA EEPROM_VALID_PAGE Transfer Page1 to Page0
  324. EEPROM_ERASED Page0 need set to valid, Page1 erased
  325. any EEPROM_NO_VALID_PAGE
  326. */
  327. case EEPROM_RECEIVE_DATA:
  328. if (status1 == EEPROM_VALID_PAGE) // Page0 receive, Page1 valid
  329. Status = EE_PageTransfer(PageBase0, PageBase1, 0xFFFF);
  330. else if (status1 == EEPROM_ERASED) // Page0 receive, Page1 erased
  331. {
  332. Status = EE_CheckErasePage(PageBase1, EEPROM_ERASED);
  333. if (Status == EEPROM_OK)
  334. {
  335. FlashStatus = FLASH_ProgramHalfWord(PageBase0, EEPROM_VALID_PAGE);
  336. if (FlashStatus != FLASH_COMPLETE)
  337. Status = FlashStatus;
  338. else
  339. Status = EEPROM_OK;
  340. }
  341. }
  342. break;
  343. /*
  344. Page0 Page1
  345. ----- -----
  346. EEPROM_VALID_PAGE EEPROM_VALID_PAGE Error: EEPROM_NO_VALID_PAGE
  347. EEPROM_RECEIVE_DATA Transfer Page0 to Page1
  348. any Page0 valid, Page1 erased
  349. */
  350. case EEPROM_VALID_PAGE:
  351. if (status1 == EEPROM_VALID_PAGE) // Both pages valid
  352. Status = EEPROM_NO_VALID_PAGE;
  353. else if (status1 == EEPROM_RECEIVE_DATA)
  354. Status = EE_PageTransfer(PageBase1, PageBase0, 0xFFFF);
  355. else
  356. Status = EE_CheckErasePage(PageBase1, EEPROM_ERASED);
  357. break;
  358. /*
  359. Page0 Page1
  360. ----- -----
  361. any EEPROM_VALID_PAGE Page1 valid, Page0 erased
  362. EEPROM_RECEIVE_DATA Page1 valid, Page0 erased
  363. any EEPROM_NO_VALID_PAGE
  364. */
  365. default:
  366. if (status1 == EEPROM_VALID_PAGE)
  367. Status = EE_CheckErasePage(PageBase0, EEPROM_ERASED); // Check/Erase Page0
  368. else if (status1 == EEPROM_RECEIVE_DATA)
  369. {
  370. FlashStatus = FLASH_ProgramHalfWord(PageBase1, EEPROM_VALID_PAGE);
  371. if (FlashStatus != FLASH_COMPLETE)
  372. Status = FlashStatus;
  373. else
  374. Status = EE_CheckErasePage(PageBase0, EEPROM_ERASED);
  375. }
  376. break;
  377. }
  378. return Status;
  379. }
  380. /**
  381. * @brief Erases PAGE0 and PAGE1 and writes EEPROM_VALID_PAGE / 0 header to PAGE0
  382. * @param PAGE0 and PAGE1 base addresses
  383. * @retval Status of the last operation (Flash write or erase) done during EEPROM formating
  384. */
  385. uint16_t EEPROM_format(void)
  386. {
  387. uint16_t status;
  388. FLASH_Status FlashStatus;
  389. FLASH_Unlock();
  390. // Erase Page0
  391. status = EE_CheckErasePage(PageBase0, EEPROM_VALID_PAGE);
  392. if (status != EEPROM_OK)
  393. return status;
  394. if ((*(__IO uint16_t*)PageBase0) == EEPROM_ERASED)
  395. {
  396. // Set Page0 as valid page: Write VALID_PAGE at Page0 base address
  397. FlashStatus = FLASH_ProgramHalfWord(PageBase0, EEPROM_VALID_PAGE);
  398. if (FlashStatus != FLASH_COMPLETE)
  399. return FlashStatus;
  400. }
  401. // Erase Page1
  402. return EE_CheckErasePage(PageBase1, EEPROM_ERASED);
  403. }
  404. /**
  405. * @brief Returns the erase counter for current page
  406. * @param Data: Global variable contains the read variable value
  407. * @retval Success or error status:
  408. * - EEPROM_OK: if erases counter return.
  409. * - EEPROM_NO_VALID_PAGE: if no valid page was found.
  410. */
  411. uint16_t EEPROM_erases(uint16_t *Erases)
  412. {
  413. uint32_t pageBase;
  414. if (Status != EEPROM_OK)
  415. if (EEPROM_init() != EEPROM_OK)
  416. return Status;
  417. // Get active Page for read operation
  418. pageBase = EE_FindValidPage();
  419. if (pageBase == 0)
  420. return EEPROM_NO_VALID_PAGE;
  421. *Erases = (*(__IO uint16_t*)pageBase+2);
  422. return EEPROM_OK;
  423. }
  424. /**
  425. * @brief Returns the last stored variable data, if found,
  426. * which correspond to the passed virtual address
  427. * @param Address: Variable virtual address
  428. * @retval Data for variable or EEPROM_DEFAULT_DATA, if any errors
  429. */
  430. /*
  431. uint16_t EEPROM_read (uint16_t Address)
  432. {
  433. uint16_t data;
  434. EEPROM_read(Address, &data);
  435. return data;
  436. }*/
  437. /**
  438. * @brief Returns the last stored variable data, if found,
  439. * which correspond to the passed virtual address
  440. * @param Address: Variable virtual address
  441. * @param Data: Pointer to data variable
  442. * @retval Success or error status:
  443. * - EEPROM_OK: if variable was found
  444. * - EEPROM_BAD_ADDRESS: if the variable was not found
  445. * - EEPROM_NO_VALID_PAGE: if no valid page was found.
  446. */
  447. uint16_t EEPROM_read(uint16_t Address, uint16_t *Data)
  448. {
  449. uint32_t pageBase, pageEnd;
  450. // Set default data (empty EEPROM)
  451. *Data = EEPROM_DEFAULT_DATA;
  452. if (Status == EEPROM_NOT_INIT)
  453. if (EEPROM_init() != EEPROM_OK)
  454. return Status;
  455. // Get active Page for read operation
  456. pageBase = EE_FindValidPage();
  457. if (pageBase == 0)
  458. return EEPROM_NO_VALID_PAGE;
  459. // Get the valid Page end Address
  460. pageEnd = pageBase + ((uint32_t)(PageSize - 2));
  461. // Check each active page address starting from end
  462. for (pageBase += 6; pageEnd >= pageBase; pageEnd -= 4)
  463. if ((*(__IO uint16_t*)pageEnd) == Address) // Compare the read address with the virtual address
  464. {
  465. *Data = (*(__IO uint16_t*)(pageEnd - 2)); // Get content of Address-2 which is variable value
  466. return EEPROM_OK;
  467. }
  468. // Return ReadStatus value: (0: variable exist, 1: variable doesn't exist)
  469. return EEPROM_BAD_ADDRESS;
  470. }
  471. /**
  472. * @brief Writes/upadtes variable data in EEPROM.
  473. * @param VirtAddress: Variable virtual address
  474. * @param Data: 16 bit data to be written
  475. * @retval Success or error status:
  476. * - FLASH_COMPLETE: on success
  477. * - EEPROM_BAD_ADDRESS: if address = 0xFFFF
  478. * - EEPROM_PAGE_FULL: if valid page is full
  479. * - EEPROM_NO_VALID_PAGE: if no valid page was found
  480. * - EEPROM_OUT_SIZE: if no empty EEPROM variables
  481. * - Flash error code: on write Flash error
  482. */
  483. uint16_t EEPROM_write(uint16_t Address, uint16_t Data)
  484. {
  485. if (Status == EEPROM_NOT_INIT)
  486. if (EEPROM_init() != EEPROM_OK)
  487. return Status;
  488. if (Address == 0xFFFF)
  489. return EEPROM_BAD_ADDRESS;
  490. // Write the variable virtual address and value in the EEPROM
  491. uint16_t status = EE_VerifyPageFullWriteVariable(Address, Data);
  492. return status;
  493. }
  494. /**
  495. * @brief Writes/upadtes variable data in EEPROM.
  496. The value is written only if differs from the one already saved at the same address.
  497. * @param VirtAddress: Variable virtual address
  498. * @param Data: 16 bit data to be written
  499. * @retval Success or error status:
  500. * - EEPROM_SAME_VALUE: If new Data matches existing EEPROM Data
  501. * - FLASH_COMPLETE: on success
  502. * - EEPROM_BAD_ADDRESS: if address = 0xFFFF
  503. * - EEPROM_PAGE_FULL: if valid page is full
  504. * - EEPROM_NO_VALID_PAGE: if no valid page was found
  505. * - EEPROM_OUT_SIZE: if no empty EEPROM variables
  506. * - Flash error code: on write Flash error
  507. */
  508. uint16_t EEPROM_update(uint16_t Address, uint16_t Data)
  509. {
  510. uint16_t temp;
  511. EEPROM_read(Address, &temp);
  512. if (temp == Data)
  513. return EEPROM_SAME_VALUE;
  514. else
  515. return EEPROM_write(Address, Data);
  516. }
  517. /**
  518. * @brief Return number of variable
  519. * @retval Number of variables
  520. */
  521. uint16_t EEPROM_count(uint16_t *Count)
  522. {
  523. if (Status == EEPROM_NOT_INIT)
  524. if (EEPROM_init() != EEPROM_OK)
  525. return Status;
  526. // Get valid Page for write operation
  527. uint32_t pageBase = EE_FindValidPage();
  528. if (pageBase == 0)
  529. return EEPROM_NO_VALID_PAGE; // No valid page, return max. numbers
  530. *Count = EE_GetVariablesCount(pageBase, 0xFFFF);
  531. return EEPROM_OK;
  532. }
  533. uint16_t EEPROM_maxcount(void)
  534. {
  535. return ((PageSize / 4)-1);
  536. }
  537. uint8_t eeprom_read_byte (const uint8_t *Address)
  538. {
  539. const uint16_t p = (const uint32_t) Address;
  540. uint16_t temp;
  541. EEPROM_read(p, &temp);
  542. return (uint8_t) temp;
  543. }
  544. void eeprom_write_byte (uint8_t *Address, uint8_t Value)
  545. {
  546. uint16_t p = (uint32_t) Address;
  547. EEPROM_write(p, (uint16_t) Value);
  548. }
  549. void eeprom_update_byte (uint8_t *Address, uint8_t Value)
  550. {
  551. uint16_t p = (uint32_t) Address;
  552. EEPROM_update(p, (uint16_t) Value);
  553. }
  554. uint16_t eeprom_read_word (const uint16_t *Address)
  555. {
  556. const uint16_t p = (const uint32_t) Address;
  557. uint16_t temp;
  558. EEPROM_read(p, &temp);
  559. return temp;
  560. }
  561. void eeprom_write_word (uint16_t *Address, uint16_t Value)
  562. {
  563. uint16_t p = (uint32_t) Address;
  564. EEPROM_write(p, Value);
  565. }
  566. void eeprom_update_word (uint16_t *Address, uint16_t Value)
  567. {
  568. uint16_t p = (uint32_t) Address;
  569. EEPROM_update(p, Value);
  570. }
  571. uint32_t eeprom_read_dword (const uint32_t *Address)
  572. {
  573. const uint16_t p = (const uint32_t) Address;
  574. uint16_t temp1, temp2;
  575. EEPROM_read(p, &temp1);
  576. EEPROM_read(p + 1, &temp2);
  577. return temp1 | (temp2 << 16);
  578. }
  579. void eeprom_write_dword (uint32_t *Address, uint32_t Value)
  580. {
  581. uint16_t temp = (uint16_t) Value;
  582. uint16_t p = (uint32_t) Address;
  583. EEPROM_write(p, temp);
  584. temp = (uint16_t) (Value >> 16);
  585. EEPROM_write(p + 1, temp);
  586. }
  587. void eeprom_update_dword (uint32_t *Address, uint32_t Value)
  588. {
  589. uint16_t temp = (uint16_t) Value;
  590. uint16_t p = (uint32_t) Address;
  591. EEPROM_update(p, temp);
  592. temp = (uint16_t) (Value >> 16);
  593. EEPROM_update(p + 1, temp);
  594. }