flashc.c 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283
  1. /*!
  2. * Copyright (C) 2001-2010 by egnite Software GmbH
  3. *
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions
  8. * are met:
  9. *
  10. * 1. Redistributions of source code must retain the above copyright
  11. * notice, this list of conditions and the following disclaimer.
  12. * 2. Redistributions in binary form must reproduce the above copyright
  13. * notice, this list of conditions and the following disclaimer in the
  14. * documentation and/or other materials provided with the distribution.
  15. * 3. Neither the name of the copyright holders nor the names of
  16. * contributors may be used to endorse or promote products derived
  17. * from this software without specific prior written permission.
  18. *
  19. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  20. * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  21. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  22. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  23. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  24. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  25. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  26. * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  27. * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  28. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
  29. * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  30. * SUCH DAMAGE.
  31. *
  32. * For additional information see http://www.ethernut.de/
  33. */
  34. /*!
  35. * \file arch/avr32/dev/flashc.c
  36. * \brief AVR32 embedded flash controller support.
  37. *
  38. */
  39. #include <sys/atom.h>
  40. #include <dev/nvmem.h>
  41. #include <stdint.h>
  42. #include <stdlib.h>
  43. #include <string.h>
  44. #include <arch/avr32.h>
  45. #include <arch/avr32/flashc.h>
  46. #include <avr32/io.h>
  47. /*!
  48. * \addtogroup xgAvr32Efc
  49. */
  50. /*@{*/
  51. /*! \brief Address offset of the configuration sector.
  52. */
  53. #ifndef FLASH_CONF_SECTOR
  54. #define FLASH_CONF_SECTOR 0x0003FF00
  55. #endif
  56. /*! \brief Size of the configuration area.
  57. *
  58. * During write operations a buffer with this size is allocated
  59. * from heap and may cause memory problems with large sectors.
  60. * Thus, this value may be less than the size of the configuration
  61. * sector, in which case the rest of the sector is unused.
  62. *
  63. * Currently only 1 sector can be used for system configurations.
  64. */
  65. #ifndef FLASH_CONF_SIZE
  66. #define FLASH_CONF_SIZE AVR32_FLASHC_PAGE_SIZE
  67. #endif
  68. #ifndef FLASH_WRITE_WAIT
  69. #define FLASH_WRITE_WAIT 60000
  70. #endif
  71. #ifndef FLASH_ERASE_WAIT
  72. #define FLASH_ERASE_WAIT 60000
  73. #endif
  74. #ifndef FLASH_CHIP_ERASE_WAIT
  75. #define FLASH_CHIP_ERASE_WAIT 600000
  76. #endif
  77. typedef uint32_t flashdat_t;
  78. typedef unsigned long flashadr_t;
  79. typedef volatile flashdat_t *flashptr_t;
  80. static int flashc_is_ready(void)
  81. {
  82. return ((AVR32_FLASHC.fsr & AVR32_FLASHC_FSR_FRDY_MASK) != 0);
  83. }
  84. /*!
  85. * \brief Execute flash controller command.
  86. *
  87. */
  88. int Avr32FlashcCmd(unsigned int cmd, uint32_t tmo)
  89. {
  90. int rc = 0;
  91. /* Make sure that the previous command has finished. */
  92. while (!flashc_is_ready()) {
  93. if (tmo && --tmo < 1) {
  94. return -1;
  95. }
  96. }
  97. /* IRQ handlers are located in flash. Disable them. */
  98. NutEnterCritical();
  99. /* Write command. */
  100. outr(AVR32_FLASHC.fcmd, AVR32_FLASHC_FCMD_KEY_KEY | cmd);
  101. /* Wait for ready flag set. */
  102. while (!flashc_is_ready()) {
  103. if (tmo && --tmo < 1) {
  104. rc = -1;
  105. break;
  106. }
  107. }
  108. /* Flash command finished. Re-enable IRQ handlers. */
  109. NutExitCritical();
  110. /* Check result. */
  111. if (AVR32_FLASHC.fsr & (AVR32_FLASHC_FSR_LOCKE_MASK | AVR32_FLASHC_FSR_PROGE_MASK)) {
  112. rc = -1;
  113. }
  114. return rc;
  115. }
  116. /*!
  117. * \brief Read data from flash memory.
  118. *
  119. * \param off Start location within the chip, starting at 0.
  120. * \param data Points to a buffer that receives the data.
  121. * \param len Number of bytes to read.
  122. *
  123. * \return Always 0.
  124. */
  125. int Avr32FlashcSectorRead(unsigned int off, void *data, unsigned int len)
  126. {
  127. memcpy(data, (void *) (uptr_t) (AVR32_FLASH_ADDRESS + off), len);
  128. return 0;
  129. }
  130. /*!
  131. * \brief Write data into flash memory.
  132. *
  133. * The related sector will be automatically erased before writing.
  134. *
  135. * \param off Start location within the chip, starting at 0.
  136. * \param data Points to a buffer that contains the bytes to be written.
  137. * If this is a NULL pointer, then the sector will be erased.
  138. * \param len Number of bytes to write, 1 full sector max.
  139. *
  140. * \return 0 on success or -1 in case of an error.
  141. */
  142. int Avr32FlashcSectorWrite(unsigned int off, const void *data, unsigned int len)
  143. {
  144. flashptr_t dp = (flashptr_t) (uptr_t) (AVR32_FLASH_ADDRESS + off);
  145. int rc;
  146. unsigned int i;
  147. if (data) {
  148. flashptr_t sp = (flashptr_t) data;
  149. /* Copy data to the flash write buffer. */
  150. for (i = 0; i < len; i += sizeof(flashdat_t)) {
  151. *dp++ = *sp++;
  152. }
  153. } else {
  154. /* All bits set to emulate sector erasing. */
  155. for (i = 0; i < len; i += sizeof(flashdat_t)) {
  156. *dp++ = (flashdat_t) (-1);
  157. }
  158. }
  159. /* Erase target flash page. */
  160. Avr32FlashcSectorErase(off);
  161. /* Execute page write command. */
  162. rc = Avr32FlashcCmd((off & AVR32_FLASHC_FCMD_PAGEN_MASK) | AVR32_FLASHC_FCMD_CMD_WP, FLASH_WRITE_WAIT);
  163. return rc;
  164. }
  165. /*!
  166. * \brief Erase sector at the specified offset.
  167. */
  168. int Avr32FlashcSectorErase(unsigned int off)
  169. {
  170. return Avr32FlashcCmd((off & AVR32_FLASHC_FCMD_PAGEN_MASK) | AVR32_FLASHC_FCMD_CMD_EP, FLASH_ERASE_WAIT);
  171. }
  172. /*!
  173. * \brief Lock specified region.
  174. *
  175. * \param off Location within the region to be locked.
  176. *
  177. * \return 0 on success or -1 in case of an error.
  178. */
  179. int Avr32FlashcRegionLock(unsigned int off)
  180. {
  181. return Avr32FlashcCmd((off & AVR32_FLASHC_FCMD_PAGEN_MASK) | AVR32_FLASHC_FCMD_CMD_LP, FLASH_WRITE_WAIT);
  182. }
  183. /*!
  184. * \brief Unlock specified region.
  185. *
  186. * \param off Location within the region to be unlocked.
  187. *
  188. * \return 0 on success or -1 in case of an error.
  189. */
  190. int Avr32FlashcRegionUnlock(unsigned int off)
  191. {
  192. return Avr32FlashcCmd((off & AVR32_FLASHC_FCMD_PAGEN_MASK) | AVR32_FLASHC_FCMD_CMD_UP, FLASH_WRITE_WAIT);
  193. }
  194. /*!
  195. * \brief Load configuration parameters from embedded flash memory.
  196. *
  197. * Applications should call NutNvMemLoad().
  198. *
  199. * \param pos Start location within configuration sector.
  200. * \param data Points to a buffer that receives the contents.
  201. * \param len Number of bytes to read.
  202. *
  203. * \return Always 0.
  204. */
  205. int Avr32FlashcParamRead(unsigned int pos, void *data, unsigned int len)
  206. {
  207. return Avr32FlashcSectorRead(FLASH_CONF_SECTOR + pos, data, len);
  208. }
  209. /*!
  210. * \brief Store configuration parameters in embedded flash memory.
  211. *
  212. * Applications should call NutNvMemSave().
  213. *
  214. * The region that contains the configuration sector will be automatically
  215. * locked.
  216. *
  217. * \param pos Start location within configuration sector.
  218. * \param data Points to a buffer that contains the bytes to store.
  219. * \param len Number of bytes to store.
  220. *
  221. * \return 0 on success or -1 in case of an error.
  222. */
  223. int Avr32FlashcParamWrite(unsigned int pos, const void *data, unsigned int len)
  224. {
  225. int rc = -1;
  226. uint8_t *buff;
  227. /* Load the complete configuration area. */
  228. if ((buff = malloc(FLASH_CONF_SIZE)) != NULL) {
  229. rc = Avr32FlashcSectorRead(FLASH_CONF_SECTOR, buff, FLASH_CONF_SIZE);
  230. /* Compare old with new contents. */
  231. if (memcmp(buff + pos, data, len)) {
  232. /* New contents differs. Copy it into the sector buffer. */
  233. memcpy(buff + pos, data, len);
  234. /* Write back new data. Maintain region lock. */
  235. if (Avr32FlashcRegionUnlock(FLASH_CONF_SECTOR) == 0) {
  236. rc = Avr32FlashcSectorWrite(FLASH_CONF_SECTOR, buff, FLASH_CONF_SIZE);
  237. Avr32FlashcRegionLock(FLASH_CONF_SECTOR);
  238. }
  239. }
  240. free(buff);
  241. }
  242. return rc;
  243. }
  244. /*@}*/