stm32l1_eeprom.c 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. /*
  2. * Copyright (C) 2013 Uwe Bonnes
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions
  6. * are met:
  7. *
  8. * 1. Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the distribution.
  13. * 3. Neither the name of the copyright holders nor the names of
  14. * contributors may be used to endorse or promote products derived
  15. * from this software without specific prior written permission.
  16. *
  17. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  18. * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  19. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  20. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  21. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  22. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  23. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  24. * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  25. * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  26. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
  27. * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  28. * SUCH DAMAGE.
  29. *
  30. * For additional information see http://www.ethernut.de/
  31. *
  32. */
  33. #include <stdint.h>
  34. #include <string.h>
  35. #include <cfg/arch.h>
  36. #include <cfg/memory.h>
  37. #include <cfg/eeprom.h>
  38. #include <sys/nutdebug.h>
  39. #include <dev/iap_flash.h>
  40. #if defined(MCU_STM32L1)
  41. #include <arch/cm3/stm/vendor/stm32l1xx.h>
  42. #else
  43. #warning "STM32 family has no L1 compatible FLASH/EEPROM"
  44. #endif
  45. #define ERASED_PATTERN_32 0
  46. #define FLASH_PEKEY1 0x89abcdef
  47. #define FLASH_PEKEY2 0x02030405
  48. #if defined (STM32L1XX_MDP)
  49. #define STM32L1_EEPROM_SIZE ( 8 << 10)
  50. #elif defined (STM32L1XX_HD)
  51. #define STM32L1_EEPROM_SIZE ( 8 << 10)
  52. #else
  53. #define STM32L1_EEPROM_SIZE ( 4 << 10)
  54. #endif
  55. #define STM32L1_EEPROM_BASE 0x08080000
  56. /*!
  57. * \brief Read data from EEPROM at specific address
  58. *
  59. * \param address EEPROM address that start to write data, it must be
  60. * in range 0..STM32L1_EEPROM_SIZE
  61. * \param buff buffer to place the read data in
  62. * \param size number of bytes to be read
  63. *
  64. * \return none
  65. */
  66. int Stm32l1_EepromRead(uint16_t addr, void* buff, size_t size)
  67. {
  68. uint32_t ee_addr;
  69. if ((uint32_t)addr + size > STM32L1_EEPROM_SIZE )
  70. return FLASH_BOUNDARY;
  71. ee_addr = STM32L1_EEPROM_BASE + addr;
  72. while((ee_addr & 3) && size) {
  73. *(uint8_t*)buff = *(uint8_t*)ee_addr;
  74. buff++;
  75. ee_addr++;
  76. size--;
  77. }
  78. while(size > 3) {
  79. *(uint32_t*)buff = *(uint32_t*)ee_addr;
  80. buff += 4;
  81. ee_addr += 4;
  82. size -= 4;
  83. }
  84. while(size) {
  85. *(uint8_t*)buff = *(uint8_t*)ee_addr;
  86. buff++;
  87. ee_addr++;
  88. size--;
  89. }
  90. return FLASH_COMPLETE;
  91. }
  92. /*!
  93. * \brief Write data to EEPROM at specific address
  94. *
  95. * \param address EEPROM address that start to write data, it must be
  96. * in range 0..STM32L1_EEPROM_SIZE
  97. * \param buff buffer that contain data that will be written to buffer
  98. * \param size number of bytes to be written
  99. *
  100. * \return FLASH_STARUS
  101. */
  102. int Stm32l1_EepromWrite(uint16_t addr, const void* buff, size_t size)
  103. {
  104. uint32_t ee_addr;
  105. int rs;
  106. if (size == 0)
  107. return FLASH_COMPLETE;
  108. if ((uint32_t)addr + size > STM32L1_EEPROM_SIZE )
  109. return FLASH_BOUNDARY;
  110. ee_addr = STM32L1_EEPROM_BASE + addr;
  111. if (FLASH->PECR & FLASH_PECR_PELOCK) {
  112. FLASH->PEKEYR = FLASH_PEKEY1;
  113. FLASH->PEKEYR = FLASH_PEKEY2;
  114. if (FLASH->PECR & FLASH_PECR_PELOCK)
  115. return FLASH_ERROR_PG;
  116. }
  117. if (ee_addr & 1) {
  118. uint8_t data = *(uint8_t *)buff;
  119. if (data != *(uint8_t *)ee_addr) {
  120. if (*(uint8_t *)ee_addr != (uint8_t)ERASED_PATTERN_32)
  121. FLASH->PECR = FLASH_PECR_FTDW;
  122. else
  123. FLASH->PECR = 0;
  124. *(uint8_t *)ee_addr = data;
  125. }
  126. buff ++;
  127. ee_addr ++;
  128. size --;
  129. }
  130. if ((ee_addr & 2) && (size > 1)) {
  131. uint16_t data = *(uint16_t *)buff;
  132. if (data != *(uint16_t *)ee_addr) {
  133. if (*(uint16_t *)ee_addr != (uint16_t)ERASED_PATTERN_32)
  134. FLASH->PECR = FLASH_PECR_FTDW;
  135. else
  136. FLASH->PECR = 0;
  137. *(uint16_t *)ee_addr = data;
  138. }
  139. buff += 2;
  140. ee_addr += 2;
  141. size -= 2;
  142. }
  143. while (size > 3) {
  144. uint32_t data = *(uint32_t *)buff;
  145. if (data != *(uint32_t *)ee_addr) {
  146. if (*(uint32_t *)ee_addr != ERASED_PATTERN_32)
  147. FLASH->PECR = FLASH_PECR_FTDW;
  148. else
  149. FLASH->PECR = 0;
  150. *(uint32_t *)ee_addr = data;
  151. }
  152. buff += 4;
  153. ee_addr += 4;
  154. size -= 4;
  155. }
  156. if (size > 1) {
  157. uint16_t data = *(uint16_t *)buff;
  158. if (data != *(uint16_t *)ee_addr) {
  159. if (*(uint16_t *)ee_addr != (uint16_t)ERASED_PATTERN_32)
  160. FLASH->PECR = FLASH_PECR_FTDW;
  161. else
  162. FLASH->PECR = 0;
  163. *(uint16_t *)ee_addr = data;
  164. }
  165. buff += 2;
  166. ee_addr += 2;
  167. size -= 2;
  168. }
  169. if (size) {
  170. uint8_t data = *(uint8_t *)buff;
  171. if (data != *(uint8_t *)ee_addr) {
  172. if (*(uint8_t *)ee_addr != (uint8_t)ERASED_PATTERN_32)
  173. FLASH->PECR = FLASH_PECR_FTDW;
  174. else
  175. FLASH->PECR = 0;
  176. *(uint8_t *)ee_addr = data;
  177. }
  178. }
  179. rs = FLASH_COMPLETE;
  180. FLASH->PECR = FLASH_PECR_PELOCK;
  181. return rs;
  182. }