em_msc.c
Go to the documentation of this file.00001
00034 #include "em_msc.h"
00035 #if defined(MSC_COUNT) && (MSC_COUNT > 0)
00036
00037 #include "em_system.h"
00038 #if defined( _MSC_TIMEBASE_MASK )
00039 #include "em_cmu.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 #ifdef __CC_ARM
00052 msc_Return_TypeDef MscLoadData(uint32_t *data, int num);
00053 msc_Return_TypeDef MscLoadAddress(uint32_t *address);
00054 #endif
00055
00056 #ifdef __ICCARM__
00057 __ramfunc msc_Return_TypeDef MscLoadData(uint32_t *data, int num);
00058 __ramfunc msc_Return_TypeDef MscLoadAddress(uint32_t *address);
00059 #endif
00060
00061 #ifdef __GNUC__
00062 #ifdef __CROSSWORKS_ARM
00063 msc_Return_TypeDef MscLoadData(uint32_t *data, int num) __attribute__ ((section(".fast")));
00064 msc_Return_TypeDef MscLoadAddress(uint32_t *address) __attribute__ ((section(".fast")));
00065 #else
00066 msc_Return_TypeDef MscLoadData(uint32_t *data, int num) __attribute__ ((section(".ram")));
00067 msc_Return_TypeDef MscLoadAddress(uint32_t *address) __attribute__ ((section(".ram")));
00068 #endif
00069 #endif
00070
00073
00078
00084
00085
00086
00087
00088
00095 void MSC_Init(void)
00096 {
00097 #if defined( _MSC_TIMEBASE_MASK )
00098 uint32_t freq, cycles;
00099 #endif
00100
00101 MSC->LOCK = MSC_UNLOCK_CODE;
00102
00103 MSC->WRITECTRL &= ~MSC_WRITECTRL_WREN;
00104
00105 #if defined( _MSC_TIMEBASE_MASK )
00106
00107 freq = CMU_ClockFreqGet(cmuClock_AUX);
00108
00109 if (freq > 7000000)
00110 {
00111
00112 freq = (freq * 11) / 10;
00113 cycles = (freq / 1000000) + 1;
00114
00115
00116 MSC->TIMEBASE = (MSC->TIMEBASE & ~(_MSC_TIMEBASE_BASE_MASK |
00117 _MSC_TIMEBASE_PERIOD_MASK)) |
00118 MSC_TIMEBASE_PERIOD_1US |
00119 (cycles << _MSC_TIMEBASE_BASE_SHIFT);
00120 }
00121 else
00122 {
00123
00124 freq = (freq * 5 * 11) / 10;
00125 cycles = (freq / 1000000) + 1;
00126
00127
00128 MSC->TIMEBASE = (MSC->TIMEBASE & ~(_MSC_TIMEBASE_BASE_MASK |
00129 _MSC_TIMEBASE_PERIOD_MASK)) |
00130 MSC_TIMEBASE_PERIOD_5US |
00131 (cycles << _MSC_TIMEBASE_BASE_SHIFT);
00132 }
00133 #endif
00134 }
00135
00136
00140 void MSC_Deinit(void)
00141 {
00142
00143 MSC->WRITECTRL &= ~MSC_WRITECTRL_WREN;
00144
00145 MSC->LOCK = 0;
00146 }
00147
00148
00151
00174 #ifdef __CC_ARM
00175 #pragma arm section code="ram_code"
00176 #endif
00177 #if defined(__ICCARM__)
00178
00179
00180
00181 #pragma diag_suppress=Ta022
00182 #pragma diag_suppress=Ta023
00183 #endif
00184
00185 msc_Return_TypeDef MscLoadAddress(uint32_t* address)
00186 {
00187 uint32_t status;
00188 int timeOut;
00189
00190
00191 timeOut = MSC_PROGRAM_TIMEOUT;
00192 while ((MSC->STATUS & MSC_STATUS_BUSY) && (timeOut != 0))
00193 {
00194 timeOut--;
00195 }
00196
00197
00198 if (timeOut == 0)
00199 return mscReturnTimeOut;
00200
00201
00202 MSC->ADDRB = (uint32_t) (address);
00203 MSC->WRITECMD = MSC_WRITECMD_LADDRIM;
00204
00205 status = MSC->STATUS;
00206 if (status & (MSC_STATUS_INVADDR | MSC_STATUS_LOCKED))
00207 {
00208
00209 if (status & MSC_STATUS_INVADDR)
00210 return mscReturnInvalidAddr;
00211
00212 if (status & MSC_STATUS_LOCKED)
00213 return mscReturnLocked;
00214 }
00215 return mscReturnOk;
00216 }
00217
00218 #if defined(__ICCARM__)
00219 #pragma diag_default=Ta022
00220 #pragma diag_default=Ta023
00221 #endif
00222 #ifdef __CC_ARM
00223 #pragma arm section code
00224 #endif
00225
00226
00227
00228
00252 #ifdef __CC_ARM
00253 #pragma arm section code="ram_code"
00254 #endif
00255 #if defined(__ICCARM__)
00256
00257
00258
00259 #pragma diag_suppress=Ta022
00260 #pragma diag_suppress=Ta023
00261 #endif
00262
00263 msc_Return_TypeDef MscLoadData(uint32_t* data, int num)
00264 {
00265 int timeOut = MSC_PROGRAM_TIMEOUT;
00266 int i;
00267 int wordsPerDataPhase;
00268 msc_Return_TypeDef retval = mscReturnOk;
00269
00270 #ifdef MSC_WRITECTRL_LPWRITE
00271
00272 if (0 == (MSC->WRITECTRL & MSC_WRITECTRL_LPWRITE))
00273 {
00274
00275
00276 if (num & 0x1)
00277 {
00278
00279 timeOut = MSC_PROGRAM_TIMEOUT;
00280 while ((0 == (MSC->STATUS & MSC_STATUS_WDATAREADY)) && (timeOut != 0))
00281 {
00282 timeOut--;
00283 }
00284
00285 if (timeOut == 0)
00286 return mscReturnTimeOut;
00287
00288
00289 MSC->WRITECTRL &= ~MSC_WRITECTRL_WDOUBLE;
00290
00291 MSC->WDATA = *data++;
00292
00293
00294
00295
00296 MSC->WRITECMD = MSC_WRITECMD_WRITETRIG;
00297
00298
00299 timeOut = MSC_PROGRAM_TIMEOUT;
00300 while ((MSC->STATUS & MSC_STATUS_BUSY) && (timeOut != 0))
00301 {
00302 timeOut--;
00303 }
00304
00305 if (timeOut == 0)
00306 return mscReturnTimeOut;
00307
00308 if (0 == --num)
00309 {
00310 retval = mscReturnOk;
00311 goto msc_load_data_exit;
00312 }
00313 }
00314
00315
00316
00317 MSC->WRITECTRL |= MSC_WRITECTRL_WDOUBLE;
00318 wordsPerDataPhase = 2;
00319 }
00320 else
00321 #endif
00322 {
00323 wordsPerDataPhase = 1;
00324 }
00325
00326
00327
00328
00329
00330 timeOut = MSC_PROGRAM_TIMEOUT;
00331 while (((MSC->STATUS & MSC_STATUS_WDATAREADY) == 0) && (timeOut != 0))
00332 {
00333 timeOut--;
00334 }
00335
00336
00337 if (timeOut == 0)
00338 return mscReturnTimeOut;
00339
00340
00341 MSC->WDATA = *data;
00342
00343
00344 MSC->WRITECMD = MSC_WRITECMD_WRITETRIG;
00345
00346
00347 for (i=1, data++; i<num; i++, data++)
00348 {
00349
00350 if (0 == (i&(wordsPerDataPhase-1)))
00351 {
00352
00353 timeOut = MSC_PROGRAM_TIMEOUT;
00354 while ((0 == (MSC->STATUS & MSC_STATUS_WDATAREADY)) && (timeOut != 0))
00355 {
00356 timeOut--;
00357 }
00358
00359 if (timeOut == 0)
00360 return mscReturnTimeOut;
00361 }
00362
00363
00364 if (MSC->STATUS & MSC_STATUS_WORDTIMEOUT)
00365 {
00366 retval = mscReturnTimeOut;
00367 goto msc_load_data_exit;
00368 }
00369
00370
00371 MSC->WDATA = *data;
00372 }
00373
00374 msc_load_data_exit:
00375
00376
00377 timeOut = MSC_PROGRAM_TIMEOUT;
00378 while ((MSC->STATUS & MSC_STATUS_BUSY) && (timeOut != 0))
00379 {
00380 timeOut--;
00381 }
00382
00383 if (timeOut == 0)
00384 retval = mscReturnTimeOut;
00385
00386 #ifdef MSC_WRITECTRL_WDOUBLE
00387
00388 MSC->WRITECTRL &= ~MSC_WRITECTRL_WDOUBLE;
00389 #endif
00390
00391 return retval;
00392 }
00393 #if defined(__ICCARM__)
00394 #pragma diag_default=Ta022
00395 #pragma diag_default=Ta023
00396 #endif
00397 #ifdef __CC_ARM
00398 #pragma arm section code
00399 #endif
00400
00404
00426 #ifdef __CC_ARM
00427 #pragma arm section code="ram_code"
00428 #endif
00429 #if defined(__ICCARM__)
00430
00431
00432
00433 #pragma diag_suppress=Ta022
00434 #pragma diag_suppress=Ta023
00435 #endif
00436 msc_Return_TypeDef MSC_ErasePage(uint32_t *startAddress)
00437 {
00438 int timeOut = MSC_PROGRAM_TIMEOUT;
00439
00440
00441 EFM_ASSERT((((uint32_t) startAddress) & (FLASH_PAGE_SIZE - 1)) == 0);
00442
00443
00444 MSC->WRITECTRL |= MSC_WRITECTRL_WREN;
00445
00446
00447 MSC->ADDRB = (uint32_t) startAddress;
00448 MSC->WRITECMD = MSC_WRITECMD_LADDRIM;
00449
00450
00451 if (MSC->STATUS & MSC_STATUS_INVADDR)
00452 {
00453
00454 MSC->WRITECTRL &= ~MSC_WRITECTRL_WREN;
00455 return mscReturnInvalidAddr;
00456 }
00457
00458
00459 if (MSC->STATUS & MSC_STATUS_LOCKED)
00460 {
00461
00462 MSC->WRITECTRL &= ~MSC_WRITECTRL_WREN;
00463 return mscReturnLocked;
00464 }
00465
00466
00467 MSC->WRITECMD = MSC_WRITECMD_ERASEPAGE;
00468
00469
00470 while ((MSC->STATUS & MSC_STATUS_BUSY) && (timeOut != 0))
00471 {
00472 timeOut--;
00473 }
00474
00475 if (timeOut == 0)
00476 {
00477
00478 MSC->WRITECTRL &= ~MSC_WRITECTRL_WREN;
00479 return mscReturnTimeOut;
00480 }
00481
00482
00483 MSC->WRITECTRL &= ~MSC_WRITECTRL_WREN;
00484 return mscReturnOk;
00485 }
00486 #if defined(__ICCARM__)
00487 #pragma diag_default=Ta022
00488 #pragma diag_default=Ta023
00489 #endif
00490 #ifdef __CC_ARM
00491 #pragma arm section code
00492 #endif
00493
00494
00495
00496
00528 #ifdef __CC_ARM
00529 #pragma arm section code="ram_code"
00530 #endif
00531 #if defined(__ICCARM__)
00532
00533
00534
00535 #pragma diag_suppress=Ta022
00536 #pragma diag_suppress=Ta023
00537 #endif
00538
00539 msc_Return_TypeDef MSC_WriteWord(uint32_t *address, void const *data, int numBytes)
00540 {
00541 int wordCount;
00542 int numWords;
00543 int pageWords;
00544 uint32_t* pData;
00545 msc_Return_TypeDef retval = mscReturnOk;
00546
00547
00548 EFM_ASSERT(((uint32_t) address & 0x3) == 0);
00549
00550
00551 EFM_ASSERT((numBytes & 0x3) == 0);
00552
00553
00554 MSC->WRITECTRL |= MSC_WRITECTRL_WREN;
00555
00556
00557 numWords = numBytes >> 2;
00558
00559
00560
00561
00562 for (wordCount = 0, pData = (uint32_t*) data; wordCount < numWords; )
00563 {
00564
00565
00566 retval = MscLoadAddress(address+wordCount);
00567 if (mscReturnOk != retval)
00568 return retval;
00569
00570
00571 pageWords =
00572 (FLASH_PAGE_SIZE - ((uint32_t) (address + wordCount)) % FLASH_PAGE_SIZE) /
00573 sizeof(uint32_t);
00574 if (pageWords > numWords-wordCount)
00575 pageWords = numWords-wordCount;
00576
00577
00578 retval = MscLoadData(pData, pageWords);
00579 if (mscReturnOk != retval) goto msc_write_word_exit;
00580
00581 wordCount += pageWords;
00582 pData += pageWords;
00583 }
00584
00585 msc_write_word_exit:
00586
00587
00588 MSC->WRITECTRL &= ~MSC_WRITECTRL_WREN;
00589
00590 #if (defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_WONDER_FAMILY)) && (2==WORDS_PER_DATA_PHASE)
00591
00592 MSC->WRITECTRL &= ~MSC_WRITECTRL_WDOUBLE;
00593 #endif
00594
00595 return retval;
00596 }
00597
00598 #if defined(__ICCARM__)
00599 #pragma diag_default=Ta022
00600 #pragma diag_default=Ta023
00601 #endif
00602 #ifdef __CC_ARM
00603 #pragma arm section code
00604 #endif
00605
00606
00607 #if defined( _MSC_MASSLOCK_MASK )
00608
00617 #ifdef __CC_ARM
00618 #pragma arm section code="ram_code"
00619 #endif
00620 msc_Return_TypeDef MSC_MassErase(void)
00621 {
00622
00623 MSC->WRITECTRL |= MSC_WRITECTRL_WREN;
00624
00625
00626 MSC->MASSLOCK = MSC_MASSLOCK_LOCKKEY_UNLOCK;
00627
00628
00629 MSC->WRITECMD = MSC_WRITECMD_ERASEMAIN0;
00630
00631
00632 while ((MSC->STATUS & MSC_STATUS_BUSY))
00633 {
00634 }
00635
00636 #if FLASH_SIZE >= (512 * 1024)
00637
00638 MSC->WRITECMD = MSC_WRITECMD_ERASEMAIN1;
00639
00640
00641 while ((MSC->STATUS & MSC_STATUS_BUSY))
00642 {
00643 }
00644 #endif
00645
00646
00647 MSC->MASSLOCK = MSC_MASSLOCK_LOCKKEY_LOCK;
00648
00649
00650 return mscReturnOk;
00651 }
00652 #ifdef __CC_ARM
00653 #pragma arm section code
00654 #endif
00655 #endif
00656
00659 #endif