added prescaler for 16 bit pwm in LPC1347 target

Fork of mbed-dev by mbed official

Committer:
mbed_official
Date:
Fri Jan 15 07:45:16 2016 +0000
Revision:
50:a417edff4437
Parent:
0:9b334a45a8ff
Child:
144:ef7eb2e8f9f7
Synchronized with git revision 6010f32619bfcbb01cc73747d4ff9040863482d9

Full URL: https://github.com/mbedmicro/mbed/commit/6010f32619bfcbb01cc73747d4ff9040863482d9/

Remove doubling of buffer size in realiseEndpoint()

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