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__ /* IAR compiler */
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__  /* GCC based compilers */
00067 #ifdef __CROSSWORKS_ARM  /* Rowley Crossworks (GCC based) */
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 /* GCC */
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 /* __CROSSWORKS_ARM */
00086 #endif /* __GNUC__ */
00087 
00090 /***************************************************************************/
00095 /***************************************************************************/
00101 /*******************************************************************************
00102  **************************   GLOBAL FUNCTIONS   *******************************
00103  ******************************************************************************/
00104 
00105 /***************************************************************************/
00119 void MSC_Init(void)
00120 {
00121 #if defined( _MSC_TIMEBASE_MASK )
00122   uint32_t freq, cycles;
00123 #endif
00124   /* Unlock the MSC */
00125   MSC->LOCK = MSC_UNLOCK_CODE;
00126   /* Disable writing to the flash */
00127   MSC->WRITECTRL &= ~MSC_WRITECTRL_WREN;
00128 
00129   /* Call SystemCoreClockGet in order to set the global variable SystemCoreClock
00130      which is used in MSC_LoadWriteData to make sure the frequency is
00131      sufficiently high. If the clock frequency is changed then software is
00132      responsible for calling MSC_Init or SystemCoreClockGet in order to set the
00133      SystemCoreClock variable to the correct value. */
00134   SystemCoreClockGet();
00135 
00136 #if defined( _MSC_TIMEBASE_MASK )
00137   /* Configure MSC->TIMEBASE according to selected frequency */
00138   freq = CMU_ClockFreqGet(cmuClock_AUX);
00139 
00140   if (freq > 7000000)
00141   {
00142     /* Calculate number of clock cycles for 1us as base period */
00143     freq   = (freq * 11) / 10;
00144     cycles = (freq / 1000000) + 1;
00145 
00146     /* Configure clock cycles for flash timing */
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     /* Calculate number of clock cycles for 5us as base period */
00155     freq   = (freq * 5 * 11) / 10;
00156     cycles = (freq / 1000000) + 1;
00157 
00158     /* Configure clock cycles for flash timing */
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   /* Disable writing to the flash */
00174   MSC->WRITECTRL &= ~MSC_WRITECTRL_WREN;
00175   /* Lock the MSC */
00176   MSC->LOCK = 0;
00177 }
00178 
00181 /***************************************************************************/
00198 #ifdef __CC_ARM  /* MDK-ARM compiler */
00199 #pragma arm section code="ram_code"
00200 #endif /* __CC_ARM */
00201 #ifdef __ICCARM__
00202 /* Suppress warnings originating from use of EFM_ASSERT():              */
00203 /* "Call to a non __ramfunc function from within a __ramfunc function"  */
00204 /* "Possible rom access from within a __ramfunc function"               */
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   /* Wait for the MSC to become ready. */
00215   timeOut = MSC_PROGRAM_TIMEOUT;
00216   while ((MSC->STATUS & MSC_STATUS_BUSY) && (timeOut != 0))
00217   {
00218     timeOut--;
00219   }
00220 
00221   /* Check for timeout */
00222   if (timeOut == 0)
00223   {
00224     return mscReturnTimeOut;
00225   }
00226   /* Load address */
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     /* Check for invalid address */
00234     if (status & MSC_STATUS_INVADDR)
00235       return mscReturnInvalidAddr;
00236     /* Check for write protected page */
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  /* MDK-ARM compiler */
00247 #pragma arm section code
00248 #endif /* __CC_ARM */
00249 
00250 
00251 /***************************************************************************/
00271 #ifdef __CC_ARM  /* MDK-ARM compiler */
00272 #pragma arm section code="ram_code"
00273 #endif /* __CC_ARM */
00274 #ifdef __ICCARM__
00275 /* Suppress warnings originating from use of EFM_ASSERT():              */
00276 /* "Call to a non __ramfunc function from within a __ramfunc function"  */
00277 /* "Possible rom access from within a __ramfunc function"               */
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   /* If LPWRITE (Low Power Write) is NOT enabled, set WDOUBLE (Write Double word) */
00293   if (!(MSC->WRITECTRL & MSC_WRITECTRL_LPWRITE))
00294   {
00295     /* If the number of words to be written are odd, we need to align by writing
00296        a single word first, before setting the WDOUBLE bit. */
00297     if (numWords & 0x1)
00298     {
00299       /* Wait for the MSC to become ready for the next word. */
00300       timeOut = MSC_PROGRAM_TIMEOUT;
00301       while ((!(MSC->STATUS & MSC_STATUS_WDATAREADY)) && (timeOut != 0))
00302       {
00303         timeOut--;
00304       }
00305       /* Check for timeout */
00306       if (timeOut == 0)
00307       {
00308         return mscReturnTimeOut;
00309       }
00310       /* Clear double word option, in order to write the initial single word. */
00311       MSC->WRITECTRL &= ~MSC_WRITECTRL_WDOUBLE;
00312       /* Write first data word. */
00313       MSC->WDATA = *data++;
00314       MSC->WRITECMD = MSC_WRITECMD_WRITEONCE;
00315 
00316       /* Wait for the operation to finish. It may be required to change the WDOUBLE
00317          config after the initial write. It should not be changed while BUSY. */
00318       timeOut = MSC_PROGRAM_TIMEOUT;
00319       while((MSC->STATUS & MSC_STATUS_BUSY) && (timeOut != 0))
00320       {
00321         timeOut--;
00322       }
00323       /* Check for timeout */
00324       if (timeOut == 0)
00325       {
00326         return mscReturnTimeOut;
00327       }
00328       /* Subtract this initial odd word for the write loop below */
00329       numWords -= 1;
00330       retval = mscReturnOk;
00331     }
00332     /* Now we can set the double word option in order to write two words per
00333        data phase. */
00334     MSC->WRITECTRL |= MSC_WRITECTRL_WDOUBLE;
00335     wordsPerDataPhase = 2;
00336   }
00337   else
00338 #endif /* defined( _MSC_WRITECTRL_LPWRITE_MASK ) && defined( _MSC_WRITECTRL_WDOUBLE_MASK ) */
00339   {
00340     wordsPerDataPhase = 1;
00341   }
00342 
00343   /* Write the rest as double word write if wordsPerDataPhase == 2 */
00344   if (numWords > 0)
00345   {
00346     /**** Write strategy: mscWriteIntSafe ****/
00347     if (writeStrategy == mscWriteIntSafe)
00348     {
00349       /* Requires a system core clock at 1MHz or higher */
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         /* Wait for the transaction to finish. */
00365         timeOut = MSC_PROGRAM_TIMEOUT;
00366         while ((MSC->STATUS & MSC_STATUS_BUSY) && (timeOut != 0))
00367         {
00368           timeOut--;
00369         }
00370         /* Check for timeout */
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     /**** Write strategy: mscWriteFast ****/
00384     else
00385     {
00386 #if defined( _EFM32_GECKO_FAMILY )
00387       /* Gecko does not have auto-increment of ADDR. */
00388       EFM_ASSERT(0);
00389 #else
00390       /* Requires a system core clock at 14MHz or higher */
00391       EFM_ASSERT(SystemCoreClock >= 14000000);
00392 
00393       wordIndex = 0;
00394       INT_Disable();
00395       while(wordIndex < numWords)
00396       {
00397         /* Wait for the MSC to be ready for the next word. */
00398         while (!(MSC->STATUS & MSC_STATUS_WDATAREADY))
00399         {
00400           /* If the write to MSC->WDATA below missed the 30us timeout and the
00401              following MSC_WRITECMD_WRITETRIG command arrived while
00402              MSC_STATUS_BUSY is 1, then the MSC_WRITECMD_WRITETRIG could be ignored by
00403              the MSC. In this case, MSC_STATUS_WORDTIMEOUT is set to 1
00404              and MSC_STATUS_BUSY is 0. A new trigger is therefore needed here to
00405              complete write of data in MSC->WDATA.
00406              If WDATAREADY became high since entry into this loop, exit and continue
00407              to the next WDATA write.
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       /* Wait for the transaction to finish. */
00425       timeOut = MSC_PROGRAM_TIMEOUT;
00426       while ((MSC->STATUS & MSC_STATUS_BUSY) && (timeOut != 0))
00427       {
00428         timeOut--;
00429       }
00430       /* Check for timeout */
00431       if (timeOut == 0)
00432       {
00433         retval = mscReturnTimeOut;
00434       }
00435 #endif
00436     } /* writeStrategy */
00437   }
00438 
00439 #if defined( _MSC_WRITECTRL_WDOUBLE_MASK )
00440   /* Clear double word option, which should not be left on when returning. */
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  /* MDK-ARM compiler */
00451 #pragma arm section code
00452 #endif /* __CC_ARM */
00453 
00454 
00455 /***************************************************************************/
00469 #ifdef __CC_ARM  /* MDK-ARM compiler */
00470 #pragma arm section code="ram_code"
00471 #endif /* __CC_ARM */
00472 #ifdef __ICCARM__
00473 /* Suppress warnings originating from use of EFM_ASSERT():              */
00474 /* "Call to a non __ramfunc function from within a __ramfunc function"  */
00475 /* "Possible rom access from within a __ramfunc function"               */
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   /* Check alignment (Must be aligned to words) */
00491   EFM_ASSERT(((uint32_t) address & 0x3) == 0);
00492 
00493   /* Check number of bytes. Must be divisable by four */
00494   EFM_ASSERT((numBytes & 0x3) == 0);
00495 
00496   /* Enable writing to the MSC */
00497   MSC->WRITECTRL |= MSC_WRITECTRL_WREN;
00498 
00499   /* Convert bytes to words */
00500   numWords = numBytes >> 2;
00501   EFM_ASSERT(numWords > 0);
00502 
00503   /* The following loop splits the data into chunks corresponding to flash pages.
00504      The address is loaded only once per page, because the hardware automatically
00505      increments the address internally for each data load inside a page. */
00506   for (wordCount = 0, pData = (uint32_t *)data; wordCount < numWords; )
00507   {
00508     /* First we load address. The address is auto-incremented within a page.
00509        Therefore the address phase is only needed once for each page. */
00510     retval = MSC_LoadVerifyAddress(address + wordCount);
00511     if (mscReturnOk != retval)
00512     {
00513       return retval;
00514     }
00515     /* Compute the number of words to write to the current page. */
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     /* Now write the data in the current page. */
00525     retval = MSC_LoadWriteData(pData, pageWords, writeStrategy);
00526     if (mscReturnOk != retval)
00527     {
00528       break;
00529     }
00530     wordCount += pageWords;
00531     pData += pageWords;
00532   }
00533 
00534   /* Disable writing to the MSC */
00535   MSC->WRITECTRL &= ~MSC_WRITECTRL_WREN;
00536 
00537 #if defined( _MSC_WRITECTRL_WDOUBLE_MASK )
00538 #if ( WORDS_PER_DATA_PHASE == 2 )
00539   /* Turn off double word write cycle support. */
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  /* MDK-ARM compiler */
00551 #pragma arm section code
00552 #endif /* __CC_ARM */
00553 
00557 /***************************************************************************/
00582 #ifdef __CC_ARM  /* MDK-ARM compiler */
00583 #pragma arm section code="ram_code"
00584 #endif /* __CC_ARM */
00585 #ifdef __ICCARM__
00586 /* Suppress warnings originating from use of EFM_ASSERT():              */
00587 /* "Call to a non __ramfunc function from within a __ramfunc function"  */
00588 /* "Possible rom access from within a __ramfunc function"               */
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   /* Address must be aligned to pages */
00597   EFM_ASSERT((((uint32_t) startAddress) & (FLASH_PAGE_SIZE - 1)) == 0);
00598 
00599   /* Enable writing to the MSC */
00600   MSC->WRITECTRL |= MSC_WRITECTRL_WREN;
00601 
00602   /* Load address */
00603   MSC->ADDRB    = (uint32_t)startAddress;
00604   MSC->WRITECMD = MSC_WRITECMD_LADDRIM;
00605 
00606   /* Check for invalid address */
00607   if (MSC->STATUS & MSC_STATUS_INVADDR)
00608   {
00609     /* Disable writing to the MSC */
00610     MSC->WRITECTRL &= ~MSC_WRITECTRL_WREN;
00611     return mscReturnInvalidAddr;
00612   }
00613   /* Check for write protected page */
00614   if (MSC->STATUS & MSC_STATUS_LOCKED)
00615   {
00616     /* Disable writing to the MSC */
00617     MSC->WRITECTRL &= ~MSC_WRITECTRL_WREN;
00618     return mscReturnLocked;
00619   }
00620   /* Send erase page command */
00621   MSC->WRITECMD = MSC_WRITECMD_ERASEPAGE;
00622 
00623   /* Wait for the erase to complete */
00624   while ((MSC->STATUS & MSC_STATUS_BUSY) && (timeOut != 0))
00625   {
00626     timeOut--;
00627   }
00628   if (timeOut == 0)
00629   {
00630     /* Disable writing to the MSC */
00631     MSC->WRITECTRL &= ~MSC_WRITECTRL_WREN;
00632     return mscReturnTimeOut;
00633   }
00634   /* Disable writing to the MSC */
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  /* MDK-ARM compiler */
00643 #pragma arm section code
00644 #endif /* __CC_ARM */
00645 
00646 
00647 /***************************************************************************/
00683 #ifdef __CC_ARM  /* MDK-ARM compiler */
00684 #pragma arm section code="ram_code"
00685 #endif /* __CC_ARM */
00686 #ifdef __ICCARM__
00687 /* Suppress warnings originating from use of EFM_ASSERT():              */
00688 /* "Call to a non __ramfunc function from within a __ramfunc function"  */
00689 /* "Possible rom access from within a __ramfunc function"               */
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  /* MDK-ARM compiler */
00704 #pragma arm section code
00705 #endif /* __CC_ARM */
00706 
00707 
00708 #if !defined( _EFM32_GECKO_FAMILY )
00709 /***************************************************************************/
00742 #ifdef __CC_ARM  /* MDK-ARM compiler */
00743 #pragma arm section code="ram_code"
00744 #endif /* __CC_ARM */
00745 #ifdef __ICCARM__
00746 /* Suppress warnings originating from use of EFM_ASSERT():              */
00747 /* "Call to a non __ramfunc function from within a __ramfunc function"  */
00748 /* "Possible rom access from within a __ramfunc function"               */
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  /* MDK-ARM compiler */
00763 #pragma arm section code
00764 #endif /* __CC_ARM */
00765 #endif
00766 
00767 
00768 #if defined( _MSC_MASSLOCK_MASK )
00769 /***************************************************************************/
00778 #ifdef __CC_ARM  /* MDK-ARM compiler */
00779 #pragma arm section code="ram_code"
00780 #endif /* __CC_ARM */
00781 MSC_Status_TypeDef MSC_MassErase(void)
00782 {
00783   /* Enable writing to the MSC */
00784   MSC->WRITECTRL |= MSC_WRITECTRL_WREN;
00785 
00786   /* Unlock device mass erase */
00787   MSC->MASSLOCK = MSC_MASSLOCK_LOCKKEY_UNLOCK;
00788 
00789   /* Erase first 512K block */
00790   MSC->WRITECMD = MSC_WRITECMD_ERASEMAIN0;
00791 
00792   /* Waiting for erase to complete */
00793   while ((MSC->STATUS & MSC_STATUS_BUSY));
00794 
00795 #if (FLASH_SIZE >= (512 * 1024))
00796   /* Erase second 512K block */
00797   MSC->WRITECMD = MSC_WRITECMD_ERASEMAIN1;
00798 
00799   /* Waiting for erase to complete */
00800   while ((MSC->STATUS & MSC_STATUS_BUSY));
00801 #endif
00802 
00803   /* Restore mass erase lock */
00804   MSC->MASSLOCK = MSC_MASSLOCK_LOCKKEY_LOCK;
00805 
00806   /* This will only successfully return if calling function is also in SRAM */
00807   return mscReturnOk;
00808 }
00809 #ifdef __CC_ARM  /* MDK-ARM compiler */
00810 #pragma arm section code
00811 #endif /* __CC_ARM */
00812 #endif
00813 
00816 #endif /* defined(MSC_COUNT) && (MSC_COUNT > 0) */