added prescaler for 16 bit pwm in LPC1347 target

Fork of mbed-dev by mbed official

Committer:
JojoS
Date:
Sat Sep 10 15:32:04 2016 +0000
Revision:
147:ba84b7dc41a7
Parent:
144:ef7eb2e8f9f7
added prescaler for 16 bit timers (solution as in LPC11xx), default prescaler 31 for max 28 ms period time

Who changed what in which revision?

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