em_msc.c
Go to the documentation of this file.00001
00033 #include "em_msc.h"
00034 #if defined( MSC_COUNT ) && ( MSC_COUNT > 0 )
00035
00036 #include "em_system.h"
00037 #if defined( _MSC_TIMEBASE_MASK )
00038 #include "em_cmu.h"
00039 #include "em_int.h"
00040 #endif
00041 #include "em_assert.h"
00042
00045 #if defined( MSC_WRITECTRL_WDOUBLE )
00046 #define WORDS_PER_DATA_PHASE (FLASH_SIZE < (512 * 1024) ? 1 : 2)
00047 #else
00048 #define WORDS_PER_DATA_PHASE (1)
00049 #endif
00050
00051 typedef enum {
00052 mscWriteIntSafe,
00053 mscWriteFast,
00054 } MSC_WriteStrategy_Typedef;
00055
00056 #ifdef __ICCARM__
00057 __ramfunc static MSC_Status_TypeDef MSC_WriteWordI(uint32_t *address,
00058 void const *data,
00059 uint32_t numBytes,
00060 MSC_WriteStrategy_Typedef writeStrategy);
00061 __ramfunc __STATIC_INLINE MSC_Status_TypeDef MSC_LoadWriteData(uint32_t* data,
00062 uint32_t numWords,
00063 MSC_WriteStrategy_Typedef writeStrategy);
00064 __ramfunc __STATIC_INLINE MSC_Status_TypeDef MSC_LoadVerifyAddress(uint32_t* address);
00065 #endif
00066 #ifdef __GNUC__
00067 #ifdef __CROSSWORKS_ARM
00068 static MSC_Status_TypeDef MSC_WriteWordI(uint32_t *address,
00069 void const *data,
00070 uint32_t numBytes,
00071 MSC_WriteStrategy_Typedef writeStrategy) __attribute__ ((section(".fast")));
00072 __STATIC_INLINE MSC_Status_TypeDef MSC_LoadWriteData(uint32_t* data,
00073 uint32_t numWords,
00074 MSC_WriteStrategy_Typedef writeStrategy) __attribute__ ((section(".fast")));
00075 __STATIC_INLINE MSC_Status_TypeDef MSC_LoadVerifyAddress(uint32_t* address) __attribute__ ((section(".fast")));
00076 #else
00077 static MSC_Status_TypeDef MSC_WriteWordI(uint32_t *address,
00078 void const *data,
00079 uint32_t numBytes,
00080 MSC_WriteStrategy_Typedef writeStrategy) __attribute__ ((section(".ram")));
00081 __STATIC_INLINE MSC_Status_TypeDef MSC_LoadWriteData(uint32_t* data,
00082 uint32_t numWords,
00083 MSC_WriteStrategy_Typedef writeStrategy) __attribute__ ((section(".ram")));
00084 __STATIC_INLINE MSC_Status_TypeDef MSC_LoadVerifyAddress(uint32_t* address) __attribute__ ((section(".ram")));
00085 #endif
00086 #endif
00087
00090
00095
00101
00102
00103
00104
00105
00119 void MSC_Init(void)
00120 {
00121 #if defined( _MSC_TIMEBASE_MASK )
00122 uint32_t freq, cycles;
00123 #endif
00124
00125 MSC->LOCK = MSC_UNLOCK_CODE;
00126
00127 MSC->WRITECTRL &= ~MSC_WRITECTRL_WREN;
00128
00129
00130
00131
00132
00133
00134 SystemCoreClockGet();
00135
00136 #if defined( _MSC_TIMEBASE_MASK )
00137
00138 freq = CMU_ClockFreqGet(cmuClock_AUX);
00139
00140 if (freq > 7000000)
00141 {
00142
00143 freq = (freq * 11) / 10;
00144 cycles = (freq / 1000000) + 1;
00145
00146
00147 MSC->TIMEBASE = (MSC->TIMEBASE & ~(_MSC_TIMEBASE_BASE_MASK |
00148 _MSC_TIMEBASE_PERIOD_MASK)) |
00149 MSC_TIMEBASE_PERIOD_1US |
00150 (cycles << _MSC_TIMEBASE_BASE_SHIFT);
00151 }
00152 else
00153 {
00154
00155 freq = (freq * 5 * 11) / 10;
00156 cycles = (freq / 1000000) + 1;
00157
00158
00159 MSC->TIMEBASE = (MSC->TIMEBASE & ~(_MSC_TIMEBASE_BASE_MASK |
00160 _MSC_TIMEBASE_PERIOD_MASK)) |
00161 MSC_TIMEBASE_PERIOD_5US |
00162 (cycles << _MSC_TIMEBASE_BASE_SHIFT);
00163 }
00164 #endif
00165 }
00166
00167
00171 void MSC_Deinit(void)
00172 {
00173
00174 MSC->WRITECTRL &= ~MSC_WRITECTRL_WREN;
00175
00176 MSC->LOCK = 0;
00177 }
00178
00181
00198 #ifdef __CC_ARM
00199 #pragma arm section code="ram_code"
00200 #endif
00201 #ifdef __ICCARM__
00202
00203
00204
00205 #pragma diag_suppress=Ta022
00206 #pragma diag_suppress=Ta023
00207 __ramfunc
00208 #endif
00209 __STATIC_INLINE MSC_Status_TypeDef MSC_LoadVerifyAddress(uint32_t* address)
00210 {
00211 uint32_t status;
00212 uint32_t timeOut;
00213
00214
00215 timeOut = MSC_PROGRAM_TIMEOUT;
00216 while ((MSC->STATUS & MSC_STATUS_BUSY) && (timeOut != 0))
00217 {
00218 timeOut--;
00219 }
00220
00221
00222 if (timeOut == 0)
00223 {
00224 return mscReturnTimeOut;
00225 }
00226
00227 MSC->ADDRB = (uint32_t)address;
00228 MSC->WRITECMD = MSC_WRITECMD_LADDRIM;
00229
00230 status = MSC->STATUS;
00231 if (status & (MSC_STATUS_INVADDR | MSC_STATUS_LOCKED))
00232 {
00233
00234 if (status & MSC_STATUS_INVADDR)
00235 return mscReturnInvalidAddr;
00236
00237 if (status & MSC_STATUS_LOCKED)
00238 return mscReturnLocked;
00239 }
00240 return mscReturnOk;
00241 }
00242 #ifdef __ICCARM__
00243 #pragma diag_default=Ta022
00244 #pragma diag_default=Ta023
00245 #endif
00246 #ifdef __CC_ARM
00247 #pragma arm section code
00248 #endif
00249
00250
00251
00271 #ifdef __CC_ARM
00272 #pragma arm section code="ram_code"
00273 #endif
00274 #ifdef __ICCARM__
00275
00276
00277
00278 #pragma diag_suppress=Ta022
00279 #pragma diag_suppress=Ta023
00280 __ramfunc
00281 #endif
00282 __STATIC_INLINE MSC_Status_TypeDef MSC_LoadWriteData(uint32_t* data,
00283 uint32_t numWords,
00284 MSC_WriteStrategy_Typedef writeStrategy)
00285 {
00286 uint32_t timeOut;
00287 uint32_t wordIndex;
00288 uint32_t wordsPerDataPhase;
00289 MSC_Status_TypeDef retval = mscReturnOk;
00290
00291 #if defined( _MSC_WRITECTRL_LPWRITE_MASK ) && defined( _MSC_WRITECTRL_WDOUBLE_MASK )
00292
00293 if (!(MSC->WRITECTRL & MSC_WRITECTRL_LPWRITE))
00294 {
00295
00296
00297 if (numWords & 0x1)
00298 {
00299
00300 timeOut = MSC_PROGRAM_TIMEOUT;
00301 while ((!(MSC->STATUS & MSC_STATUS_WDATAREADY)) && (timeOut != 0))
00302 {
00303 timeOut--;
00304 }
00305
00306 if (timeOut == 0)
00307 {
00308 return mscReturnTimeOut;
00309 }
00310
00311 MSC->WRITECTRL &= ~MSC_WRITECTRL_WDOUBLE;
00312
00313 MSC->WDATA = *data++;
00314 MSC->WRITECMD = MSC_WRITECMD_WRITEONCE;
00315
00316
00317
00318 timeOut = MSC_PROGRAM_TIMEOUT;
00319 while((MSC->STATUS & MSC_STATUS_BUSY) && (timeOut != 0))
00320 {
00321 timeOut--;
00322 }
00323
00324 if (timeOut == 0)
00325 {
00326 return mscReturnTimeOut;
00327 }
00328
00329 numWords -= 1;
00330 retval = mscReturnOk;
00331 }
00332
00333
00334 MSC->WRITECTRL |= MSC_WRITECTRL_WDOUBLE;
00335 wordsPerDataPhase = 2;
00336 }
00337 else
00338 #endif
00339 {
00340 wordsPerDataPhase = 1;
00341 }
00342
00343
00344 if (numWords > 0)
00345 {
00346
00347 if (writeStrategy == mscWriteIntSafe)
00348 {
00349
00350 EFM_ASSERT(SystemCoreClock >= 1000000);
00351 wordIndex = 0;
00352 while(wordIndex < numWords)
00353 {
00354 MSC->WDATA = *data++;
00355 wordIndex++;
00356 if (wordsPerDataPhase == 2)
00357 {
00358 while (!(MSC->STATUS & MSC_STATUS_WDATAREADY));
00359 MSC->WDATA = *data++;
00360 wordIndex++;
00361 }
00362 MSC->WRITECMD = MSC_WRITECMD_WRITEONCE;
00363
00364
00365 timeOut = MSC_PROGRAM_TIMEOUT;
00366 while ((MSC->STATUS & MSC_STATUS_BUSY) && (timeOut != 0))
00367 {
00368 timeOut--;
00369 }
00370
00371 if (timeOut == 0)
00372 {
00373 retval = mscReturnTimeOut;
00374 break;
00375 }
00376 #if defined( _EFM32_GECKO_FAMILY )
00377 MSC->ADDRB += 4;
00378 MSC->WRITECMD = MSC_WRITECMD_LADDRIM;
00379 #endif
00380 }
00381 }
00382
00383
00384 else
00385 {
00386 #if defined( _EFM32_GECKO_FAMILY )
00387
00388 EFM_ASSERT(0);
00389 #else
00390
00391 EFM_ASSERT(SystemCoreClock >= 14000000);
00392
00393 wordIndex = 0;
00394 INT_Disable();
00395 while(wordIndex < numWords)
00396 {
00397
00398 while (!(MSC->STATUS & MSC_STATUS_WDATAREADY))
00399 {
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409 if ((MSC->STATUS & (MSC_STATUS_WORDTIMEOUT | MSC_STATUS_BUSY | MSC_STATUS_WDATAREADY)) == MSC_STATUS_WORDTIMEOUT)
00410 {
00411 MSC->WRITECMD = MSC_WRITECMD_WRITETRIG;
00412 }
00413 }
00414 MSC->WDATA = *data;
00415 if ((wordsPerDataPhase == 1) || ((wordsPerDataPhase == 2) && (wordIndex & 0x1)))
00416 {
00417 MSC->WRITECMD = MSC_WRITECMD_WRITETRIG;
00418 }
00419 data++;
00420 wordIndex++;
00421 }
00422 INT_Enable();
00423
00424
00425 timeOut = MSC_PROGRAM_TIMEOUT;
00426 while ((MSC->STATUS & MSC_STATUS_BUSY) && (timeOut != 0))
00427 {
00428 timeOut--;
00429 }
00430
00431 if (timeOut == 0)
00432 {
00433 retval = mscReturnTimeOut;
00434 }
00435 #endif
00436 }
00437 }
00438
00439 #if defined( _MSC_WRITECTRL_WDOUBLE_MASK )
00440
00441 MSC->WRITECTRL &= ~MSC_WRITECTRL_WDOUBLE;
00442 #endif
00443
00444 return retval;
00445 }
00446 #ifdef __ICCARM__
00447 #pragma diag_default=Ta022
00448 #pragma diag_default=Ta023
00449 #endif
00450 #ifdef __CC_ARM
00451 #pragma arm section code
00452 #endif
00453
00454
00455
00469 #ifdef __CC_ARM
00470 #pragma arm section code="ram_code"
00471 #endif
00472 #ifdef __ICCARM__
00473
00474
00475
00476 #pragma diag_suppress=Ta022
00477 #pragma diag_suppress=Ta023
00478 #endif
00479 static MSC_Status_TypeDef MSC_WriteWordI(uint32_t *address,
00480 void const *data,
00481 uint32_t numBytes,
00482 MSC_WriteStrategy_Typedef writeStrategy)
00483 {
00484 uint32_t wordCount;
00485 uint32_t numWords;
00486 uint32_t pageWords;
00487 uint32_t* pData;
00488 MSC_Status_TypeDef retval = mscReturnOk;
00489
00490
00491 EFM_ASSERT(((uint32_t) address & 0x3) == 0);
00492
00493
00494 EFM_ASSERT((numBytes & 0x3) == 0);
00495
00496
00497 MSC->WRITECTRL |= MSC_WRITECTRL_WREN;
00498
00499
00500 numWords = numBytes >> 2;
00501 EFM_ASSERT(numWords > 0);
00502
00503
00504
00505
00506 for (wordCount = 0, pData = (uint32_t *)data; wordCount < numWords; )
00507 {
00508
00509
00510 retval = MSC_LoadVerifyAddress(address + wordCount);
00511 if (mscReturnOk != retval)
00512 {
00513 return retval;
00514 }
00515
00516 pageWords =
00517 (FLASH_PAGE_SIZE -
00518 (((uint32_t) (address + wordCount)) & (FLASH_PAGE_SIZE - 1)))
00519 / sizeof(uint32_t);
00520 if (pageWords > numWords - wordCount)
00521 {
00522 pageWords = numWords - wordCount;
00523 }
00524
00525 retval = MSC_LoadWriteData(pData, pageWords, writeStrategy);
00526 if (mscReturnOk != retval)
00527 {
00528 break;
00529 }
00530 wordCount += pageWords;
00531 pData += pageWords;
00532 }
00533
00534
00535 MSC->WRITECTRL &= ~MSC_WRITECTRL_WREN;
00536
00537 #if defined( _MSC_WRITECTRL_WDOUBLE_MASK )
00538 #if ( WORDS_PER_DATA_PHASE == 2 )
00539
00540 MSC->WRITECTRL &= ~MSC_WRITECTRL_WDOUBLE;
00541 #endif
00542 #endif
00543
00544 return retval;
00545 }
00546 #ifdef __ICCARM__
00547 #pragma diag_default=Ta022
00548 #pragma diag_default=Ta023
00549 #endif
00550 #ifdef __CC_ARM
00551 #pragma arm section code
00552 #endif
00553
00557
00582 #ifdef __CC_ARM
00583 #pragma arm section code="ram_code"
00584 #endif
00585 #ifdef __ICCARM__
00586
00587
00588
00589 #pragma diag_suppress=Ta022
00590 #pragma diag_suppress=Ta023
00591 #endif
00592 MSC_Status_TypeDef MSC_ErasePage(uint32_t *startAddress)
00593 {
00594 uint32_t timeOut = MSC_PROGRAM_TIMEOUT;
00595
00596
00597 EFM_ASSERT((((uint32_t) startAddress) & (FLASH_PAGE_SIZE - 1)) == 0);
00598
00599
00600 MSC->WRITECTRL |= MSC_WRITECTRL_WREN;
00601
00602
00603 MSC->ADDRB = (uint32_t)startAddress;
00604 MSC->WRITECMD = MSC_WRITECMD_LADDRIM;
00605
00606
00607 if (MSC->STATUS & MSC_STATUS_INVADDR)
00608 {
00609
00610 MSC->WRITECTRL &= ~MSC_WRITECTRL_WREN;
00611 return mscReturnInvalidAddr;
00612 }
00613
00614 if (MSC->STATUS & MSC_STATUS_LOCKED)
00615 {
00616
00617 MSC->WRITECTRL &= ~MSC_WRITECTRL_WREN;
00618 return mscReturnLocked;
00619 }
00620
00621 MSC->WRITECMD = MSC_WRITECMD_ERASEPAGE;
00622
00623
00624 while ((MSC->STATUS & MSC_STATUS_BUSY) && (timeOut != 0))
00625 {
00626 timeOut--;
00627 }
00628 if (timeOut == 0)
00629 {
00630
00631 MSC->WRITECTRL &= ~MSC_WRITECTRL_WREN;
00632 return mscReturnTimeOut;
00633 }
00634
00635 MSC->WRITECTRL &= ~MSC_WRITECTRL_WREN;
00636 return mscReturnOk;
00637 }
00638 #ifdef __ICCARM__
00639 #pragma diag_default=Ta022
00640 #pragma diag_default=Ta023
00641 #endif
00642 #ifdef __CC_ARM
00643 #pragma arm section code
00644 #endif
00645
00646
00647
00683 #ifdef __CC_ARM
00684 #pragma arm section code="ram_code"
00685 #endif
00686 #ifdef __ICCARM__
00687
00688
00689
00690 #pragma diag_suppress=Ta022
00691 #pragma diag_suppress=Ta023
00692 #endif
00693 MSC_Status_TypeDef MSC_WriteWord(uint32_t *address,
00694 void const *data,
00695 uint32_t numBytes)
00696 {
00697 return MSC_WriteWordI(address, data, numBytes, mscWriteIntSafe);
00698 }
00699 #ifdef __ICCARM__
00700 #pragma diag_default=Ta022
00701 #pragma diag_default=Ta023
00702 #endif
00703 #ifdef __CC_ARM
00704 #pragma arm section code
00705 #endif
00706
00707
00708 #if !defined( _EFM32_GECKO_FAMILY )
00709
00742 #ifdef __CC_ARM
00743 #pragma arm section code="ram_code"
00744 #endif
00745 #ifdef __ICCARM__
00746
00747
00748
00749 #pragma diag_suppress=Ta022
00750 #pragma diag_suppress=Ta023
00751 #endif
00752 MSC_Status_TypeDef MSC_WriteWordFast(uint32_t *address,
00753 void const *data,
00754 uint32_t numBytes)
00755 {
00756 return MSC_WriteWordI(address, data, numBytes, mscWriteFast);
00757 }
00758 #ifdef __ICCARM__
00759 #pragma diag_default=Ta022
00760 #pragma diag_default=Ta023
00761 #endif
00762 #ifdef __CC_ARM
00763 #pragma arm section code
00764 #endif
00765 #endif
00766
00767
00768 #if defined( _MSC_MASSLOCK_MASK )
00769
00778 #ifdef __CC_ARM
00779 #pragma arm section code="ram_code"
00780 #endif
00781 MSC_Status_TypeDef MSC_MassErase(void)
00782 {
00783
00784 MSC->WRITECTRL |= MSC_WRITECTRL_WREN;
00785
00786
00787 MSC->MASSLOCK = MSC_MASSLOCK_LOCKKEY_UNLOCK;
00788
00789
00790 MSC->WRITECMD = MSC_WRITECMD_ERASEMAIN0;
00791
00792
00793 while ((MSC->STATUS & MSC_STATUS_BUSY));
00794
00795 #if (FLASH_SIZE >= (512 * 1024))
00796
00797 MSC->WRITECMD = MSC_WRITECMD_ERASEMAIN1;
00798
00799
00800 while ((MSC->STATUS & MSC_STATUS_BUSY));
00801 #endif
00802
00803
00804 MSC->MASSLOCK = MSC_MASSLOCK_LOCKKEY_LOCK;
00805
00806
00807 return mscReturnOk;
00808 }
00809 #ifdef __CC_ARM
00810 #pragma arm section code
00811 #endif
00812 #endif
00813
00816 #endif