eeprom_stm32.c 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  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 http://engsta.com/stm32-flash-memory-eeprom-emulator/ by
  14. * Artur F.
  15. *
  16. * Modifications for QMK and STM32F303 by Yiancar
  17. */
  18. #include <stdio.h>
  19. #include <string.h>
  20. #include "eeprom_stm32.h"
  21. /*****************************************************************************
  22. * Allows to use the internal flash to store non volatile data. To initialize
  23. * the functionality use the EEPROM_Init() function. Be sure that by reprogramming
  24. * of the controller just affected pages will be deleted. In other case the non
  25. * volatile data will be lost.
  26. ******************************************************************************/
  27. /* Private macro -------------------------------------------------------------*/
  28. /* Private variables ---------------------------------------------------------*/
  29. /* Functions -----------------------------------------------------------------*/
  30. uint8_t DataBuf[FEE_PAGE_SIZE];
  31. /*****************************************************************************
  32. * Delete Flash Space used for user Data, deletes the whole space between
  33. * RW_PAGE_BASE_ADDRESS and the last uC Flash Page
  34. ******************************************************************************/
  35. uint16_t EEPROM_Init(void) {
  36. // unlock flash
  37. FLASH_Unlock();
  38. // Clear Flags
  39. //FLASH_ClearFlag(FLASH_SR_EOP|FLASH_SR_PGERR|FLASH_SR_WRPERR);
  40. return FEE_DENSITY_BYTES;
  41. }
  42. /*****************************************************************************
  43. * Erase the whole reserved Flash Space used for user Data
  44. ******************************************************************************/
  45. void EEPROM_Erase (void) {
  46. int page_num = 0;
  47. // delete all pages from specified start page to the last page
  48. do {
  49. FLASH_ErasePage(FEE_PAGE_BASE_ADDRESS + (page_num * FEE_PAGE_SIZE));
  50. page_num++;
  51. } while (page_num < FEE_DENSITY_PAGES);
  52. }
  53. /*****************************************************************************
  54. * Writes once data byte to flash on specified address. If a byte is already
  55. * written, the whole page must be copied to a buffer, the byte changed and
  56. * the manipulated buffer written after PageErase.
  57. *******************************************************************************/
  58. uint16_t EEPROM_WriteDataByte (uint16_t Address, uint8_t DataByte) {
  59. FLASH_Status FlashStatus = FLASH_COMPLETE;
  60. uint32_t page;
  61. int i;
  62. // exit if desired address is above the limit (e.G. under 2048 Bytes for 4 pages)
  63. if (Address > FEE_DENSITY_BYTES) {
  64. return 0;
  65. }
  66. // calculate which page is affected (Pagenum1/Pagenum2...PagenumN)
  67. page = (FEE_PAGE_BASE_ADDRESS + FEE_ADDR_OFFSET(Address)) & 0x00000FFF;
  68. if (page % FEE_PAGE_SIZE) page = page + FEE_PAGE_SIZE;
  69. page = (page / FEE_PAGE_SIZE) - 1;
  70. // if current data is 0xFF, the byte is empty, just overwrite with the new one
  71. if ((*(__IO uint16_t*)(FEE_PAGE_BASE_ADDRESS + FEE_ADDR_OFFSET(Address))) == FEE_EMPTY_WORD) {
  72. FlashStatus = FLASH_ProgramHalfWord(FEE_PAGE_BASE_ADDRESS + FEE_ADDR_OFFSET(Address), (uint16_t)(0x00FF & DataByte));
  73. }
  74. else {
  75. // Copy Page to a buffer
  76. memcpy(DataBuf, (uint8_t*)FEE_PAGE_BASE_ADDRESS + (page * FEE_PAGE_SIZE), FEE_PAGE_SIZE); // !!! Calculate base address for the desired page
  77. // check if new data is differ to current data, return if not, proceed if yes
  78. if (DataByte == *(__IO uint8_t*)(FEE_PAGE_BASE_ADDRESS + FEE_ADDR_OFFSET(Address))) {
  79. return 0;
  80. }
  81. // manipulate desired data byte in temp data array if new byte is differ to the current
  82. DataBuf[FEE_ADDR_OFFSET(Address)] = DataByte;
  83. //Erase Page
  84. FlashStatus = FLASH_ErasePage(FEE_PAGE_BASE_ADDRESS + page);
  85. // Write new data (whole page) to flash if data has beed changed
  86. for(i = 0; i < (FEE_PAGE_SIZE / 2); i++) {
  87. if ((__IO uint16_t)(0xFF00 | DataBuf[FEE_ADDR_OFFSET(i)]) != 0xFFFF) {
  88. FlashStatus = FLASH_ProgramHalfWord((FEE_PAGE_BASE_ADDRESS + (page * FEE_PAGE_SIZE)) + (i * 2), (uint16_t)(0xFF00 | DataBuf[FEE_ADDR_OFFSET(i)]));
  89. }
  90. }
  91. }
  92. return FlashStatus;
  93. }
  94. /*****************************************************************************
  95. * Read once data byte from a specified address.
  96. *******************************************************************************/
  97. uint8_t EEPROM_ReadDataByte (uint16_t Address) {
  98. uint8_t DataByte = 0xFF;
  99. // Get Byte from specified address
  100. DataByte = (*(__IO uint8_t*)(FEE_PAGE_BASE_ADDRESS + FEE_ADDR_OFFSET(Address)));
  101. return DataByte;
  102. }
  103. /*****************************************************************************
  104. * Wrap library in AVR style functions.
  105. *******************************************************************************/
  106. uint8_t eeprom_read_byte (const uint8_t *Address)
  107. {
  108. const uint16_t p = (const uint32_t) Address;
  109. return EEPROM_ReadDataByte(p);
  110. }
  111. void eeprom_write_byte (uint8_t *Address, uint8_t Value)
  112. {
  113. uint16_t p = (uint32_t) Address;
  114. EEPROM_WriteDataByte(p, Value);
  115. }
  116. void eeprom_update_byte (uint8_t *Address, uint8_t Value)
  117. {
  118. uint16_t p = (uint32_t) Address;
  119. EEPROM_WriteDataByte(p, Value);
  120. }
  121. uint16_t eeprom_read_word (const uint16_t *Address)
  122. {
  123. const uint16_t p = (const uint32_t) Address;
  124. return EEPROM_ReadDataByte(p) | (EEPROM_ReadDataByte(p+1) << 8);
  125. }
  126. void eeprom_write_word (uint16_t *Address, uint16_t Value)
  127. {
  128. uint16_t p = (uint32_t) Address;
  129. EEPROM_WriteDataByte(p, (uint8_t) Value);
  130. EEPROM_WriteDataByte(p + 1, (uint8_t) (Value >> 8));
  131. }
  132. void eeprom_update_word (uint16_t *Address, uint16_t Value)
  133. {
  134. uint16_t p = (uint32_t) Address;
  135. EEPROM_WriteDataByte(p, (uint8_t) Value);
  136. EEPROM_WriteDataByte(p + 1, (uint8_t) (Value >> 8));
  137. }
  138. uint32_t eeprom_read_dword (const uint32_t *Address)
  139. {
  140. const uint16_t p = (const uint32_t) Address;
  141. return EEPROM_ReadDataByte(p) | (EEPROM_ReadDataByte(p+1) << 8)
  142. | (EEPROM_ReadDataByte(p+2) << 16) | (EEPROM_ReadDataByte(p+3) << 24);
  143. }
  144. void eeprom_write_dword (uint32_t *Address, uint32_t Value)
  145. {
  146. uint16_t p = (const uint32_t) Address;
  147. EEPROM_WriteDataByte(p, (uint8_t) Value);
  148. EEPROM_WriteDataByte(p+1, (uint8_t) (Value >> 8));
  149. EEPROM_WriteDataByte(p+2, (uint8_t) (Value >> 16));
  150. EEPROM_WriteDataByte(p+3, (uint8_t) (Value >> 24));
  151. }
  152. void eeprom_update_dword (uint32_t *Address, uint32_t Value)
  153. {
  154. uint16_t p = (const uint32_t) Address;
  155. EEPROM_WriteDataByte(p, (uint8_t) Value);
  156. EEPROM_WriteDataByte(p+1, (uint8_t) (Value >> 8));
  157. EEPROM_WriteDataByte(p+2, (uint8_t) (Value >> 16));
  158. EEPROM_WriteDataByte(p+3, (uint8_t) (Value >> 24));
  159. }
  160. void eeprom_read_block(void *buf, const void *addr, uint32_t len) {
  161. const uint8_t *p = (const uint8_t *)addr;
  162. uint8_t *dest = (uint8_t *)buf;
  163. while (len--) {
  164. *dest++ = eeprom_read_byte(p++);
  165. }
  166. }
  167. void eeprom_write_block(const void *buf, void *addr, uint32_t len) {
  168. uint8_t *p = (uint8_t *)addr;
  169. const uint8_t *src = (const uint8_t *)buf;
  170. while (len--) {
  171. eeprom_write_byte(p++, *src++);
  172. }
  173. }
  174. void eeprom_update_block(const void *buf, void *addr, uint32_t len) {
  175. uint8_t *p = (uint8_t *)addr;
  176. const uint8_t *src = (const uint8_t *)buf;
  177. while (len--) {
  178. eeprom_write_byte(p++, *src++);
  179. }
  180. }