em_msc.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374
  1. /***************************************************************************//**
  2. * @file
  3. * @brief Flash controller (MSC) Peripheral API
  4. * @author Energy Micro AS
  5. * @version 3.0.0
  6. *******************************************************************************
  7. * @section License
  8. * <b>(C) Copyright 2012 Energy Micro AS, http://www.energymicro.com</b>
  9. *******************************************************************************
  10. *
  11. * Permission is granted to anyone to use this software for any purpose,
  12. * including commercial applications, and to alter it and redistribute it
  13. * freely, subject to the following restrictions:
  14. *
  15. * 1. The origin of this software must not be misrepresented; you must not
  16. * claim that you wrote the original software.
  17. * 2. Altered source versions must be plainly marked as such, and must not be
  18. * misrepresented as being the original software.
  19. * 3. This notice may not be removed or altered from any source distribution.
  20. *
  21. * DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Energy Micro AS has no
  22. * obligation to support this Software. Energy Micro AS is providing the
  23. * Software "AS IS", with no express or implied warranties of any kind,
  24. * including, but not limited to, any implied warranties of merchantability
  25. * or fitness for any particular purpose or warranties against infringement
  26. * of any proprietary rights of a third party.
  27. *
  28. * Energy Micro AS will not be liable for any consequential, incidental, or
  29. * special damages, or any other relief, or for any claim by any third party,
  30. * arising from your use of this Software.
  31. *
  32. ******************************************************************************/
  33. #include "em_msc.h"
  34. #if defined (_EFM32_TINY_FAMILY) || defined(_EFM32_GIANT_FAMILY)
  35. #include "em_cmu.h"
  36. #endif
  37. #include "em_assert.h"
  38. /***************************************************************************//**
  39. * @addtogroup EM_Library
  40. * @{
  41. ******************************************************************************/
  42. /***************************************************************************//**
  43. * @addtogroup MSC
  44. * @brief Flash controller (MSC) Peripheral API
  45. * @{
  46. ******************************************************************************/
  47. /*******************************************************************************
  48. ************************** GLOBAL FUNCTIONS *******************************
  49. ******************************************************************************/
  50. /***************************************************************************//**
  51. * @brief
  52. * Enables the flash controller for writing.
  53. * @note
  54. * IMPORTANT: This function must be called before flash operations when
  55. * AUXHFRCO clock has been changed from default 14MHz band.
  56. ******************************************************************************/
  57. void MSC_Init(void)
  58. {
  59. #if defined (_EFM32_TINY_FAMILY) || defined(_EFM32_GIANT_FAMILY)
  60. uint32_t freq, cycles;
  61. #endif
  62. /* Enable writing to the MSC */
  63. MSC->WRITECTRL |= MSC_WRITECTRL_WREN;
  64. /* Unlock the MSC */
  65. MSC->LOCK = MSC_UNLOCK_CODE;
  66. /* Disable writing to the MSC */
  67. MSC->WRITECTRL &= ~MSC_WRITECTRL_WREN;
  68. #if defined (_EFM32_TINY_FAMILY) || defined(_EFM32_GIANT_FAMILY)
  69. /* Configure MSC->TIMEBASE according to selected frequency */
  70. freq = CMU_ClockFreqGet(cmuClock_AUX);
  71. if( freq > 7000000)
  72. {
  73. /* Calculate number of clock cycles for 1us as base period */
  74. freq = (freq * 11) / 10;
  75. cycles = (freq / 1000000) + 1;
  76. /* Configure clock cycles for flash timing */
  77. MSC->TIMEBASE = (MSC->TIMEBASE & ~(_MSC_TIMEBASE_BASE_MASK|
  78. _MSC_TIMEBASE_PERIOD_MASK))|
  79. MSC_TIMEBASE_PERIOD_1US|
  80. (cycles << _MSC_TIMEBASE_BASE_SHIFT);
  81. }
  82. else
  83. {
  84. /* Calculate number of clock cycles for 5us as base period */
  85. freq = (freq * 5 * 11) / 10;
  86. cycles = (freq / 1000000) + 1;
  87. /* Configure clock cycles for flash timing */
  88. MSC->TIMEBASE = (MSC->TIMEBASE & ~(_MSC_TIMEBASE_BASE_MASK|
  89. _MSC_TIMEBASE_PERIOD_MASK))|
  90. MSC_TIMEBASE_PERIOD_5US|
  91. (cycles << _MSC_TIMEBASE_BASE_SHIFT);
  92. }
  93. #endif
  94. }
  95. /***************************************************************************//**
  96. * @brief
  97. * Disables the flash controller for writing.
  98. ******************************************************************************/
  99. void MSC_Deinit(void)
  100. {
  101. /* Enable writing to the MSC */
  102. MSC->WRITECTRL |= MSC_WRITECTRL_WREN;
  103. /* Lock the MSC */
  104. MSC->LOCK = 0;
  105. /* Disable writing to the MSC */
  106. MSC->WRITECTRL &= ~MSC_WRITECTRL_WREN;
  107. }
  108. /***************************************************************************//**
  109. * @brief
  110. * Erases a page in flash memory.
  111. * @note
  112. * This function MUST be executed from RAM. Failure to execute this portion
  113. * of the code in RAM will result in a hardfault. For IAR, Rowley and
  114. * Codesourcery this will be achieved automatically. For Keil uVision 4 you
  115. * must define a section called "ram_code" and place this manually in your
  116. * project's scatter file.
  117. * @param[in] startAddress
  118. * Pointer to the flash page to erase. Must be aligned to beginning of page
  119. * boundary.
  120. * @return
  121. * Returns the status of erase operation, #msc_Return_TypeDef
  122. * @verbatim
  123. * flashReturnOk - Operation completed successfully.
  124. * flashReturnInvalidAddr - Operation tried to erase a non-flash area.
  125. * flashReturnLocked - Operation tried to erase a locked area of the flash.
  126. * flashReturnTimeOut - Operation timed out waiting for flash operation
  127. * to complete.
  128. * @endverbatim
  129. ******************************************************************************/
  130. #ifdef __CC_ARM /* MDK-ARM compiler */
  131. #pragma arm section code="ram_code"
  132. #endif /* __CC_ARM */
  133. #if defined( __ICCARM__ )
  134. /* Suppress warnings originating from use of EFM_ASSERT(): */
  135. /* "Call to a non __ramfunc function from within a __ramfunc function" */
  136. /* "Possible rom access from within a __ramfunc function" */
  137. #pragma diag_suppress=Ta022
  138. #pragma diag_suppress=Ta023
  139. #endif
  140. msc_Return_TypeDef MSC_ErasePage(uint32_t *startAddress)
  141. {
  142. int timeOut = MSC_PROGRAM_TIMEOUT;
  143. /* Address must be aligned to pages */
  144. EFM_ASSERT((((uint32_t)startAddress) & 0x1FF) == 0);
  145. /* Enable writing to the MSC */
  146. MSC->WRITECTRL |= MSC_WRITECTRL_WREN;
  147. /* Load address */
  148. MSC->ADDRB = (uint32_t)startAddress;
  149. MSC->WRITECMD = MSC_WRITECMD_LADDRIM;
  150. /* Check for invalid address */
  151. if (MSC->STATUS & MSC_STATUS_INVADDR)
  152. {
  153. /* Disable writing to the MSC */
  154. MSC->WRITECTRL &= ~MSC_WRITECTRL_WREN;
  155. return mscReturnInvalidAddr;
  156. }
  157. /* Check for write protected page */
  158. if (MSC->STATUS & MSC_STATUS_LOCKED)
  159. {
  160. /* Disable writing to the MSC */
  161. MSC->WRITECTRL &= ~MSC_WRITECTRL_WREN;
  162. return mscReturnLocked;
  163. }
  164. /* Send erase page command */
  165. MSC->WRITECMD = MSC_WRITECMD_ERASEPAGE;
  166. /* Wait for the erase to complete */
  167. while ((MSC->STATUS & MSC_STATUS_BUSY) && (timeOut != 0))
  168. {
  169. timeOut--;
  170. }
  171. if (timeOut == 0)
  172. {
  173. /* Disable writing to the MSC */
  174. MSC->WRITECTRL &= ~MSC_WRITECTRL_WREN;
  175. return mscReturnTimeOut;
  176. }
  177. /* Disable writing to the MSC */
  178. MSC->WRITECTRL &= ~MSC_WRITECTRL_WREN;
  179. return mscReturnOk;
  180. }
  181. #if defined( __ICCARM__ )
  182. #pragma diag_default=Ta022
  183. #pragma diag_default=Ta023
  184. #endif
  185. /***************************************************************************//**
  186. * @brief
  187. * Writes a single word to flash memory. Data to write must be aligned to
  188. * words and contain a number of bytes that is divisable by four.
  189. * @note
  190. * The flash must be erased prior to writing a new word.
  191. * This function must be run from RAM. Failure to execute this portion
  192. * of the code in RAM will result in a hardfault. For IAR, Rowley and
  193. * Codesourcery this will be achieved automatically. For Keil uVision 4 you
  194. * must define a section called "ram_code" and place this manually in your
  195. * project's scatter file.
  196. *
  197. * @param[in] address
  198. * Pointer to the flash word to write to. Must be aligned to words.
  199. * @param[in] data
  200. * Data to write to flash.
  201. * @param[in] numBytes
  202. * Number of bytes to write from flash. NB: Must be divisable by four.
  203. * @return
  204. * Returns the status of the write operation, #msc_Return_TypeDef
  205. * @verbatim
  206. * flashReturnOk - Operation completed successfully.
  207. * flashReturnInvalidAddr - Operation tried to erase a non-flash area.
  208. * flashReturnLocked - Operation tried to erase a locked area of the flash.
  209. * flashReturnTimeOut - Operation timed out waiting for flash operation
  210. * to complete.
  211. * @endverbatim
  212. ******************************************************************************/
  213. #ifdef __CC_ARM /* MDK-ARM compiler */
  214. #pragma arm section code="ram_code"
  215. #endif /* __CC_ARM */
  216. #if defined( __ICCARM__ )
  217. /* Suppress warnings originating from use of EFM_ASSERT(): */
  218. /* "Call to a non __ramfunc function from within a __ramfunc function" */
  219. /* "Possible rom access from within a __ramfunc function" */
  220. #pragma diag_suppress=Ta022
  221. #pragma diag_suppress=Ta023
  222. #endif
  223. msc_Return_TypeDef MSC_WriteWord(uint32_t *address, void const *data, int numBytes)
  224. {
  225. int timeOut;
  226. int wordCount;
  227. int numWords;
  228. /* Check alignment (Must be aligned to words) */
  229. EFM_ASSERT(((uint32_t) address & 0x3) == 0);
  230. /* Check number of bytes. Must be divisable by four */
  231. EFM_ASSERT((numBytes & 0x3) == 0);
  232. /* Enable writing to the MSC */
  233. MSC->WRITECTRL |= MSC_WRITECTRL_WREN;
  234. /* Convert bytes to words */
  235. numWords = numBytes >> 2;
  236. for (wordCount = 0; wordCount < numWords; wordCount++)
  237. {
  238. /* Load address */
  239. MSC->ADDRB = (uint32_t)(address + wordCount);
  240. MSC->WRITECMD = MSC_WRITECMD_LADDRIM;
  241. /* Check for invalid address */
  242. if (MSC->STATUS & MSC_STATUS_INVADDR)
  243. {
  244. /* Disable writing to the MSC */
  245. MSC->WRITECTRL &= ~MSC_WRITECTRL_WREN;
  246. return mscReturnInvalidAddr;
  247. }
  248. /* Check for write protected page */
  249. if (MSC->STATUS & MSC_STATUS_LOCKED)
  250. {
  251. /* Disable writing to the MSC */
  252. MSC->WRITECTRL &= ~MSC_WRITECTRL_WREN;
  253. return mscReturnLocked;
  254. }
  255. /* Wait for the MSC to be ready for a new data word */
  256. /* Due to the timing of this function, the MSC should already by ready */
  257. timeOut = MSC_PROGRAM_TIMEOUT;
  258. while (((MSC->STATUS & MSC_STATUS_WDATAREADY) == 0) && (timeOut != 0))
  259. {
  260. timeOut--;
  261. }
  262. /* Check for timeout */
  263. if (timeOut == 0)
  264. {
  265. /* Disable writing to the MSC */
  266. MSC->WRITECTRL &= ~MSC_WRITECTRL_WREN;
  267. return mscReturnTimeOut;
  268. }
  269. /* Load data into write data register */
  270. MSC->WDATA = *(((uint32_t *)data) + wordCount);
  271. /* Trigger write once */
  272. MSC->WRITECMD = MSC_WRITECMD_WRITEONCE;
  273. /* Wait for the write to complete */
  274. timeOut = MSC_PROGRAM_TIMEOUT;
  275. while ((MSC->STATUS & MSC_STATUS_BUSY) && (timeOut != 0))
  276. {
  277. timeOut--;
  278. }
  279. /* Check for timeout */
  280. if (timeOut == 0)
  281. {
  282. /* Disable writing to the MSC */
  283. MSC->WRITECTRL &= ~MSC_WRITECTRL_WREN;
  284. return mscReturnTimeOut;
  285. }
  286. }
  287. /* Disable writing to the MSC */
  288. MSC->WRITECTRL &= ~MSC_WRITECTRL_WREN;
  289. return mscReturnOk;
  290. }
  291. #if defined( __ICCARM__ )
  292. #pragma diag_default=Ta022
  293. #pragma diag_default=Ta023
  294. #endif
  295. #if defined(_EFM32_GIANT_FAMILY)
  296. /***************************************************************************//**
  297. * @brief
  298. * Erase entire flash in one operation
  299. * @note
  300. * This command will erase the entire contents of the device.
  301. * Use with care, both a debug session and all contents of the flash will be
  302. * lost. The lock bit, MLW will prevent this operation from executing and
  303. * might prevent successful mass erase.
  304. ******************************************************************************/
  305. #ifdef __CC_ARM /* MDK-ARM compiler */
  306. #pragma arm section code="ram_code"
  307. #endif /* __CC_ARM */
  308. msc_Return_TypeDef MSC_MassErase(void)
  309. {
  310. /* Enable writing to the MSC */
  311. MSC->WRITECTRL |= MSC_WRITECTRL_WREN;
  312. /* Unlock device mass erase */
  313. MSC->MASSLOCK = MSC_MASSLOCK_LOCKKEY_UNLOCK;
  314. /* Erase first 512K block */
  315. MSC->WRITECMD = MSC_WRITECMD_ERASEMAIN0;
  316. /* Waiting for erase to complete */
  317. while ((MSC->STATUS & MSC_STATUS_BUSY)){}
  318. #if FLASH_SIZE >= (512*1024)
  319. /* Erase second 512K block */
  320. MSC->WRITECMD = MSC_WRITECMD_ERASEMAIN1;
  321. /* Waiting for erase to complete */
  322. while ((MSC->STATUS & MSC_STATUS_BUSY)){}
  323. #endif
  324. /* Restore mass erase lock */
  325. MSC->MASSLOCK = MSC_MASSLOCK_LOCKKEY_LOCK;
  326. /* This will only successfully return if calling function is also in SRAM */
  327. return mscReturnOk;
  328. }
  329. #endif
  330. /** @} (end addtogroup MSC) */
  331. /** @} (end addtogroup EM_Library) */