efm32_msc.c 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. /***************************************************************************//**
  2. * @file
  3. * @brief On-board Flash controller module peripheral API for EFM32
  4. * devices.
  5. * @author Energy Micro AS
  6. * @version 1.3.0
  7. *******************************************************************************
  8. * @section License
  9. * <b>(C) Copyright 2010 Energy Micro AS, http://www.energymicro.com</b>
  10. *******************************************************************************
  11. *
  12. * This source code is the property of Energy Micro AS. The source and compiled
  13. * code may only be used on Energy Micro "EFM32" microcontrollers.
  14. *
  15. * This copyright notice may not be removed from the source code nor changed.
  16. *
  17. * DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Energy Micro AS has no
  18. * obligation to support this Software. Energy Micro AS is providing the
  19. * Software "AS IS", with no express or implied warranties of any kind,
  20. * including, but not limited to, any implied warranties of merchantability
  21. * or fitness for any particular purpose or warranties against infringement
  22. * of any proprietary rights of a third party.
  23. *
  24. * Energy Micro AS will not be liable for any consequential, incidental, or
  25. * special damages, or any other relief, or for any claim by any third party,
  26. * arising from your use of this Software.
  27. *
  28. ******************************************************************************/
  29. #include "efm32_msc.h"
  30. #include "efm32_assert.h"
  31. /***************************************************************************//**
  32. * @addtogroup EFM32_Library
  33. * @{
  34. ******************************************************************************/
  35. /***************************************************************************//**
  36. * @addtogroup MSC
  37. * @brief EFM32 Flash controllre utilities.
  38. * @{
  39. ******************************************************************************/
  40. /*******************************************************************************
  41. ************************** GLOBAL FUNCTIONS *******************************
  42. ******************************************************************************/
  43. /***************************************************************************//**
  44. * @brief
  45. * Enables the flash controller for writing.
  46. ******************************************************************************/
  47. void MSC_Init(void)
  48. {
  49. /* Enable writing to the MSC */
  50. MSC->WRITECTRL |= MSC_WRITECTRL_WREN;
  51. /* Unlock the MSC */
  52. MSC->LOCK = MSC_UNLOCK_CODE;
  53. /* Disable writing to the MSC */
  54. MSC->WRITECTRL &= ~MSC_WRITECTRL_WREN;
  55. }
  56. /***************************************************************************//**
  57. * @brief
  58. * Disables the flash controller for writing.
  59. ******************************************************************************/
  60. void MSC_Deinit(void)
  61. {
  62. /* Enable writing to the MSC */
  63. MSC->WRITECTRL |= MSC_WRITECTRL_WREN;
  64. /* Lock the MSC */
  65. MSC->LOCK = 0;
  66. /* Disable writing to the MSC */
  67. MSC->WRITECTRL &= ~MSC_WRITECTRL_WREN;
  68. }
  69. /***************************************************************************//**
  70. * @brief
  71. * Erases a page in flash memory.
  72. * @note
  73. * This function MUST be executed from RAM. Failure to execute this portion
  74. * of the code in RAM will result in a hardfault. For IAR, Rowley and
  75. * Codesourcery this will be achieved automatically. For Keil uVision 4 you
  76. * must define a section called "ram_code" and place this manually in your
  77. * project's scatter file.
  78. * @param[in] startAddress
  79. * Pointer to the flash page to erase. Must be aligned to beginning of page
  80. * boundary.
  81. * @return
  82. * Returns the status of erase operation, #msc_Return_TypeDef
  83. * @verbatim
  84. * flashReturnOk - Operation completed successfully.
  85. * flashReturnInvalidAddr - Operation tried to erase a non-flash area.
  86. * flashReturnLocked - Operation tried to erase a locked area of the flash.
  87. * flashReturnTimeOut - Operation timed out waiting for flash operation
  88. * to complete.
  89. * @endverbatim
  90. ******************************************************************************/
  91. #ifdef __CC_ARM /* MDK-ARM compiler */
  92. #pragma arm section code="ram_code"
  93. #endif /* __CC_ARM */
  94. msc_Return_TypeDef MSC_ErasePage(uint32_t *startAddress)
  95. {
  96. int timeOut = MSC_PROGRAM_TIMEOUT;
  97. /* Address must be aligned to pages */
  98. EFM_ASSERT((((uint32_t) startAddress) & 0x1FF) == 0);
  99. /* Enable writing to the MSC */
  100. MSC->WRITECTRL |= MSC_WRITECTRL_WREN;
  101. /* Load address */
  102. MSC->ADDRB = (uint32_t) startAddress;
  103. MSC->WRITECMD = MSC_WRITECMD_LADDRIM;
  104. /* Check for invalid address */
  105. if (MSC->STATUS & MSC_STATUS_INVADDR)
  106. {
  107. /* Disable writing to the MSC */
  108. MSC->WRITECTRL &= ~MSC_WRITECTRL_WREN;
  109. return mscReturnInvalidAddr;
  110. }
  111. /* Check for write protected page */
  112. if (MSC->STATUS & MSC_STATUS_LOCKED)
  113. {
  114. /* Disable writing to the MSC */
  115. MSC->WRITECTRL &= ~MSC_WRITECTRL_WREN;
  116. return mscReturnLocked;
  117. }
  118. /* Send erase page command */
  119. MSC->WRITECMD = MSC_WRITECMD_ERASEPAGE;
  120. /* Wait for the erase to complete */
  121. while ((MSC->STATUS & MSC_STATUS_BUSY) && (timeOut != 0))
  122. {
  123. timeOut--;
  124. }
  125. if (timeOut == 0)
  126. {
  127. /* Disable writing to the MSC */
  128. MSC->WRITECTRL &= ~MSC_WRITECTRL_WREN;
  129. return mscReturnTimeOut;
  130. }
  131. /* Disable writing to the MSC */
  132. MSC->WRITECTRL &= ~MSC_WRITECTRL_WREN;
  133. return mscReturnOk;
  134. }
  135. /***************************************************************************//**
  136. * @brief
  137. * Writes a single word to flash memory. Data to write must be aligned to
  138. * words and contain a number of bytes that is divisable by four.
  139. * @note
  140. * The flash must be erased prior to writing a new word.
  141. * This function must be run from RAM. Failure to execute this portion
  142. * of the code in RAM will result in a hardfault. For IAR, Rowley and
  143. * Codesourcery this will be achieved automatically. For Keil uVision 4 you
  144. * must define a section called "ram_code" and place this manually in your
  145. * project's scatter file.
  146. *
  147. * @param[in] address
  148. * Pointer to the flash word to write to. Must be aligned to words.
  149. * @param[in] data
  150. * Data to write to flash.
  151. * @param[in] numBytes
  152. * Number of bytes to write from flash. NB: Must be divisable by four.
  153. * @return
  154. * Returns the status of the write operation, #msc_Return_TypeDef
  155. * @verbatim
  156. * flashReturnOk - Operation completed successfully.
  157. * flashReturnInvalidAddr - Operation tried to erase a non-flash area.
  158. * flashReturnLocked - Operation tried to erase a locked area of the flash.
  159. * flashReturnTimeOut - Operation timed out waiting for flash operation
  160. * to complete.
  161. * @endverbatim
  162. ******************************************************************************/
  163. #ifdef __CC_ARM /* MDK-ARM compiler */
  164. #pragma arm section code="ram_code"
  165. #endif /* __CC_ARM */
  166. msc_Return_TypeDef MSC_WriteWord(uint32_t *address, void *data, int numBytes)
  167. {
  168. int timeOut;
  169. int wordCount;
  170. int numWords;
  171. /* Check alignment (Must be aligned to words) */
  172. EFM_ASSERT(((uint32_t)address & 0x3) == 0);
  173. /* Check number of bytes. Must be divisable by four */
  174. EFM_ASSERT((numBytes & 0x3) == 0);
  175. /* Enable writing to the MSC */
  176. MSC->WRITECTRL |= MSC_WRITECTRL_WREN;
  177. /* Convert bytes to words */
  178. numWords = numBytes >> 2;
  179. for (wordCount = 0; wordCount < numWords; wordCount++)
  180. {
  181. /* Load address */
  182. MSC->ADDRB = (uint32_t)(address + wordCount);
  183. MSC->WRITECMD = MSC_WRITECMD_LADDRIM;
  184. /* Check for invalid address */
  185. if (MSC->STATUS & MSC_STATUS_INVADDR)
  186. {
  187. /* Disable writing to the MSC */
  188. MSC->WRITECTRL &= ~MSC_WRITECTRL_WREN;
  189. return mscReturnInvalidAddr;
  190. }
  191. /* Check for write protected page */
  192. if (MSC->STATUS & MSC_STATUS_LOCKED)
  193. {
  194. /* Disable writing to the MSC */
  195. MSC->WRITECTRL &= ~MSC_WRITECTRL_WREN;
  196. return mscReturnLocked;
  197. }
  198. /* Wait for the MSC to be ready for a new data word */
  199. /* Due to the timing of this function, the MSC should allready by ready */
  200. timeOut = MSC_PROGRAM_TIMEOUT;
  201. while (((MSC->STATUS & MSC_STATUS_WDATAREADY) == 0) && (timeOut != 0))
  202. {
  203. timeOut--;
  204. }
  205. /* Check for timeout */
  206. if (timeOut == 0)
  207. {
  208. /* Disable writing to the MSC */
  209. MSC->WRITECTRL &= ~MSC_WRITECTRL_WREN;
  210. return mscReturnTimeOut;
  211. }
  212. /* Load data into write data register */
  213. MSC->WDATA = *(((uint32_t *) data) + wordCount);
  214. /* Trigger write once */
  215. MSC->WRITECMD = MSC_WRITECMD_WRITEONCE;
  216. /* Wait for the write to complete */
  217. timeOut = MSC_PROGRAM_TIMEOUT;
  218. while ((MSC->STATUS & MSC_STATUS_BUSY) && (timeOut != 0))
  219. {
  220. timeOut--;
  221. }
  222. /* Check for timeout */
  223. if (timeOut == 0)
  224. {
  225. /* Disable writing to the MSC */
  226. MSC->WRITECTRL &= ~MSC_WRITECTRL_WREN;
  227. return mscReturnTimeOut;
  228. }
  229. }
  230. /* Disable writing to the MSC */
  231. MSC->WRITECTRL &= ~MSC_WRITECTRL_WREN;
  232. return mscReturnOk;
  233. }
  234. /** @} (end addtogroup MSC) */
  235. /** @} (end addtogroup EFM32_Library) */