added prescaler for 16 bit pwm in LPC1347 target

Fork of mbed-dev by mbed official

Committer:
bogdanm
Date:
Thu Oct 01 15:25:22 2015 +0300
Revision:
0:9b334a45a8ff
Child:
50:a417edff4437
Initial commit on mbed-dev

Replaces mbed-src (now inactive)

Who changed what in which revision?

UserRevisionLine numberNew contents of line
bogdanm 0:9b334a45a8ff 1 /***************************************************************************//**
bogdanm 0:9b334a45a8ff 2 * @file em_msc.c
bogdanm 0:9b334a45a8ff 3 * @brief Flash controller (MSC) Peripheral API
bogdanm 0:9b334a45a8ff 4 * @version 3.20.12
bogdanm 0:9b334a45a8ff 5 *******************************************************************************
bogdanm 0:9b334a45a8ff 6 * @section License
bogdanm 0:9b334a45a8ff 7 * <b>(C) Copyright 2014 Silicon Labs, http://www.silabs.com</b>
bogdanm 0:9b334a45a8ff 8 *******************************************************************************
bogdanm 0:9b334a45a8ff 9 *
bogdanm 0:9b334a45a8ff 10 * Permission is granted to anyone to use this software for any purpose,
bogdanm 0:9b334a45a8ff 11 * including commercial applications, and to alter it and redistribute it
bogdanm 0:9b334a45a8ff 12 * freely, subject to the following restrictions:
bogdanm 0:9b334a45a8ff 13 *
bogdanm 0:9b334a45a8ff 14 * 1. The origin of this software must not be misrepresented; you must not
bogdanm 0:9b334a45a8ff 15 * claim that you wrote the original software.
bogdanm 0:9b334a45a8ff 16 * 2. Altered source versions must be plainly marked as such, and must not be
bogdanm 0:9b334a45a8ff 17 * misrepresented as being the original software.
bogdanm 0:9b334a45a8ff 18 * 3. This notice may not be removed or altered from any source distribution.
bogdanm 0:9b334a45a8ff 19 *
bogdanm 0:9b334a45a8ff 20 * DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Silicon Labs has no
bogdanm 0:9b334a45a8ff 21 * obligation to support this Software. Silicon Labs is providing the
bogdanm 0:9b334a45a8ff 22 * Software "AS IS", with no express or implied warranties of any kind,
bogdanm 0:9b334a45a8ff 23 * including, but not limited to, any implied warranties of merchantability
bogdanm 0:9b334a45a8ff 24 * or fitness for any particular purpose or warranties against infringement
bogdanm 0:9b334a45a8ff 25 * of any proprietary rights of a third party.
bogdanm 0:9b334a45a8ff 26 *
bogdanm 0:9b334a45a8ff 27 * Silicon Labs will not be liable for any consequential, incidental, or
bogdanm 0:9b334a45a8ff 28 * special damages, or any other relief, or for any claim by any third party,
bogdanm 0:9b334a45a8ff 29 * arising from your use of this Software.
bogdanm 0:9b334a45a8ff 30 *
bogdanm 0:9b334a45a8ff 31 ******************************************************************************/
bogdanm 0:9b334a45a8ff 32
bogdanm 0:9b334a45a8ff 33 #include "em_msc.h"
bogdanm 0:9b334a45a8ff 34 #if defined( MSC_COUNT ) && ( MSC_COUNT > 0 )
bogdanm 0:9b334a45a8ff 35
bogdanm 0:9b334a45a8ff 36 #include "em_system.h"
bogdanm 0:9b334a45a8ff 37 #if defined( _MSC_TIMEBASE_MASK )
bogdanm 0:9b334a45a8ff 38 #include "em_cmu.h"
bogdanm 0:9b334a45a8ff 39 #include "em_int.h"
bogdanm 0:9b334a45a8ff 40 #endif
bogdanm 0:9b334a45a8ff 41 #include "em_assert.h"
bogdanm 0:9b334a45a8ff 42
bogdanm 0:9b334a45a8ff 43 /** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
bogdanm 0:9b334a45a8ff 44
bogdanm 0:9b334a45a8ff 45 #if defined( MSC_WRITECTRL_WDOUBLE )
bogdanm 0:9b334a45a8ff 46 #define WORDS_PER_DATA_PHASE (FLASH_SIZE < (512 * 1024) ? 1 : 2)
bogdanm 0:9b334a45a8ff 47 #else
bogdanm 0:9b334a45a8ff 48 #define WORDS_PER_DATA_PHASE (1)
bogdanm 0:9b334a45a8ff 49 #endif
bogdanm 0:9b334a45a8ff 50
bogdanm 0:9b334a45a8ff 51 typedef enum {
bogdanm 0:9b334a45a8ff 52 mscWriteIntSafe,
bogdanm 0:9b334a45a8ff 53 mscWriteFast,
bogdanm 0:9b334a45a8ff 54 } MSC_WriteStrategy_Typedef;
bogdanm 0:9b334a45a8ff 55
bogdanm 0:9b334a45a8ff 56 /** @endcond */
bogdanm 0:9b334a45a8ff 57
bogdanm 0:9b334a45a8ff 58 /***************************************************************************//**
bogdanm 0:9b334a45a8ff 59 * @addtogroup EM_Library
bogdanm 0:9b334a45a8ff 60 * @{
bogdanm 0:9b334a45a8ff 61 ******************************************************************************/
bogdanm 0:9b334a45a8ff 62
bogdanm 0:9b334a45a8ff 63 /***************************************************************************//**
bogdanm 0:9b334a45a8ff 64 * @addtogroup MSC
bogdanm 0:9b334a45a8ff 65 * @brief Flash controller (MSC) Peripheral API
bogdanm 0:9b334a45a8ff 66 * @{
bogdanm 0:9b334a45a8ff 67 ******************************************************************************/
bogdanm 0:9b334a45a8ff 68
bogdanm 0:9b334a45a8ff 69 /*******************************************************************************
bogdanm 0:9b334a45a8ff 70 ************************** GLOBAL FUNCTIONS *******************************
bogdanm 0:9b334a45a8ff 71 ******************************************************************************/
bogdanm 0:9b334a45a8ff 72
bogdanm 0:9b334a45a8ff 73 /***************************************************************************//**
bogdanm 0:9b334a45a8ff 74 * @brief
bogdanm 0:9b334a45a8ff 75 * Enables the flash controller for writing.
bogdanm 0:9b334a45a8ff 76 * @note
bogdanm 0:9b334a45a8ff 77 * IMPORTANT: This function must be called before flash operations when
bogdanm 0:9b334a45a8ff 78 * AUXHFRCO clock has been changed from default 14MHz band.
bogdanm 0:9b334a45a8ff 79 ******************************************************************************/
bogdanm 0:9b334a45a8ff 80 void MSC_Init(void)
bogdanm 0:9b334a45a8ff 81 {
bogdanm 0:9b334a45a8ff 82 #if defined( _MSC_TIMEBASE_MASK )
bogdanm 0:9b334a45a8ff 83 uint32_t freq, cycles;
bogdanm 0:9b334a45a8ff 84 #endif
bogdanm 0:9b334a45a8ff 85 /* Unlock the MSC */
bogdanm 0:9b334a45a8ff 86 MSC->LOCK = MSC_UNLOCK_CODE;
bogdanm 0:9b334a45a8ff 87 /* Disable writing to the flash */
bogdanm 0:9b334a45a8ff 88 MSC->WRITECTRL &= ~MSC_WRITECTRL_WREN;
bogdanm 0:9b334a45a8ff 89
bogdanm 0:9b334a45a8ff 90 #if defined( _MSC_TIMEBASE_MASK )
bogdanm 0:9b334a45a8ff 91 /* Configure MSC->TIMEBASE according to selected frequency */
bogdanm 0:9b334a45a8ff 92 freq = CMU_ClockFreqGet(cmuClock_AUX);
bogdanm 0:9b334a45a8ff 93
bogdanm 0:9b334a45a8ff 94 if (freq > 7000000)
bogdanm 0:9b334a45a8ff 95 {
bogdanm 0:9b334a45a8ff 96 /* Calculate number of clock cycles for 1us as base period */
bogdanm 0:9b334a45a8ff 97 freq = (freq * 11) / 10;
bogdanm 0:9b334a45a8ff 98 cycles = (freq / 1000000) + 1;
bogdanm 0:9b334a45a8ff 99
bogdanm 0:9b334a45a8ff 100 /* Configure clock cycles for flash timing */
bogdanm 0:9b334a45a8ff 101 MSC->TIMEBASE = (MSC->TIMEBASE & ~(_MSC_TIMEBASE_BASE_MASK |
bogdanm 0:9b334a45a8ff 102 _MSC_TIMEBASE_PERIOD_MASK)) |
bogdanm 0:9b334a45a8ff 103 MSC_TIMEBASE_PERIOD_1US |
bogdanm 0:9b334a45a8ff 104 (cycles << _MSC_TIMEBASE_BASE_SHIFT);
bogdanm 0:9b334a45a8ff 105 }
bogdanm 0:9b334a45a8ff 106 else
bogdanm 0:9b334a45a8ff 107 {
bogdanm 0:9b334a45a8ff 108 /* Calculate number of clock cycles for 5us as base period */
bogdanm 0:9b334a45a8ff 109 freq = (freq * 5 * 11) / 10;
bogdanm 0:9b334a45a8ff 110 cycles = (freq / 1000000) + 1;
bogdanm 0:9b334a45a8ff 111
bogdanm 0:9b334a45a8ff 112 /* Configure clock cycles for flash timing */
bogdanm 0:9b334a45a8ff 113 MSC->TIMEBASE = (MSC->TIMEBASE & ~(_MSC_TIMEBASE_BASE_MASK |
bogdanm 0:9b334a45a8ff 114 _MSC_TIMEBASE_PERIOD_MASK)) |
bogdanm 0:9b334a45a8ff 115 MSC_TIMEBASE_PERIOD_5US |
bogdanm 0:9b334a45a8ff 116 (cycles << _MSC_TIMEBASE_BASE_SHIFT);
bogdanm 0:9b334a45a8ff 117 }
bogdanm 0:9b334a45a8ff 118 #endif
bogdanm 0:9b334a45a8ff 119 }
bogdanm 0:9b334a45a8ff 120
bogdanm 0:9b334a45a8ff 121 /***************************************************************************//**
bogdanm 0:9b334a45a8ff 122 * @brief
bogdanm 0:9b334a45a8ff 123 * Disables the flash controller for writing.
bogdanm 0:9b334a45a8ff 124 ******************************************************************************/
bogdanm 0:9b334a45a8ff 125 void MSC_Deinit(void)
bogdanm 0:9b334a45a8ff 126 {
bogdanm 0:9b334a45a8ff 127 /* Disable writing to the flash */
bogdanm 0:9b334a45a8ff 128 MSC->WRITECTRL &= ~MSC_WRITECTRL_WREN;
bogdanm 0:9b334a45a8ff 129 /* Lock the MSC */
bogdanm 0:9b334a45a8ff 130 MSC->LOCK = 0;
bogdanm 0:9b334a45a8ff 131 }
bogdanm 0:9b334a45a8ff 132
bogdanm 0:9b334a45a8ff 133 /** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
bogdanm 0:9b334a45a8ff 134
bogdanm 0:9b334a45a8ff 135 /***************************************************************************//**
bogdanm 0:9b334a45a8ff 136 * @brief
bogdanm 0:9b334a45a8ff 137 * Perform address phase of Flash write cycle.
bogdanm 0:9b334a45a8ff 138 * @details
bogdanm 0:9b334a45a8ff 139 * This function performs the address phase of a Flash write operation by
bogdanm 0:9b334a45a8ff 140 * writing the given flash address to the ADDRB register and issuing the
bogdanm 0:9b334a45a8ff 141 * LADDRIM command to load the address.
bogdanm 0:9b334a45a8ff 142 * @param[in] address
bogdanm 0:9b334a45a8ff 143 * Address in flash memory. Must be aligned at a 4 byte boundary.
bogdanm 0:9b334a45a8ff 144 * @return
bogdanm 0:9b334a45a8ff 145 * Returns the status of the address load operation, #MSC_Status_TypeDef
bogdanm 0:9b334a45a8ff 146 * @verbatim
bogdanm 0:9b334a45a8ff 147 * mscReturnOk - Operation completed successfully.
bogdanm 0:9b334a45a8ff 148 * mscReturnInvalidAddr - Operation tried to erase a non-flash area.
bogdanm 0:9b334a45a8ff 149 * mscReturnLocked - Operation tried to erase a locked area of the flash.
bogdanm 0:9b334a45a8ff 150 * @endverbatim
bogdanm 0:9b334a45a8ff 151 ******************************************************************************/
bogdanm 0:9b334a45a8ff 152 #ifdef __CC_ARM /* MDK-ARM compiler */
bogdanm 0:9b334a45a8ff 153 #pragma arm section code="ram_code"
bogdanm 0:9b334a45a8ff 154 #endif /* __CC_ARM */
bogdanm 0:9b334a45a8ff 155 #ifdef __ICCARM__
bogdanm 0:9b334a45a8ff 156 /* Suppress warnings originating from use of EFM_ASSERT(): */
bogdanm 0:9b334a45a8ff 157 /* "Call to a non __ramfunc function from within a __ramfunc function" */
bogdanm 0:9b334a45a8ff 158 /* "Possible rom access from within a __ramfunc function" */
bogdanm 0:9b334a45a8ff 159 #pragma diag_suppress=Ta022
bogdanm 0:9b334a45a8ff 160 #pragma diag_suppress=Ta023
bogdanm 0:9b334a45a8ff 161 __ramfunc
bogdanm 0:9b334a45a8ff 162 #endif
bogdanm 0:9b334a45a8ff 163 __STATIC_INLINE MSC_Status_TypeDef MSC_LoadVerifyAddress(uint32_t* address)
bogdanm 0:9b334a45a8ff 164 {
bogdanm 0:9b334a45a8ff 165 uint32_t status;
bogdanm 0:9b334a45a8ff 166 uint32_t timeOut;
bogdanm 0:9b334a45a8ff 167
bogdanm 0:9b334a45a8ff 168 /* Wait for the MSC to become ready. */
bogdanm 0:9b334a45a8ff 169 timeOut = MSC_PROGRAM_TIMEOUT;
bogdanm 0:9b334a45a8ff 170 while ((MSC->STATUS & MSC_STATUS_BUSY) && (timeOut != 0))
bogdanm 0:9b334a45a8ff 171 {
bogdanm 0:9b334a45a8ff 172 timeOut--;
bogdanm 0:9b334a45a8ff 173 }
bogdanm 0:9b334a45a8ff 174
bogdanm 0:9b334a45a8ff 175 /* Check for timeout */
bogdanm 0:9b334a45a8ff 176 if (timeOut == 0)
bogdanm 0:9b334a45a8ff 177 {
bogdanm 0:9b334a45a8ff 178 return mscReturnTimeOut;
bogdanm 0:9b334a45a8ff 179 }
bogdanm 0:9b334a45a8ff 180 /* Load address */
bogdanm 0:9b334a45a8ff 181 MSC->ADDRB = (uint32_t)address;
bogdanm 0:9b334a45a8ff 182 MSC->WRITECMD = MSC_WRITECMD_LADDRIM;
bogdanm 0:9b334a45a8ff 183
bogdanm 0:9b334a45a8ff 184 status = MSC->STATUS;
bogdanm 0:9b334a45a8ff 185 if (status & (MSC_STATUS_INVADDR | MSC_STATUS_LOCKED))
bogdanm 0:9b334a45a8ff 186 {
bogdanm 0:9b334a45a8ff 187 /* Check for invalid address */
bogdanm 0:9b334a45a8ff 188 if (status & MSC_STATUS_INVADDR)
bogdanm 0:9b334a45a8ff 189 return mscReturnInvalidAddr;
bogdanm 0:9b334a45a8ff 190 /* Check for write protected page */
bogdanm 0:9b334a45a8ff 191 if (status & MSC_STATUS_LOCKED)
bogdanm 0:9b334a45a8ff 192 return mscReturnLocked;
bogdanm 0:9b334a45a8ff 193 }
bogdanm 0:9b334a45a8ff 194 return mscReturnOk;
bogdanm 0:9b334a45a8ff 195 }
bogdanm 0:9b334a45a8ff 196 #ifdef __ICCARM__
bogdanm 0:9b334a45a8ff 197 #pragma diag_default=Ta022
bogdanm 0:9b334a45a8ff 198 #pragma diag_default=Ta023
bogdanm 0:9b334a45a8ff 199 #endif
bogdanm 0:9b334a45a8ff 200 #ifdef __CC_ARM /* MDK-ARM compiler */
bogdanm 0:9b334a45a8ff 201 #pragma arm section code
bogdanm 0:9b334a45a8ff 202 #endif /* __CC_ARM */
bogdanm 0:9b334a45a8ff 203
bogdanm 0:9b334a45a8ff 204
bogdanm 0:9b334a45a8ff 205 /***************************************************************************//**
bogdanm 0:9b334a45a8ff 206 * @brief
bogdanm 0:9b334a45a8ff 207 * Perform a Flash data write phase.
bogdanm 0:9b334a45a8ff 208 * @details
bogdanm 0:9b334a45a8ff 209 * This function performs the data phase of a Flash write operation by loading
bogdanm 0:9b334a45a8ff 210 * the given number of 32-bit words to the WDATA register.
bogdanm 0:9b334a45a8ff 211 * @param[in] data
bogdanm 0:9b334a45a8ff 212 * Pointer to the first data word to load.
bogdanm 0:9b334a45a8ff 213 * @param[in] numWords
bogdanm 0:9b334a45a8ff 214 * Number of data words (32-bit) to load.
bogdanm 0:9b334a45a8ff 215 * @param[in] writeStrategy
bogdanm 0:9b334a45a8ff 216 * Write strategy to apply.
bogdanm 0:9b334a45a8ff 217 * @return
bogdanm 0:9b334a45a8ff 218 * Returns the status of the data load operation
bogdanm 0:9b334a45a8ff 219 * @verbatim
bogdanm 0:9b334a45a8ff 220 * mscReturnOk - Operation completed successfully.
bogdanm 0:9b334a45a8ff 221 * mscReturnTimeOut - Operation timed out waiting for flash operation
bogdanm 0:9b334a45a8ff 222 * to complete.
bogdanm 0:9b334a45a8ff 223 * @endverbatim
bogdanm 0:9b334a45a8ff 224 ******************************************************************************/
bogdanm 0:9b334a45a8ff 225 #ifdef __CC_ARM /* MDK-ARM compiler */
bogdanm 0:9b334a45a8ff 226 #pragma arm section code="ram_code"
bogdanm 0:9b334a45a8ff 227 #endif /* __CC_ARM */
bogdanm 0:9b334a45a8ff 228 #ifdef __ICCARM__
bogdanm 0:9b334a45a8ff 229 /* Suppress warnings originating from use of EFM_ASSERT(): */
bogdanm 0:9b334a45a8ff 230 /* "Call to a non __ramfunc function from within a __ramfunc function" */
bogdanm 0:9b334a45a8ff 231 /* "Possible rom access from within a __ramfunc function" */
bogdanm 0:9b334a45a8ff 232 #pragma diag_suppress=Ta022
bogdanm 0:9b334a45a8ff 233 #pragma diag_suppress=Ta023
bogdanm 0:9b334a45a8ff 234 __ramfunc
bogdanm 0:9b334a45a8ff 235 #endif
bogdanm 0:9b334a45a8ff 236 __STATIC_INLINE MSC_Status_TypeDef MSC_LoadWriteData(uint32_t* data,
bogdanm 0:9b334a45a8ff 237 uint32_t numWords,
bogdanm 0:9b334a45a8ff 238 MSC_WriteStrategy_Typedef writeStrategy)
bogdanm 0:9b334a45a8ff 239 {
bogdanm 0:9b334a45a8ff 240 uint32_t timeOut;
bogdanm 0:9b334a45a8ff 241 uint32_t wordIndex;
bogdanm 0:9b334a45a8ff 242 uint32_t wordsPerDataPhase;
bogdanm 0:9b334a45a8ff 243 MSC_Status_TypeDef retval = mscReturnOk;
bogdanm 0:9b334a45a8ff 244
bogdanm 0:9b334a45a8ff 245 #if defined( _MSC_WRITECTRL_LPWRITE_MASK ) && defined( _MSC_WRITECTRL_WDOUBLE_MASK )
bogdanm 0:9b334a45a8ff 246 /* If LPWRITE (Low Power Write) is NOT enabled, set WDOUBLE (Write Double word) */
bogdanm 0:9b334a45a8ff 247 if (!(MSC->WRITECTRL & MSC_WRITECTRL_LPWRITE))
bogdanm 0:9b334a45a8ff 248 {
bogdanm 0:9b334a45a8ff 249 /* If the number of words to be written are odd, we need to align by writing
bogdanm 0:9b334a45a8ff 250 a single word first, before setting the WDOUBLE bit. */
bogdanm 0:9b334a45a8ff 251 if (numWords & 0x1)
bogdanm 0:9b334a45a8ff 252 {
bogdanm 0:9b334a45a8ff 253 /* Wait for the MSC to become ready for the next word. */
bogdanm 0:9b334a45a8ff 254 timeOut = MSC_PROGRAM_TIMEOUT;
bogdanm 0:9b334a45a8ff 255 while ((!(MSC->STATUS & MSC_STATUS_WDATAREADY)) && (timeOut != 0))
bogdanm 0:9b334a45a8ff 256 {
bogdanm 0:9b334a45a8ff 257 timeOut--;
bogdanm 0:9b334a45a8ff 258 }
bogdanm 0:9b334a45a8ff 259 /* Check for timeout */
bogdanm 0:9b334a45a8ff 260 if (timeOut == 0)
bogdanm 0:9b334a45a8ff 261 {
bogdanm 0:9b334a45a8ff 262 return mscReturnTimeOut;
bogdanm 0:9b334a45a8ff 263 }
bogdanm 0:9b334a45a8ff 264 /* Clear double word option, in order to write the initial single word. */
bogdanm 0:9b334a45a8ff 265 MSC->WRITECTRL &= ~MSC_WRITECTRL_WDOUBLE;
bogdanm 0:9b334a45a8ff 266 /* Write first data word. */
bogdanm 0:9b334a45a8ff 267 MSC->WDATA = *data++;
bogdanm 0:9b334a45a8ff 268 MSC->WRITECMD = MSC_WRITECMD_WRITEONCE;
bogdanm 0:9b334a45a8ff 269
bogdanm 0:9b334a45a8ff 270 /* Wait for the operation to finish. It may be required to change the WDOUBLE
bogdanm 0:9b334a45a8ff 271 config after the initial write. It should not be changed while BUSY. */
bogdanm 0:9b334a45a8ff 272 timeOut = MSC_PROGRAM_TIMEOUT;
bogdanm 0:9b334a45a8ff 273 while((MSC->STATUS & MSC_STATUS_BUSY) && (timeOut != 0))
bogdanm 0:9b334a45a8ff 274 {
bogdanm 0:9b334a45a8ff 275 timeOut--;
bogdanm 0:9b334a45a8ff 276 }
bogdanm 0:9b334a45a8ff 277 /* Check for timeout */
bogdanm 0:9b334a45a8ff 278 if (timeOut == 0)
bogdanm 0:9b334a45a8ff 279 {
bogdanm 0:9b334a45a8ff 280 return mscReturnTimeOut;
bogdanm 0:9b334a45a8ff 281 }
bogdanm 0:9b334a45a8ff 282 /* Subtract this initial odd word for the write loop below */
bogdanm 0:9b334a45a8ff 283 numWords -= 1;
bogdanm 0:9b334a45a8ff 284 retval = mscReturnOk;
bogdanm 0:9b334a45a8ff 285 }
bogdanm 0:9b334a45a8ff 286 /* Now we can set the double word option in order to write two words per
bogdanm 0:9b334a45a8ff 287 data phase. */
bogdanm 0:9b334a45a8ff 288 MSC->WRITECTRL |= MSC_WRITECTRL_WDOUBLE;
bogdanm 0:9b334a45a8ff 289 wordsPerDataPhase = 2;
bogdanm 0:9b334a45a8ff 290 }
bogdanm 0:9b334a45a8ff 291 else
bogdanm 0:9b334a45a8ff 292 #endif /* defined( _MSC_WRITECTRL_LPWRITE_MASK ) && defined( _MSC_WRITECTRL_WDOUBLE_MASK ) */
bogdanm 0:9b334a45a8ff 293 {
bogdanm 0:9b334a45a8ff 294 wordsPerDataPhase = 1;
bogdanm 0:9b334a45a8ff 295 }
bogdanm 0:9b334a45a8ff 296
bogdanm 0:9b334a45a8ff 297 /* Write the rest as double word write if wordsPerDataPhase == 2 */
bogdanm 0:9b334a45a8ff 298 if (numWords > 0)
bogdanm 0:9b334a45a8ff 299 {
bogdanm 0:9b334a45a8ff 300 /**** Write strategy: mscWriteIntSafe ****/
bogdanm 0:9b334a45a8ff 301 if (writeStrategy == mscWriteIntSafe)
bogdanm 0:9b334a45a8ff 302 {
bogdanm 0:9b334a45a8ff 303 /* Requires a system core clock at 1MHz or higher */
bogdanm 0:9b334a45a8ff 304 EFM_ASSERT(SystemCoreClockGet() >= 1000000);
bogdanm 0:9b334a45a8ff 305 wordIndex = 0;
bogdanm 0:9b334a45a8ff 306 while(wordIndex < numWords)
bogdanm 0:9b334a45a8ff 307 {
bogdanm 0:9b334a45a8ff 308 MSC->WDATA = *data++;
bogdanm 0:9b334a45a8ff 309 wordIndex++;
bogdanm 0:9b334a45a8ff 310 if (wordsPerDataPhase == 2)
bogdanm 0:9b334a45a8ff 311 {
bogdanm 0:9b334a45a8ff 312 while (!(MSC->STATUS & MSC_STATUS_WDATAREADY));
bogdanm 0:9b334a45a8ff 313 MSC->WDATA = *data++;
bogdanm 0:9b334a45a8ff 314 wordIndex++;
bogdanm 0:9b334a45a8ff 315 }
bogdanm 0:9b334a45a8ff 316 MSC->WRITECMD = MSC_WRITECMD_WRITEONCE;
bogdanm 0:9b334a45a8ff 317
bogdanm 0:9b334a45a8ff 318 /* Wait for the transaction to finish. */
bogdanm 0:9b334a45a8ff 319 timeOut = MSC_PROGRAM_TIMEOUT;
bogdanm 0:9b334a45a8ff 320 while ((MSC->STATUS & MSC_STATUS_BUSY) && (timeOut != 0))
bogdanm 0:9b334a45a8ff 321 {
bogdanm 0:9b334a45a8ff 322 timeOut--;
bogdanm 0:9b334a45a8ff 323 }
bogdanm 0:9b334a45a8ff 324 /* Check for timeout */
bogdanm 0:9b334a45a8ff 325 if (timeOut == 0)
bogdanm 0:9b334a45a8ff 326 {
bogdanm 0:9b334a45a8ff 327 retval = mscReturnTimeOut;
bogdanm 0:9b334a45a8ff 328 break;
bogdanm 0:9b334a45a8ff 329 }
bogdanm 0:9b334a45a8ff 330 #if defined( _EFM32_GECKO_FAMILY )
bogdanm 0:9b334a45a8ff 331 MSC->ADDRB += 4;
bogdanm 0:9b334a45a8ff 332 MSC->WRITECMD = MSC_WRITECMD_LADDRIM;
bogdanm 0:9b334a45a8ff 333 #endif
bogdanm 0:9b334a45a8ff 334 }
bogdanm 0:9b334a45a8ff 335 }
bogdanm 0:9b334a45a8ff 336
bogdanm 0:9b334a45a8ff 337 /**** Write strategy: mscWriteFast ****/
bogdanm 0:9b334a45a8ff 338 else
bogdanm 0:9b334a45a8ff 339 {
bogdanm 0:9b334a45a8ff 340 #if defined( _EFM32_GECKO_FAMILY )
bogdanm 0:9b334a45a8ff 341 /* Gecko does not have auto-increment of ADDR. */
bogdanm 0:9b334a45a8ff 342 EFM_ASSERT(0);
bogdanm 0:9b334a45a8ff 343 #else
bogdanm 0:9b334a45a8ff 344 /* Requires a system core clock at 14MHz or higher */
bogdanm 0:9b334a45a8ff 345 EFM_ASSERT(SystemCoreClockGet() >= 14000000);
bogdanm 0:9b334a45a8ff 346
bogdanm 0:9b334a45a8ff 347 wordIndex = 0;
bogdanm 0:9b334a45a8ff 348 INT_Disable();
bogdanm 0:9b334a45a8ff 349 while(wordIndex < numWords)
bogdanm 0:9b334a45a8ff 350 {
bogdanm 0:9b334a45a8ff 351 /* Wait for the MSC to be ready for the next word. */
bogdanm 0:9b334a45a8ff 352 while (!(MSC->STATUS & MSC_STATUS_WDATAREADY))
bogdanm 0:9b334a45a8ff 353 {
bogdanm 0:9b334a45a8ff 354 /* If the write to MSC->WDATA below missed the 30us timeout and the
bogdanm 0:9b334a45a8ff 355 following MSC_WRITECMD_WRITETRIG command arrived while
bogdanm 0:9b334a45a8ff 356 MSC_STATUS_BUSY is 1, then the MSC_WRITECMD_WRITETRIG could be ignored by
bogdanm 0:9b334a45a8ff 357 the MSC. In this case, MSC_STATUS_WORDTIMEOUT is set to 1
bogdanm 0:9b334a45a8ff 358 and MSC_STATUS_BUSY is 0. A new trigger is therefore needed here to
bogdanm 0:9b334a45a8ff 359 complete write of data in MSC->WDATA.
bogdanm 0:9b334a45a8ff 360 If WDATAREADY became high since entry into this loop, exit and continue
bogdanm 0:9b334a45a8ff 361 to the next WDATA write.
bogdanm 0:9b334a45a8ff 362 */
bogdanm 0:9b334a45a8ff 363 if ((MSC->STATUS & (MSC_STATUS_WORDTIMEOUT | MSC_STATUS_BUSY | MSC_STATUS_WDATAREADY)) == MSC_STATUS_WORDTIMEOUT)
bogdanm 0:9b334a45a8ff 364 {
bogdanm 0:9b334a45a8ff 365 MSC->WRITECMD = MSC_WRITECMD_WRITETRIG;
bogdanm 0:9b334a45a8ff 366 }
bogdanm 0:9b334a45a8ff 367 }
bogdanm 0:9b334a45a8ff 368 MSC->WDATA = *data;
bogdanm 0:9b334a45a8ff 369 if ((wordsPerDataPhase == 1) || ((wordsPerDataPhase == 2) && (wordIndex & 0x1)))
bogdanm 0:9b334a45a8ff 370 {
bogdanm 0:9b334a45a8ff 371 MSC->WRITECMD = MSC_WRITECMD_WRITETRIG;
bogdanm 0:9b334a45a8ff 372 }
bogdanm 0:9b334a45a8ff 373 data++;
bogdanm 0:9b334a45a8ff 374 wordIndex++;
bogdanm 0:9b334a45a8ff 375 }
bogdanm 0:9b334a45a8ff 376 INT_Enable();
bogdanm 0:9b334a45a8ff 377
bogdanm 0:9b334a45a8ff 378 /* Wait for the transaction to finish. */
bogdanm 0:9b334a45a8ff 379 timeOut = MSC_PROGRAM_TIMEOUT;
bogdanm 0:9b334a45a8ff 380 while ((MSC->STATUS & MSC_STATUS_BUSY) && (timeOut != 0))
bogdanm 0:9b334a45a8ff 381 {
bogdanm 0:9b334a45a8ff 382 timeOut--;
bogdanm 0:9b334a45a8ff 383 }
bogdanm 0:9b334a45a8ff 384 /* Check for timeout */
bogdanm 0:9b334a45a8ff 385 if (timeOut == 0)
bogdanm 0:9b334a45a8ff 386 {
bogdanm 0:9b334a45a8ff 387 retval = mscReturnTimeOut;
bogdanm 0:9b334a45a8ff 388 }
bogdanm 0:9b334a45a8ff 389 #endif
bogdanm 0:9b334a45a8ff 390 } /* writeStrategy */
bogdanm 0:9b334a45a8ff 391 }
bogdanm 0:9b334a45a8ff 392
bogdanm 0:9b334a45a8ff 393 #if defined( _MSC_WRITECTRL_WDOUBLE_MASK )
bogdanm 0:9b334a45a8ff 394 /* Clear double word option, which should not be left on when returning. */
bogdanm 0:9b334a45a8ff 395 MSC->WRITECTRL &= ~MSC_WRITECTRL_WDOUBLE;
bogdanm 0:9b334a45a8ff 396 #endif
bogdanm 0:9b334a45a8ff 397
bogdanm 0:9b334a45a8ff 398 return retval;
bogdanm 0:9b334a45a8ff 399 }
bogdanm 0:9b334a45a8ff 400 #ifdef __ICCARM__
bogdanm 0:9b334a45a8ff 401 #pragma diag_default=Ta022
bogdanm 0:9b334a45a8ff 402 #pragma diag_default=Ta023
bogdanm 0:9b334a45a8ff 403 #endif
bogdanm 0:9b334a45a8ff 404 #ifdef __CC_ARM /* MDK-ARM compiler */
bogdanm 0:9b334a45a8ff 405 #pragma arm section code
bogdanm 0:9b334a45a8ff 406 #endif /* __CC_ARM */
bogdanm 0:9b334a45a8ff 407
bogdanm 0:9b334a45a8ff 408
bogdanm 0:9b334a45a8ff 409 /***************************************************************************//**
bogdanm 0:9b334a45a8ff 410 * @brief
bogdanm 0:9b334a45a8ff 411 * Internal flash write function with select write strategy parameter
bogdanm 0:9b334a45a8ff 412 * @param[in] address
bogdanm 0:9b334a45a8ff 413 * Write address
bogdanm 0:9b334a45a8ff 414 * @param[in] data
bogdanm 0:9b334a45a8ff 415 * Pointer to the first data word to load.
bogdanm 0:9b334a45a8ff 416 * @param[in] numWords
bogdanm 0:9b334a45a8ff 417 * Number of data words (32-bit) to load.
bogdanm 0:9b334a45a8ff 418 * @param[in] writeStrategy
bogdanm 0:9b334a45a8ff 419 * Write strategy to apply.
bogdanm 0:9b334a45a8ff 420 * @return
bogdanm 0:9b334a45a8ff 421 * Returns the status of the data load operation
bogdanm 0:9b334a45a8ff 422 ******************************************************************************/
bogdanm 0:9b334a45a8ff 423 #ifdef __CC_ARM /* MDK-ARM compiler */
bogdanm 0:9b334a45a8ff 424 #pragma arm section code="ram_code"
bogdanm 0:9b334a45a8ff 425 #endif /* __CC_ARM */
bogdanm 0:9b334a45a8ff 426 #ifdef __ICCARM__
bogdanm 0:9b334a45a8ff 427 /* Suppress warnings originating from use of EFM_ASSERT(): */
bogdanm 0:9b334a45a8ff 428 /* "Call to a non __ramfunc function from within a __ramfunc function" */
bogdanm 0:9b334a45a8ff 429 /* "Possible rom access from within a __ramfunc function" */
bogdanm 0:9b334a45a8ff 430 #pragma diag_suppress=Ta022
bogdanm 0:9b334a45a8ff 431 #pragma diag_suppress=Ta023
bogdanm 0:9b334a45a8ff 432 #endif
bogdanm 0:9b334a45a8ff 433 static MSC_Status_TypeDef MSC_WriteWordI(uint32_t *address,
bogdanm 0:9b334a45a8ff 434 void const *data,
bogdanm 0:9b334a45a8ff 435 uint32_t numBytes,
bogdanm 0:9b334a45a8ff 436 MSC_WriteStrategy_Typedef writeStrategy)
bogdanm 0:9b334a45a8ff 437 {
bogdanm 0:9b334a45a8ff 438 uint32_t wordCount;
bogdanm 0:9b334a45a8ff 439 uint32_t numWords;
bogdanm 0:9b334a45a8ff 440 uint32_t pageWords;
bogdanm 0:9b334a45a8ff 441 uint32_t* pData;
bogdanm 0:9b334a45a8ff 442 MSC_Status_TypeDef retval = mscReturnOk;
bogdanm 0:9b334a45a8ff 443
bogdanm 0:9b334a45a8ff 444 /* Check alignment (Must be aligned to words) */
bogdanm 0:9b334a45a8ff 445 EFM_ASSERT(((uint32_t) address & 0x3) == 0);
bogdanm 0:9b334a45a8ff 446
bogdanm 0:9b334a45a8ff 447 /* Check number of bytes. Must be divisable by four */
bogdanm 0:9b334a45a8ff 448 EFM_ASSERT((numBytes & 0x3) == 0);
bogdanm 0:9b334a45a8ff 449
bogdanm 0:9b334a45a8ff 450 /* Enable writing to the MSC */
bogdanm 0:9b334a45a8ff 451 MSC->WRITECTRL |= MSC_WRITECTRL_WREN;
bogdanm 0:9b334a45a8ff 452
bogdanm 0:9b334a45a8ff 453 /* Convert bytes to words */
bogdanm 0:9b334a45a8ff 454 numWords = numBytes >> 2;
bogdanm 0:9b334a45a8ff 455 EFM_ASSERT(numWords > 0);
bogdanm 0:9b334a45a8ff 456
bogdanm 0:9b334a45a8ff 457 /* The following loop splits the data into chunks corresponding to flash pages.
bogdanm 0:9b334a45a8ff 458 The address is loaded only once per page, because the hardware automatically
bogdanm 0:9b334a45a8ff 459 increments the address internally for each data load inside a page. */
bogdanm 0:9b334a45a8ff 460 for (wordCount = 0, pData = (uint32_t *)data; wordCount < numWords; )
bogdanm 0:9b334a45a8ff 461 {
bogdanm 0:9b334a45a8ff 462 /* First we load address. The address is auto-incremented within a page.
bogdanm 0:9b334a45a8ff 463 Therefore the address phase is only needed once for each page. */
bogdanm 0:9b334a45a8ff 464 retval = MSC_LoadVerifyAddress(address + wordCount);
bogdanm 0:9b334a45a8ff 465 if (mscReturnOk != retval)
bogdanm 0:9b334a45a8ff 466 {
bogdanm 0:9b334a45a8ff 467 return retval;
bogdanm 0:9b334a45a8ff 468 }
bogdanm 0:9b334a45a8ff 469 /* Compute the number of words to write to the current page. */
bogdanm 0:9b334a45a8ff 470 pageWords =
bogdanm 0:9b334a45a8ff 471 (FLASH_PAGE_SIZE -
bogdanm 0:9b334a45a8ff 472 (((uint32_t) (address + wordCount)) & (FLASH_PAGE_SIZE - 1)))
bogdanm 0:9b334a45a8ff 473 / sizeof(uint32_t);
bogdanm 0:9b334a45a8ff 474 if (pageWords > numWords - wordCount)
bogdanm 0:9b334a45a8ff 475 {
bogdanm 0:9b334a45a8ff 476 pageWords = numWords - wordCount;
bogdanm 0:9b334a45a8ff 477 }
bogdanm 0:9b334a45a8ff 478 /* Now write the data in the current page. */
bogdanm 0:9b334a45a8ff 479 retval = MSC_LoadWriteData(pData, pageWords, writeStrategy);
bogdanm 0:9b334a45a8ff 480 if (mscReturnOk != retval)
bogdanm 0:9b334a45a8ff 481 {
bogdanm 0:9b334a45a8ff 482 break;
bogdanm 0:9b334a45a8ff 483 }
bogdanm 0:9b334a45a8ff 484 wordCount += pageWords;
bogdanm 0:9b334a45a8ff 485 pData += pageWords;
bogdanm 0:9b334a45a8ff 486 }
bogdanm 0:9b334a45a8ff 487
bogdanm 0:9b334a45a8ff 488 /* Disable writing to the MSC */
bogdanm 0:9b334a45a8ff 489 MSC->WRITECTRL &= ~MSC_WRITECTRL_WREN;
bogdanm 0:9b334a45a8ff 490
bogdanm 0:9b334a45a8ff 491 #if defined( _MSC_WRITECTRL_WDOUBLE_MASK )
bogdanm 0:9b334a45a8ff 492 #if ( WORDS_PER_DATA_PHASE == 2 )
bogdanm 0:9b334a45a8ff 493 /* Turn off double word write cycle support. */
bogdanm 0:9b334a45a8ff 494 MSC->WRITECTRL &= ~MSC_WRITECTRL_WDOUBLE;
bogdanm 0:9b334a45a8ff 495 #endif
bogdanm 0:9b334a45a8ff 496 #endif
bogdanm 0:9b334a45a8ff 497
bogdanm 0:9b334a45a8ff 498 return retval;
bogdanm 0:9b334a45a8ff 499 }
bogdanm 0:9b334a45a8ff 500 #ifdef __ICCARM__
bogdanm 0:9b334a45a8ff 501 #pragma diag_default=Ta022
bogdanm 0:9b334a45a8ff 502 #pragma diag_default=Ta023
bogdanm 0:9b334a45a8ff 503 #endif
bogdanm 0:9b334a45a8ff 504 #ifdef __CC_ARM /* MDK-ARM compiler */
bogdanm 0:9b334a45a8ff 505 #pragma arm section code
bogdanm 0:9b334a45a8ff 506 #endif /* __CC_ARM */
bogdanm 0:9b334a45a8ff 507
bogdanm 0:9b334a45a8ff 508 /** @endcond */
bogdanm 0:9b334a45a8ff 509
bogdanm 0:9b334a45a8ff 510
bogdanm 0:9b334a45a8ff 511 /***************************************************************************//**
bogdanm 0:9b334a45a8ff 512 * @brief
bogdanm 0:9b334a45a8ff 513 * Erases a page in flash memory.
bogdanm 0:9b334a45a8ff 514 * @note
bogdanm 0:9b334a45a8ff 515 * It is recommended to run this code from RAM. On the Gecko family, it is required
bogdanm 0:9b334a45a8ff 516 * to run this function from RAM.
bogdanm 0:9b334a45a8ff 517 *
bogdanm 0:9b334a45a8ff 518 * For IAR, Rowley, SimplicityStudio, Atollic and armgcc this will be achieved
bogdanm 0:9b334a45a8ff 519 * automatically by using attributes in the function proctype. For Keil uVision you
bogdanm 0:9b334a45a8ff 520 * must define a section called "ram_code" and place this manually in your
bogdanm 0:9b334a45a8ff 521 * project's scatter file.
bogdanm 0:9b334a45a8ff 522 *
bogdanm 0:9b334a45a8ff 523 * @param[in] startAddress
bogdanm 0:9b334a45a8ff 524 * Pointer to the flash page to erase. Must be aligned to beginning of page
bogdanm 0:9b334a45a8ff 525 * boundary.
bogdanm 0:9b334a45a8ff 526 * @return
bogdanm 0:9b334a45a8ff 527 * Returns the status of erase operation, #MSC_Status_TypeDef
bogdanm 0:9b334a45a8ff 528 * @verbatim
bogdanm 0:9b334a45a8ff 529 * mscReturnOk - Operation completed successfully.
bogdanm 0:9b334a45a8ff 530 * mscReturnInvalidAddr - Operation tried to erase a non-flash area.
bogdanm 0:9b334a45a8ff 531 * mscReturnLocked - Operation tried to erase a locked area of the flash.
bogdanm 0:9b334a45a8ff 532 * mscReturnTimeOut - Operation timed out waiting for flash operation
bogdanm 0:9b334a45a8ff 533 * to complete.
bogdanm 0:9b334a45a8ff 534 * @endverbatim
bogdanm 0:9b334a45a8ff 535 ******************************************************************************/
bogdanm 0:9b334a45a8ff 536 #ifdef __CC_ARM /* MDK-ARM compiler */
bogdanm 0:9b334a45a8ff 537 #pragma arm section code="ram_code"
bogdanm 0:9b334a45a8ff 538 #endif /* __CC_ARM */
bogdanm 0:9b334a45a8ff 539 #ifdef __ICCARM__
bogdanm 0:9b334a45a8ff 540 /* Suppress warnings originating from use of EFM_ASSERT(): */
bogdanm 0:9b334a45a8ff 541 /* "Call to a non __ramfunc function from within a __ramfunc function" */
bogdanm 0:9b334a45a8ff 542 /* "Possible rom access from within a __ramfunc function" */
bogdanm 0:9b334a45a8ff 543 #pragma diag_suppress=Ta022
bogdanm 0:9b334a45a8ff 544 #pragma diag_suppress=Ta023
bogdanm 0:9b334a45a8ff 545 #endif
bogdanm 0:9b334a45a8ff 546 MSC_Status_TypeDef MSC_ErasePage(uint32_t *startAddress)
bogdanm 0:9b334a45a8ff 547 {
bogdanm 0:9b334a45a8ff 548 uint32_t timeOut = MSC_PROGRAM_TIMEOUT;
bogdanm 0:9b334a45a8ff 549
bogdanm 0:9b334a45a8ff 550 /* Address must be aligned to pages */
bogdanm 0:9b334a45a8ff 551 EFM_ASSERT((((uint32_t) startAddress) & (FLASH_PAGE_SIZE - 1)) == 0);
bogdanm 0:9b334a45a8ff 552
bogdanm 0:9b334a45a8ff 553 /* Enable writing to the MSC */
bogdanm 0:9b334a45a8ff 554 MSC->WRITECTRL |= MSC_WRITECTRL_WREN;
bogdanm 0:9b334a45a8ff 555
bogdanm 0:9b334a45a8ff 556 /* Load address */
bogdanm 0:9b334a45a8ff 557 MSC->ADDRB = (uint32_t)startAddress;
bogdanm 0:9b334a45a8ff 558 MSC->WRITECMD = MSC_WRITECMD_LADDRIM;
bogdanm 0:9b334a45a8ff 559
bogdanm 0:9b334a45a8ff 560 /* Check for invalid address */
bogdanm 0:9b334a45a8ff 561 if (MSC->STATUS & MSC_STATUS_INVADDR)
bogdanm 0:9b334a45a8ff 562 {
bogdanm 0:9b334a45a8ff 563 /* Disable writing to the MSC */
bogdanm 0:9b334a45a8ff 564 MSC->WRITECTRL &= ~MSC_WRITECTRL_WREN;
bogdanm 0:9b334a45a8ff 565 return mscReturnInvalidAddr;
bogdanm 0:9b334a45a8ff 566 }
bogdanm 0:9b334a45a8ff 567 /* Check for write protected page */
bogdanm 0:9b334a45a8ff 568 if (MSC->STATUS & MSC_STATUS_LOCKED)
bogdanm 0:9b334a45a8ff 569 {
bogdanm 0:9b334a45a8ff 570 /* Disable writing to the MSC */
bogdanm 0:9b334a45a8ff 571 MSC->WRITECTRL &= ~MSC_WRITECTRL_WREN;
bogdanm 0:9b334a45a8ff 572 return mscReturnLocked;
bogdanm 0:9b334a45a8ff 573 }
bogdanm 0:9b334a45a8ff 574 /* Send erase page command */
bogdanm 0:9b334a45a8ff 575 MSC->WRITECMD = MSC_WRITECMD_ERASEPAGE;
bogdanm 0:9b334a45a8ff 576
bogdanm 0:9b334a45a8ff 577 /* Wait for the erase to complete */
bogdanm 0:9b334a45a8ff 578 while ((MSC->STATUS & MSC_STATUS_BUSY) && (timeOut != 0))
bogdanm 0:9b334a45a8ff 579 {
bogdanm 0:9b334a45a8ff 580 timeOut--;
bogdanm 0:9b334a45a8ff 581 }
bogdanm 0:9b334a45a8ff 582 if (timeOut == 0)
bogdanm 0:9b334a45a8ff 583 {
bogdanm 0:9b334a45a8ff 584 /* Disable writing to the MSC */
bogdanm 0:9b334a45a8ff 585 MSC->WRITECTRL &= ~MSC_WRITECTRL_WREN;
bogdanm 0:9b334a45a8ff 586 return mscReturnTimeOut;
bogdanm 0:9b334a45a8ff 587 }
bogdanm 0:9b334a45a8ff 588 /* Disable writing to the MSC */
bogdanm 0:9b334a45a8ff 589 MSC->WRITECTRL &= ~MSC_WRITECTRL_WREN;
bogdanm 0:9b334a45a8ff 590 return mscReturnOk;
bogdanm 0:9b334a45a8ff 591 }
bogdanm 0:9b334a45a8ff 592 #ifdef __ICCARM__
bogdanm 0:9b334a45a8ff 593 #pragma diag_default=Ta022
bogdanm 0:9b334a45a8ff 594 #pragma diag_default=Ta023
bogdanm 0:9b334a45a8ff 595 #endif
bogdanm 0:9b334a45a8ff 596 #ifdef __CC_ARM /* MDK-ARM compiler */
bogdanm 0:9b334a45a8ff 597 #pragma arm section code
bogdanm 0:9b334a45a8ff 598 #endif /* __CC_ARM */
bogdanm 0:9b334a45a8ff 599
bogdanm 0:9b334a45a8ff 600
bogdanm 0:9b334a45a8ff 601 /***************************************************************************//**
bogdanm 0:9b334a45a8ff 602 * @brief
bogdanm 0:9b334a45a8ff 603 * Writes data to flash memory. This function is interrupt safe, but slower than
bogdanm 0:9b334a45a8ff 604 * MSC_WriteWordFast(), which writes to flash with interrupts disabled.
bogdanm 0:9b334a45a8ff 605 * Write data must be aligned to words and contain a number of bytes that is
bogdanm 0:9b334a45a8ff 606 * divisable by four.
bogdanm 0:9b334a45a8ff 607 * @note
bogdanm 0:9b334a45a8ff 608 * It is recommended to erase the flash page before performing a write.
bogdanm 0:9b334a45a8ff 609 *
bogdanm 0:9b334a45a8ff 610 * It is recommended to run this code from RAM. On the Gecko family, it is required
bogdanm 0:9b334a45a8ff 611 * to run this function from RAM.
bogdanm 0:9b334a45a8ff 612 *
bogdanm 0:9b334a45a8ff 613 * For IAR, Rowley, SimplicityStudio, Atollic and armgcc this will be achieved
bogdanm 0:9b334a45a8ff 614 * automatically by using attributes in the function proctype. For Keil uVision you
bogdanm 0:9b334a45a8ff 615 * must define a section called "ram_code" and place this manually in your
bogdanm 0:9b334a45a8ff 616 * project's scatter file.
bogdanm 0:9b334a45a8ff 617 *
bogdanm 0:9b334a45a8ff 618 * This function requires a ystem core clock at 1MHz or higher.
bogdanm 0:9b334a45a8ff 619 *
bogdanm 0:9b334a45a8ff 620 * @param[in] address
bogdanm 0:9b334a45a8ff 621 * Pointer to the flash word to write to. Must be aligned to words.
bogdanm 0:9b334a45a8ff 622 * @param[in] data
bogdanm 0:9b334a45a8ff 623 * Data to write to flash.
bogdanm 0:9b334a45a8ff 624 * @param[in] numBytes
bogdanm 0:9b334a45a8ff 625 * Number of bytes to write from flash. NB: Must be divisable by four.
bogdanm 0:9b334a45a8ff 626 * @return
bogdanm 0:9b334a45a8ff 627 * Returns the status of the write operation
bogdanm 0:9b334a45a8ff 628 * @verbatim
bogdanm 0:9b334a45a8ff 629 * flashReturnOk - Operation completed successfully.
bogdanm 0:9b334a45a8ff 630 * flashReturnInvalidAddr - Operation tried to erase a non-flash area.
bogdanm 0:9b334a45a8ff 631 * flashReturnLocked - Operation tried to erase a locked area of the flash.
bogdanm 0:9b334a45a8ff 632 * flashReturnTimeOut - Operation timed out waiting for flash operation
bogdanm 0:9b334a45a8ff 633 * to complete. Or the MSC timed out waiting for the software to write
bogdanm 0:9b334a45a8ff 634 * the next word into the DWORD register.
bogdanm 0:9b334a45a8ff 635 * @endverbatim
bogdanm 0:9b334a45a8ff 636 ******************************************************************************/
bogdanm 0:9b334a45a8ff 637 #ifdef __CC_ARM /* MDK-ARM compiler */
bogdanm 0:9b334a45a8ff 638 #pragma arm section code="ram_code"
bogdanm 0:9b334a45a8ff 639 #endif /* __CC_ARM */
bogdanm 0:9b334a45a8ff 640 #ifdef __ICCARM__
bogdanm 0:9b334a45a8ff 641 /* Suppress warnings originating from use of EFM_ASSERT(): */
bogdanm 0:9b334a45a8ff 642 /* "Call to a non __ramfunc function from within a __ramfunc function" */
bogdanm 0:9b334a45a8ff 643 /* "Possible rom access from within a __ramfunc function" */
bogdanm 0:9b334a45a8ff 644 #pragma diag_suppress=Ta022
bogdanm 0:9b334a45a8ff 645 #pragma diag_suppress=Ta023
bogdanm 0:9b334a45a8ff 646 #endif
bogdanm 0:9b334a45a8ff 647 MSC_Status_TypeDef MSC_WriteWord(uint32_t *address,
bogdanm 0:9b334a45a8ff 648 void const *data,
bogdanm 0:9b334a45a8ff 649 uint32_t numBytes)
bogdanm 0:9b334a45a8ff 650 {
bogdanm 0:9b334a45a8ff 651 return MSC_WriteWordI(address, data, numBytes, mscWriteIntSafe);
bogdanm 0:9b334a45a8ff 652 }
bogdanm 0:9b334a45a8ff 653 #ifdef __ICCARM__
bogdanm 0:9b334a45a8ff 654 #pragma diag_default=Ta022
bogdanm 0:9b334a45a8ff 655 #pragma diag_default=Ta023
bogdanm 0:9b334a45a8ff 656 #endif
bogdanm 0:9b334a45a8ff 657 #ifdef __CC_ARM /* MDK-ARM compiler */
bogdanm 0:9b334a45a8ff 658 #pragma arm section code
bogdanm 0:9b334a45a8ff 659 #endif /* __CC_ARM */
bogdanm 0:9b334a45a8ff 660
bogdanm 0:9b334a45a8ff 661
bogdanm 0:9b334a45a8ff 662 #if !defined( _EFM32_GECKO_FAMILY )
bogdanm 0:9b334a45a8ff 663 /***************************************************************************//**
bogdanm 0:9b334a45a8ff 664 * @brief
bogdanm 0:9b334a45a8ff 665 * Writes data to flash memory. This function is faster than MSC_WriteWord(),
bogdanm 0:9b334a45a8ff 666 * but it disables interrupts. Write data must be aligned to words and contain
bogdanm 0:9b334a45a8ff 667 * a number of bytes that is divisable by four.
bogdanm 0:9b334a45a8ff 668 * @note
bogdanm 0:9b334a45a8ff 669 * It is recommended to erase the flash page before performing a write.
bogdanm 0:9b334a45a8ff 670
bogdanm 0:9b334a45a8ff 671 * It is recommended to run this code from RAM. On the Gecko family, it is required
bogdanm 0:9b334a45a8ff 672 * to run this function from RAM.
bogdanm 0:9b334a45a8ff 673 *
bogdanm 0:9b334a45a8ff 674 * For IAR, Rowley, SimplicityStudio, Atollic and armgcc this will be achieved
bogdanm 0:9b334a45a8ff 675 * automatically by using attributes in the function proctype. For Keil uVision you
bogdanm 0:9b334a45a8ff 676 * must define a section called "ram_code" and place this manually in your
bogdanm 0:9b334a45a8ff 677 * project's scatter file.
bogdanm 0:9b334a45a8ff 678 *
bogdanm 0:9b334a45a8ff 679 * @param[in] address
bogdanm 0:9b334a45a8ff 680 * Pointer to the flash word to write to. Must be aligned to words.
bogdanm 0:9b334a45a8ff 681 * @param[in] data
bogdanm 0:9b334a45a8ff 682 * Data to write to flash.
bogdanm 0:9b334a45a8ff 683 * @param[in] numBytes
bogdanm 0:9b334a45a8ff 684 * Number of bytes to write from flash. NB: Must be divisable by four.
bogdanm 0:9b334a45a8ff 685 * @return
bogdanm 0:9b334a45a8ff 686 * Returns the status of the write operation
bogdanm 0:9b334a45a8ff 687 * @verbatim
bogdanm 0:9b334a45a8ff 688 * flashReturnOk - Operation completed successfully.
bogdanm 0:9b334a45a8ff 689 * flashReturnInvalidAddr - Operation tried to erase a non-flash area.
bogdanm 0:9b334a45a8ff 690 * flashReturnLocked - Operation tried to erase a locked area of the flash.
bogdanm 0:9b334a45a8ff 691 * flashReturnTimeOut - Operation timed out waiting for flash operation
bogdanm 0:9b334a45a8ff 692 * to complete. Or the MSC timed out waiting for the software to write
bogdanm 0:9b334a45a8ff 693 * the next word into the DWORD register.
bogdanm 0:9b334a45a8ff 694 * @endverbatim
bogdanm 0:9b334a45a8ff 695 ******************************************************************************/
bogdanm 0:9b334a45a8ff 696 #ifdef __CC_ARM /* MDK-ARM compiler */
bogdanm 0:9b334a45a8ff 697 #pragma arm section code="ram_code"
bogdanm 0:9b334a45a8ff 698 #endif /* __CC_ARM */
bogdanm 0:9b334a45a8ff 699 #ifdef __ICCARM__
bogdanm 0:9b334a45a8ff 700 /* Suppress warnings originating from use of EFM_ASSERT(): */
bogdanm 0:9b334a45a8ff 701 /* "Call to a non __ramfunc function from within a __ramfunc function" */
bogdanm 0:9b334a45a8ff 702 /* "Possible rom access from within a __ramfunc function" */
bogdanm 0:9b334a45a8ff 703 #pragma diag_suppress=Ta022
bogdanm 0:9b334a45a8ff 704 #pragma diag_suppress=Ta023
bogdanm 0:9b334a45a8ff 705 #endif
bogdanm 0:9b334a45a8ff 706 MSC_Status_TypeDef MSC_WriteWordFast(uint32_t *address,
bogdanm 0:9b334a45a8ff 707 void const *data,
bogdanm 0:9b334a45a8ff 708 uint32_t numBytes)
bogdanm 0:9b334a45a8ff 709 {
bogdanm 0:9b334a45a8ff 710 return MSC_WriteWordI(address, data, numBytes, mscWriteFast);
bogdanm 0:9b334a45a8ff 711 }
bogdanm 0:9b334a45a8ff 712 #ifdef __ICCARM__
bogdanm 0:9b334a45a8ff 713 #pragma diag_default=Ta022
bogdanm 0:9b334a45a8ff 714 #pragma diag_default=Ta023
bogdanm 0:9b334a45a8ff 715 #endif
bogdanm 0:9b334a45a8ff 716 #ifdef __CC_ARM /* MDK-ARM compiler */
bogdanm 0:9b334a45a8ff 717 #pragma arm section code
bogdanm 0:9b334a45a8ff 718 #endif /* __CC_ARM */
bogdanm 0:9b334a45a8ff 719 #endif
bogdanm 0:9b334a45a8ff 720
bogdanm 0:9b334a45a8ff 721
bogdanm 0:9b334a45a8ff 722 #if defined( _MSC_MASSLOCK_MASK )
bogdanm 0:9b334a45a8ff 723 /***************************************************************************//**
bogdanm 0:9b334a45a8ff 724 * @brief
bogdanm 0:9b334a45a8ff 725 * Erase entire flash in one operation
bogdanm 0:9b334a45a8ff 726 * @note
bogdanm 0:9b334a45a8ff 727 * This command will erase the entire contents of the device.
bogdanm 0:9b334a45a8ff 728 * Use with care, both a debug session and all contents of the flash will be
bogdanm 0:9b334a45a8ff 729 * lost. The lock bit, MLW will prevent this operation from executing and
bogdanm 0:9b334a45a8ff 730 * might prevent successful mass erase.
bogdanm 0:9b334a45a8ff 731 ******************************************************************************/
bogdanm 0:9b334a45a8ff 732 #ifdef __CC_ARM /* MDK-ARM compiler */
bogdanm 0:9b334a45a8ff 733 #pragma arm section code="ram_code"
bogdanm 0:9b334a45a8ff 734 #endif /* __CC_ARM */
bogdanm 0:9b334a45a8ff 735 MSC_Status_TypeDef MSC_MassErase(void)
bogdanm 0:9b334a45a8ff 736 {
bogdanm 0:9b334a45a8ff 737 /* Enable writing to the MSC */
bogdanm 0:9b334a45a8ff 738 MSC->WRITECTRL |= MSC_WRITECTRL_WREN;
bogdanm 0:9b334a45a8ff 739
bogdanm 0:9b334a45a8ff 740 /* Unlock device mass erase */
bogdanm 0:9b334a45a8ff 741 MSC->MASSLOCK = MSC_MASSLOCK_LOCKKEY_UNLOCK;
bogdanm 0:9b334a45a8ff 742
bogdanm 0:9b334a45a8ff 743 /* Erase first 512K block */
bogdanm 0:9b334a45a8ff 744 MSC->WRITECMD = MSC_WRITECMD_ERASEMAIN0;
bogdanm 0:9b334a45a8ff 745
bogdanm 0:9b334a45a8ff 746 /* Waiting for erase to complete */
bogdanm 0:9b334a45a8ff 747 while ((MSC->STATUS & MSC_STATUS_BUSY));
bogdanm 0:9b334a45a8ff 748
bogdanm 0:9b334a45a8ff 749 #if (FLASH_SIZE >= (512 * 1024))
bogdanm 0:9b334a45a8ff 750 /* Erase second 512K block */
bogdanm 0:9b334a45a8ff 751 MSC->WRITECMD = MSC_WRITECMD_ERASEMAIN1;
bogdanm 0:9b334a45a8ff 752
bogdanm 0:9b334a45a8ff 753 /* Waiting for erase to complete */
bogdanm 0:9b334a45a8ff 754 while ((MSC->STATUS & MSC_STATUS_BUSY));
bogdanm 0:9b334a45a8ff 755 #endif
bogdanm 0:9b334a45a8ff 756
bogdanm 0:9b334a45a8ff 757 /* Restore mass erase lock */
bogdanm 0:9b334a45a8ff 758 MSC->MASSLOCK = MSC_MASSLOCK_LOCKKEY_LOCK;
bogdanm 0:9b334a45a8ff 759
bogdanm 0:9b334a45a8ff 760 /* This will only successfully return if calling function is also in SRAM */
bogdanm 0:9b334a45a8ff 761 return mscReturnOk;
bogdanm 0:9b334a45a8ff 762 }
bogdanm 0:9b334a45a8ff 763 #ifdef __CC_ARM /* MDK-ARM compiler */
bogdanm 0:9b334a45a8ff 764 #pragma arm section code
bogdanm 0:9b334a45a8ff 765 #endif /* __CC_ARM */
bogdanm 0:9b334a45a8ff 766 #endif
bogdanm 0:9b334a45a8ff 767
bogdanm 0:9b334a45a8ff 768 /** @} (end addtogroup MSC) */
bogdanm 0:9b334a45a8ff 769 /** @} (end addtogroup EM_Library) */
bogdanm 0:9b334a45a8ff 770 #endif /* defined(MSC_COUNT) && (MSC_COUNT > 0) */