lpc177x_8x_eeprom.c 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. /*
  2. * Copyright (C) 2012 by Ole Reinhardt (ole.reinhardt@embedded-it.de)
  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. * Parts taken from lpc177x_8x_eeprom.c 2011-06-02
  36. * file lpc177x_8x_eeprom.c
  37. * brief Contains all functions support for EEPROM firmware library on
  38. * on LPC177x_8x
  39. * version 1.0
  40. * date 02. June. 2011
  41. * author NXP MCU SW Application Team
  42. *
  43. * Copyright(C) 2011, NXP Semiconductor
  44. * All rights reserved.
  45. *
  46. ***********************************************************************
  47. * Software that is described herein is for illustrative purposes only
  48. * which provides customers with programming information regarding the
  49. * products. This software is supplied "AS IS" without any warranties.
  50. * NXP Semiconductors assumes no responsibility or liability for the
  51. * use of the software, conveys no license or title under any patent,
  52. * copyright, or mask work right to the product. NXP Semiconductors
  53. * reserves the right to make changes in the software without
  54. * notification. NXP Semiconductors also make no representation or
  55. * warranty that such application will be suitable for the specified
  56. * use without further testing or modification.
  57. **********************************************************************/
  58. #include <inttypes.h>
  59. #include <sys/timer.h>
  60. #include <arch/cm3.h>
  61. #if defined(MCU_LPC177x_8x)
  62. #include <arch/cm3/nxp/lpc177x_8x.h>
  63. #include <arch/cm3/nxp/lpc177x_8x_clk.h>
  64. #elif defined(MCU_LPC407x_8x)
  65. #include <arch/cm3/nxp/lpc407x_8x.h>
  66. #include <arch/cm3/nxp/lpc407x_8x_clk.h>
  67. #else
  68. #warning "Unknown LPC familiy"
  69. #endif
  70. #include <arch/cm3/nxp/lpc177x_8x_eeprom.h>
  71. static uint8_t eeprom_init = 0;
  72. /*!
  73. * \brief Initialize EEPROM
  74. *
  75. * Initialize the eeprom memeory. Therefore enable power and setup clocks
  76. *
  77. * \param none
  78. * \return none
  79. */
  80. void Lpc177x_8x_EepromInit(void)
  81. {
  82. uint32_t cpu_clock;
  83. uint32_t clk_div;
  84. uint32_t waitstates;
  85. if (eeprom_init) {
  86. return;
  87. }
  88. /* EEPROM is automate turn on after reset */
  89. LPC_EEPROM->PWRDWN = 0x0;
  90. /* Clocks have to be set:
  91. * EEPROM requires a 375kHz. This clock is generated by dividing the
  92. * system bus clock.
  93. */
  94. cpu_clock = NutArchClockGet(NUT_HWCLK_CPU);
  95. clk_div = (cpu_clock / 375000) - 1;
  96. LPC_EEPROM->CLKDIV = clk_div;
  97. /* Setting wait state */
  98. waitstates = ((((cpu_clock / 1000000) * 15) / 1000) + 1);
  99. waitstates |= (((((cpu_clock / 1000000) * 55) / 1000) + 1) << 8);
  100. waitstates |= (((((cpu_clock / 1000000) * 35) / 1000) + 1) << 16);
  101. LPC_EEPROM->WSTATE = waitstates;
  102. eeprom_init = 1;
  103. }
  104. /*!
  105. * \brief Read data from EEPROM at specific address
  106. *
  107. * \param address EEPROM address that start to write data, it must be
  108. * in range 0..0x1000
  109. * \param buff buffer to place the read data in
  110. * \param size number of bytes to be read
  111. *
  112. * \return none
  113. */
  114. int Lpc177x_8x_EepromRead(uint16_t addr, void* buff, size_t size)
  115. {
  116. uint16_t page_nr;
  117. uint16_t page_offs;
  118. uint32_t i;
  119. uint8_t *pt = (uint8_t*) buff;
  120. if (addr + size > EEPROM_SIZE) {
  121. return -1;
  122. }
  123. if (!eeprom_init) {
  124. Lpc177x_8x_EepromInit();
  125. }
  126. page_offs = addr & EEPROM_PAGE_OFFSET_MASK;
  127. page_nr = (addr & EEPROM_PAGE_NUM_MASK) >> 6;
  128. LPC_EEPROM->INT_CLR_STATUS = (_BV(EEPROM_ENDOF_RW) | _BV(EEPROM_ENDOF_PROG));
  129. LPC_EEPROM->ADDR = EEPROM_PAGE_ADRESS(page_nr) | EEPROM_PAGE_OFFSET(page_offs);
  130. LPC_EEPROM->CMD = EEPROM_CMD_8_BIT_READ | EEPROM_CMD_RDPREFETCH;
  131. /* Read and store data in buffer */
  132. for(i = 0; i < size; i++){
  133. /* Check if we read beyond the eeprom size */
  134. if (page_nr >= EEPROM_PAGE_NUM) {
  135. /* Clean up interrupt status before exit to prevent an issue when using the IAP
  136. (internal flash) right after accessing the EEPROM
  137. */
  138. LPC_EEPROM->INT_CLR_STATUS = (_BV(EEPROM_ENDOF_RW) | _BV(EEPROM_ENDOF_PROG));
  139. return -1;
  140. }
  141. LPC_EEPROM->INT_CLR_STATUS = _BV(EEPROM_ENDOF_RW);
  142. *(pt++) = (uint8_t)(LPC_EEPROM->RDATA);
  143. page_offs ++;
  144. while (!(LPC_EEPROM->INT_STATUS & _BV(EEPROM_ENDOF_RW)));
  145. if ((page_offs >= EEPROM_PAGE_SIZE) && (i < size - 1)) {
  146. page_offs = 0;
  147. page_nr++;
  148. LPC_EEPROM->ADDR = EEPROM_PAGE_ADRESS(page_nr) | EEPROM_PAGE_OFFSET(page_offs);
  149. LPC_EEPROM->CMD = EEPROM_CMD_8_BIT_READ | EEPROM_CMD_RDPREFETCH;
  150. }
  151. }
  152. /* Clean up interrupt status before exit to prevent an issue when using the IAP
  153. (internal flash) right after accessing the EEPROM
  154. */
  155. LPC_EEPROM->INT_CLR_STATUS = (_BV(EEPROM_ENDOF_RW) | _BV(EEPROM_ENDOF_PROG));
  156. return 0;
  157. }
  158. /*!
  159. * \brief Write data to EEPROM at specific address
  160. *
  161. * \param address EEPROM address that start to write data, it must be
  162. * in range 0..0x1000
  163. * \param buff buffer that contain data that will be written to buffer
  164. * \param size number of bytes to be written
  165. *
  166. * \return none
  167. */
  168. int Lpc177x_8x_EepromWrite(uint16_t addr, const void* buff, size_t size)
  169. {
  170. uint16_t page_nr;
  171. uint16_t page_offs;
  172. uint32_t i;
  173. uint8_t *pt = (uint8_t*) buff;
  174. if (addr + size > EEPROM_SIZE) {
  175. return -1;
  176. }
  177. if (!eeprom_init) {
  178. Lpc177x_8x_EepromInit();
  179. }
  180. page_offs = addr & EEPROM_PAGE_OFFSET_MASK;
  181. page_nr = (addr & EEPROM_PAGE_NUM_MASK) >> 6;
  182. LPC_EEPROM->INT_CLR_STATUS = (_BV(EEPROM_ENDOF_RW) | _BV(EEPROM_ENDOF_PROG));
  183. LPC_EEPROM->ADDR = EEPROM_PAGE_ADRESS(page_nr) | EEPROM_PAGE_OFFSET(page_offs);
  184. LPC_EEPROM->INT_CLR_STATUS = _BV(EEPROM_ENDOF_RW);
  185. for(i = 0; i < size; i++) {
  186. /* Update data to page register */
  187. LPC_EEPROM->CMD = EEPROM_CMD_8_BIT_WRITE;
  188. LPC_EEPROM->WDATA = *(pt++);
  189. page_offs ++;
  190. if ((page_offs >= EEPROM_PAGE_SIZE) | (i == size - 1)) {
  191. /* Update to EEPROM memory */
  192. LPC_EEPROM->INT_CLR_STATUS = _BV(EEPROM_ENDOF_PROG);
  193. LPC_EEPROM->ADDR = EEPROM_PAGE_ADRESS(page_nr);
  194. LPC_EEPROM->CMD = EEPROM_CMD_ERASE_PRG_PAGE;
  195. while (!(LPC_EEPROM->INT_STATUS & _BV(EEPROM_ENDOF_PROG)));
  196. }
  197. if (page_offs >= EEPROM_PAGE_SIZE) {
  198. page_offs = 0;
  199. page_nr ++;
  200. LPC_EEPROM->ADDR =0;
  201. if(page_nr >= EEPROM_PAGE_NUM) {
  202. page_nr = 0;
  203. }
  204. }
  205. }
  206. /* Clean up interrupt status before exit to prevent an issue when using the IAP
  207. (internal flash) right after accessing the EEPROM
  208. */
  209. LPC_EEPROM->INT_CLR_STATUS = (_BV(EEPROM_ENDOF_RW) | _BV(EEPROM_ENDOF_PROG));
  210. return 0;
  211. }