EFM32 Happy Gecko Software Documentation  efm32hg-doc-5.1.2
em_msc.c
Go to the documentation of this file.
1 /***************************************************************************/
33 #include "em_msc.h"
34 #if defined( MSC_COUNT ) && ( MSC_COUNT > 0 )
35 
36 #include "em_system.h"
37 #if defined( _MSC_TIMEBASE_MASK )
38 #include "em_cmu.h"
39 #endif
40 #include "em_assert.h"
41 
44 #if defined(__ICCARM__)
45 /* Suppress warnings originating from use of EFM_ASSERT() with IAR:
46  EFM_ASSERT() is implemented as a local ramfunc */
47 #pragma diag_suppress=Ta022
48 #endif
49 
50 #if defined(EM_MSC_RUN_FROM_FLASH) && defined(_EFM32_GECKO_FAMILY)
51 #error "Running Flash write/erase operations from Flash is not supported on EFM32G."
52 #endif
53 
54 #if defined( MSC_WRITECTRL_WDOUBLE )
55 #define WORDS_PER_DATA_PHASE (FLASH_SIZE < (512 * 1024) ? 1 : 2)
56 #else
57 #define WORDS_PER_DATA_PHASE (1)
58 #endif
59 
60 #if defined( _SILICON_LABS_GECKO_INTERNAL_SDID_80 )
61 /* Fix for errata FLASH_E201 - Potential program failure after Power On */
62 #define ERRATA_FIX_FLASH_E201_EN
63 #endif
64 
65 typedef enum {
66  mscWriteIntSafe,
67  mscWriteFast,
68 } MSC_WriteStrategy_Typedef;
69 
71  MSC_WriteWordI(uint32_t *address,
72  void const *data,
73  uint32_t numBytes,
74  MSC_WriteStrategy_Typedef writeStrategy);
75 
77  MSC_LoadWriteData(uint32_t* data,
78  uint32_t numWords,
79  MSC_WriteStrategy_Typedef writeStrategy);
80 
82  MSC_LoadVerifyAddress(uint32_t* address);
83 
84 #if !defined(EM_MSC_RUN_FROM_FLASH)
85 
86 MSC_RAMFUNC_DECLARATOR void mscRfAssertEFM(const char *file, int line);
87 
88 /***************************************************************************/
106 void mscRfAssertEFM(const char *file, int line)
107 {
108  (void)file; /* Unused parameter */
109  (void)line; /* Unused parameter */
110 
111  while (true)
112  {
113  }
114 }
116 
117 /* Undef the define from em_assert.h and redirect to local ramfunc version. */
118 #undef EFM_ASSERT
119 #if defined(DEBUG_EFM) || defined(DEBUG_EFM_USER)
120 #define EFM_ASSERT(expr) ((expr) ? ((void)0) : mscRfAssertEFM(__FILE__, __LINE__))
121 #else
122 #define EFM_ASSERT(expr) ((void)(expr))
123 #endif /* defined(DEBUG_EFM) || defined(DEBUG_EFM_USER) */
124 
125 #endif /* !EM_MSC_RUN_FROM_FLASH */
126 
129 /***************************************************************************/
134 /***************************************************************************/
139 /*******************************************************************************
140  ************************** GLOBAL FUNCTIONS *******************************
141  ******************************************************************************/
142 
143 /***************************************************************************/
157 void MSC_Init(void)
158 {
159 #if defined( _MSC_TIMEBASE_MASK )
160  uint32_t freq, cycles;
161 #endif
162 
163 #if defined( _EMU_STATUS_VSCALE_MASK )
164  /* VSCALE must be done and flash erase and write requires VSCALE2 */
165  EFM_ASSERT(!(EMU->STATUS & _EMU_STATUS_VSCALEBUSY_MASK));
166  EFM_ASSERT((EMU->STATUS & _EMU_STATUS_VSCALE_MASK) == EMU_STATUS_VSCALE_VSCALE2);
167 #endif
168 
169  /* Unlock the MSC */
170  MSC->LOCK = MSC_UNLOCK_CODE;
171  /* Disable writing to the flash */
172  MSC->WRITECTRL &= ~MSC_WRITECTRL_WREN;
173 
174  /* Call SystemCoreClockGet in order to set the global variable SystemCoreClock
175  which is used in MSC_LoadWriteData to make sure the frequency is
176  sufficiently high. If the clock frequency is changed then software is
177  responsible for calling MSC_Init or SystemCoreClockGet in order to set the
178  SystemCoreClock variable to the correct value. */
180 
181 #if defined( _MSC_TIMEBASE_MASK )
182  /* Configure MSC->TIMEBASE according to selected frequency */
184 
185  /* Timebase 5us is used for the 1/1.2MHz band only. Note that the 1MHz band
186  is tuned to 1.2MHz on newer revisions. */
187  if (freq > 1200000)
188  {
189  /* Calculate number of clock cycles for 1us as base period */
190  freq = (freq * 11) / 10;
191  cycles = (freq / 1000000) + 1;
192 
193  /* Configure clock cycles for flash timing */
194  MSC->TIMEBASE = (MSC->TIMEBASE & ~(_MSC_TIMEBASE_BASE_MASK
197  | (cycles << _MSC_TIMEBASE_BASE_SHIFT);
198  }
199  else
200  {
201  /* Calculate number of clock cycles for 5us as base period */
202  freq = (freq * 5 * 11) / 10;
203  cycles = (freq / 1000000) + 1;
204 
205  /* Configure clock cycles for flash timing */
206  MSC->TIMEBASE = (MSC->TIMEBASE & ~(_MSC_TIMEBASE_BASE_MASK
209  | (cycles << _MSC_TIMEBASE_BASE_SHIFT);
210  }
211 #endif
212 }
213 
214 /***************************************************************************/
218 void MSC_Deinit(void)
219 {
220  /* Disable writing to the flash */
221  MSC->WRITECTRL &= ~MSC_WRITECTRL_WREN;
222  /* Lock the MSC */
223  MSC->LOCK = 0;
224 }
225 
226 
227 /***************************************************************************/
235 {
236  uint32_t mscReadCtrl;
237 
238 #if defined( MSC_READCTRL_MODE_WS0SCBTP )
239  mscReadCtrl = MSC->READCTRL & _MSC_READCTRL_MODE_MASK;
240  if ((mscReadCtrl == MSC_READCTRL_MODE_WS0) && (execConfig->scbtEn))
241  {
242  mscReadCtrl |= MSC_READCTRL_MODE_WS0SCBTP;
243  }
244  else if ((mscReadCtrl == MSC_READCTRL_MODE_WS1) && (execConfig->scbtEn))
245  {
246  mscReadCtrl |= MSC_READCTRL_MODE_WS1SCBTP;
247  }
248  else if ((mscReadCtrl == MSC_READCTRL_MODE_WS0SCBTP) && (!execConfig->scbtEn))
249  {
250  mscReadCtrl |= MSC_READCTRL_MODE_WS0;
251  }
252  else if ((mscReadCtrl == MSC_READCTRL_MODE_WS1SCBTP) && (!execConfig->scbtEn))
253  {
254  mscReadCtrl |= MSC_READCTRL_MODE_WS1;
255  }
256  else
257  {
258  /* No change needed */
259  }
260 #endif
261 
262  mscReadCtrl = MSC->READCTRL & ~(0
263 #if defined( MSC_READCTRL_SCBTP )
264  | MSC_READCTRL_SCBTP
265 #endif
266 #if defined( MSC_READCTRL_USEHPROT )
267  | MSC_READCTRL_USEHPROT
268 #endif
269 #if defined( MSC_READCTRL_PREFETCH )
270  | MSC_READCTRL_PREFETCH
271 #endif
272 #if defined( MSC_READCTRL_ICCDIS )
273  | MSC_READCTRL_ICCDIS
274 #endif
275 #if defined( MSC_READCTRL_AIDIS )
277 #endif
278 #if defined( MSC_READCTRL_IFCDIS )
280 #endif
281  );
282  mscReadCtrl |= (0
283 #if defined( MSC_READCTRL_SCBTP )
284  | (execConfig->scbtEn ? MSC_READCTRL_SCBTP : 0)
285 #endif
286 #if defined( MSC_READCTRL_USEHPROT )
287  | (execConfig->useHprot ? MSC_READCTRL_USEHPROT : 0)
288 #endif
289 #if defined( MSC_READCTRL_PREFETCH )
290  | (execConfig->prefetchEn ? MSC_READCTRL_PREFETCH : 0)
291 #endif
292 #if defined( MSC_READCTRL_ICCDIS )
293  | (execConfig->iccDis ? MSC_READCTRL_ICCDIS : 0)
294 #endif
295 #if defined( MSC_READCTRL_AIDIS )
296  | (execConfig->aiDis ? MSC_READCTRL_AIDIS : 0)
297 #endif
298 #if defined( MSC_READCTRL_IFCDIS )
299  | (execConfig->ifcDis ? MSC_READCTRL_IFCDIS : 0)
300 #endif
301  );
302 
303  MSC->READCTRL = mscReadCtrl;
304 }
305 
306 
307 
308 
311 /***************************************************************************/
329 MSC_Status_TypeDef MSC_LoadVerifyAddress(uint32_t* address)
330 {
331  uint32_t status;
332  uint32_t timeOut;
333 
334  /* Wait for the MSC to become ready. */
335  timeOut = MSC_PROGRAM_TIMEOUT;
336  while ((MSC->STATUS & MSC_STATUS_BUSY) && (timeOut != 0))
337  {
338  timeOut--;
339  }
340 
341  /* Check for timeout */
342  if (timeOut == 0)
343  {
344  return mscReturnTimeOut;
345  }
346  /* Load address */
347  MSC->ADDRB = (uint32_t)address;
348  MSC->WRITECMD = MSC_WRITECMD_LADDRIM;
349 
350  status = MSC->STATUS;
351  if (status & (MSC_STATUS_INVADDR | MSC_STATUS_LOCKED))
352  {
353  /* Check for invalid address */
354  if (status & MSC_STATUS_INVADDR)
355  return mscReturnInvalidAddr;
356  /* Check for write protected page */
357  if (status & MSC_STATUS_LOCKED)
358  return mscReturnLocked;
359  }
360  return mscReturnOk;
361 }
363 
364 
365 /***************************************************************************/
386 MSC_Status_TypeDef MSC_LoadWriteData(uint32_t* data,
387  uint32_t numWords,
388  MSC_WriteStrategy_Typedef writeStrategy)
389 {
390  uint32_t timeOut;
391  uint32_t wordIndex;
392  bool useWDouble = false;
394 #if !defined( _EFM32_GECKO_FAMILY )
395  uint32_t irqState;
396 #endif
397 
398 #if defined(_MSC_WRITECTRL_LPWRITE_MASK) && defined(_MSC_WRITECTRL_WDOUBLE_MASK)
399  /* If LPWRITE (Low Power Write) is NOT enabled, set WDOUBLE (Write Double word) */
400  if (!(MSC->WRITECTRL & MSC_WRITECTRL_LPWRITE))
401  {
402 #if defined(_SILICON_LABS_32B_SERIES_0)
403  /* If the number of words to be written are odd, we need to align by writing
404  a single word first, before setting the WDOUBLE bit. */
405  if (numWords & 0x1)
406  {
407  /* Wait for the MSC to become ready for the next word. */
408  timeOut = MSC_PROGRAM_TIMEOUT;
409  while ((!(MSC->STATUS & MSC_STATUS_WDATAREADY)) && (timeOut != 0))
410  {
411  timeOut--;
412  }
413  /* Check for timeout */
414  if (timeOut == 0)
415  {
416  return mscReturnTimeOut;
417  }
418  /* Clear double word option, in order to write the initial single word. */
419  MSC->WRITECTRL &= ~MSC_WRITECTRL_WDOUBLE;
420  /* Write first data word. */
421  MSC->WDATA = *data++;
422  MSC->WRITECMD = MSC_WRITECMD_WRITEONCE;
423 
424  /* Wait for the operation to finish. It may be required to change the WDOUBLE
425  config after the initial write. It should not be changed while BUSY. */
426  timeOut = MSC_PROGRAM_TIMEOUT;
427  while((MSC->STATUS & MSC_STATUS_BUSY) && (timeOut != 0))
428  {
429  timeOut--;
430  }
431  /* Check for timeout */
432  if (timeOut == 0)
433  {
434  return mscReturnTimeOut;
435  }
436  /* Subtract this initial odd word for the write loop below */
437  numWords -= 1;
438  retval = mscReturnOk;
439  }
440  /* Now we can set the double word option in order to write two words per
441  data phase. */
442 #endif
443  MSC->WRITECTRL |= MSC_WRITECTRL_WDOUBLE;
444  useWDouble = true;
445  }
446 #endif /* defined( _MSC_WRITECTRL_LPWRITE_MASK ) && defined( _MSC_WRITECTRL_WDOUBLE_MASK ) */
447 
448  /* Write the rest as double word write if wordsPerDataPhase == 2 */
449  if (numWords > 0)
450  {
451  /**** Write strategy: mscWriteIntSafe ****/
452  if (writeStrategy == mscWriteIntSafe)
453  {
454  /* Requires a system core clock at 1MHz or higher */
455  EFM_ASSERT(SystemCoreClock >= 1000000);
456  wordIndex = 0;
457  while(wordIndex < numWords)
458  {
459  if (!useWDouble)
460  {
461  MSC->WDATA = *data++;
462  wordIndex++;
463  MSC->WRITECMD = MSC_WRITECMD_WRITEONCE;
464  }
465 
466  else // useWDouble == true
467  {
468  /* Trigger double write according to flash properties. */
469 #if defined(_SILICON_LABS_32B_SERIES_0)
470  MSC->WDATA = *data++;
471  while (!(MSC->STATUS & MSC_STATUS_WDATAREADY));
472  MSC->WDATA = *data++;
473  wordIndex += 2;
474  MSC->WRITECMD = MSC_WRITECMD_WRITEONCE;
475 
476 #elif (_SILICON_LABS_32B_SERIES_1_CONFIG >= 2)
477  while (!(MSC->STATUS & MSC_STATUS_WDATAREADY));
478  do
479  {
480  MSC->WDATA = *data++;
481  wordIndex++;
482  } while ((MSC->STATUS & MSC_STATUS_WDATAREADY)
483  && (wordIndex < numWords));
484  MSC->WRITECMD = MSC_WRITECMD_WRITETRIG;
485 #endif
486  }
487 
488  /* Wait for the transaction to finish. */
489  timeOut = MSC_PROGRAM_TIMEOUT;
490  while ((MSC->STATUS & MSC_STATUS_BUSY) && (timeOut != 0))
491  {
492  timeOut--;
493  }
494  /* Check for timeout */
495  if (timeOut == 0)
496  {
497  retval = mscReturnTimeOut;
498  break;
499  }
500 #if defined( _EFM32_GECKO_FAMILY )
501  MSC->ADDRB += 4;
502  MSC->WRITECMD = MSC_WRITECMD_LADDRIM;
503 #endif
504  }
505  }
506 
507  /**** Write strategy: mscWriteFast ****/
508  else
509  {
510 #if defined( _EFM32_GECKO_FAMILY )
511  /* Gecko does not have auto-increment of ADDR. */
512  EFM_ASSERT(false);
513 #else
514  /* Requires a system core clock at 14MHz or higher. */
515  EFM_ASSERT(SystemCoreClock >= 14000000);
516 
517  /*
518  * Protect from interrupts to be sure to satisfy the us timinig
519  * needs of the MSC flash programming state machine.
520  */
521  irqState = __get_PRIMASK();
522  __disable_irq();
523 
524  wordIndex = 0;
525  while(wordIndex < numWords)
526  {
527  /* Wait for the MSC to be ready for the next word. */
528  while (!(MSC->STATUS & MSC_STATUS_WDATAREADY))
529  {
530  /* If the write to MSC->WDATA below missed the 30us timeout and the
531  following MSC_WRITECMD_WRITETRIG command arrived while
532  MSC_STATUS_BUSY is 1, then the MSC_WRITECMD_WRITETRIG could be ignored by
533  the MSC. In this case, MSC_STATUS_WORDTIMEOUT is set to 1
534  and MSC_STATUS_BUSY is 0. A new trigger is therefore needed here to
535  complete write of data in MSC->WDATA.
536  If WDATAREADY became high since entry into this loop, exit and continue
537  to the next WDATA write.
538  */
539  if ((MSC->STATUS & (MSC_STATUS_WORDTIMEOUT
543  {
544  MSC->WRITECMD = MSC_WRITECMD_WRITETRIG;
545  }
546  }
547 
548  if (!useWDouble)
549  {
550  MSC->WDATA = *data;
551  MSC->WRITECMD = MSC_WRITECMD_WRITETRIG;
552  data++;
553  wordIndex++;
554  }
555 
556  else // useWDouble == true
557  {
558  /* Trigger double write according to flash properties. */
559 #if defined(_SILICON_LABS_32B_SERIES_0)
560  MSC->WDATA = *data;
561  if (wordIndex & 0x1)
562  {
563  MSC->WRITECMD = MSC_WRITECMD_WRITETRIG;
564  }
565  data++;
566  wordIndex++;
567 
568 #elif (_SILICON_LABS_32B_SERIES_1_CONFIG >= 2)
569  do
570  {
571  MSC->WDATA = *data++;
572  wordIndex++;
573  } while ((MSC->STATUS & MSC_STATUS_WDATAREADY)
574  && (wordIndex < numWords));
575  MSC->WRITECMD = MSC_WRITECMD_WRITETRIG;
576 #endif
577  }
578  }
579 
580  if (irqState == 0)
581  {
582  /* Restore previous interrupt state. */
583  __enable_irq();
584  }
585 
586  /* Wait for the transaction to finish. */
587  timeOut = MSC_PROGRAM_TIMEOUT;
588  while ((MSC->STATUS & MSC_STATUS_BUSY) && (timeOut != 0))
589  {
590  timeOut--;
591  }
592  /* Check for timeout */
593  if (timeOut == 0)
594  {
595  retval = mscReturnTimeOut;
596  }
597 #endif
598  } /* writeStrategy */
599  }
600 
601 #if defined( _MSC_WRITECTRL_WDOUBLE_MASK )
602  /* Clear double word option, which should not be left on when returning. */
603  MSC->WRITECTRL &= ~MSC_WRITECTRL_WDOUBLE;
604 #endif
605 
606  return retval;
607 }
609 
610 
611 /***************************************************************************/
626 MSC_Status_TypeDef MSC_WriteWordI(uint32_t *address,
627  void const *data,
628  uint32_t numBytes,
629  MSC_WriteStrategy_Typedef writeStrategy)
630 {
631  uint32_t wordCount;
632  uint32_t numWords;
633  uint32_t pageWords;
634  uint32_t* pData;
636 
637  /* Check alignment (Must be aligned to words) */
638  EFM_ASSERT(((uint32_t) address & 0x3) == 0);
639 
640  /* Check number of bytes. Must be divisable by four */
641  EFM_ASSERT((numBytes & 0x3) == 0);
642 
643 #if defined( _EMU_STATUS_VSCALE_MASK )
644  /* VSCALE must be done and flash write requires VSCALE2 */
645  EFM_ASSERT(!(EMU->STATUS & _EMU_STATUS_VSCALEBUSY_MASK));
646  EFM_ASSERT((EMU->STATUS & _EMU_STATUS_VSCALE_MASK) == EMU_STATUS_VSCALE_VSCALE2);
647 #endif
648 
649  /* Enable writing to the MSC */
650  MSC->WRITECTRL |= MSC_WRITECTRL_WREN;
651 
652  /* Convert bytes to words */
653  numWords = numBytes >> 2;
654  EFM_ASSERT(numWords > 0);
655 
656  /* The following loop splits the data into chunks corresponding to flash pages.
657  The address is loaded only once per page, because the hardware automatically
658  increments the address internally for each data load inside a page. */
659  for (wordCount = 0, pData = (uint32_t *)data; wordCount < numWords; )
660  {
661  /* First we load address. The address is auto-incremented within a page.
662  Therefore the address phase is only needed once for each page. */
663  retval = MSC_LoadVerifyAddress(address + wordCount);
664  if (mscReturnOk != retval)
665  {
666  return retval;
667  }
668  /* Compute the number of words to write to the current page. */
669  pageWords =
670  (FLASH_PAGE_SIZE -
671  (((uint32_t) (address + wordCount)) & (FLASH_PAGE_SIZE - 1)))
672  / sizeof(uint32_t);
673  if (pageWords > numWords - wordCount)
674  {
675  pageWords = numWords - wordCount;
676  }
677  /* Now write the data in the current page. */
678  retval = MSC_LoadWriteData(pData, pageWords, writeStrategy);
679  if (mscReturnOk != retval)
680  {
681  break;
682  }
683  wordCount += pageWords;
684  pData += pageWords;
685  }
686 
687 #if defined( ERRATA_FIX_FLASH_E201_EN )
688  /* Fix for errata FLASH_E201 - Potential program failure after Power On.
689  *
690  * Check if the first word was programmed correctly. If a failure is detected
691  * then retry programming of the first word.
692  *
693  * Full description of errata can be found in the errata document */
694  pData = (uint32_t *) data;
695  if (*address != *pData)
696  {
697  retval = MSC_LoadVerifyAddress(address);
698  if (mscReturnOk == retval)
699  {
700  retval = MSC_LoadWriteData(pData, 1, writeStrategy);
701  }
702  }
703 #endif
704 
705  /* Disable writing to the MSC */
706  MSC->WRITECTRL &= ~MSC_WRITECTRL_WREN;
707 
708 #if defined( _MSC_WRITECTRL_WDOUBLE_MASK )
709 #if ( WORDS_PER_DATA_PHASE == 2 )
710  /* Turn off double word write cycle support. */
711  MSC->WRITECTRL &= ~MSC_WRITECTRL_WDOUBLE;
712 #endif
713 #endif
714 
715  return retval;
716 }
718 
722 /***************************************************************************/
748 MSC_Status_TypeDef MSC_ErasePage(uint32_t *startAddress)
749 {
750  uint32_t timeOut = MSC_PROGRAM_TIMEOUT;
751 
752  /* Address must be aligned to pages */
753  EFM_ASSERT((((uint32_t) startAddress) & (FLASH_PAGE_SIZE - 1)) == 0);
754 #if defined( _EMU_STATUS_VSCALE_MASK )
755  /* VSCALE must be done and flash erase requires VSCALE2 */
756  EFM_ASSERT(!(EMU->STATUS & _EMU_STATUS_VSCALEBUSY_MASK));
757  EFM_ASSERT((EMU->STATUS & _EMU_STATUS_VSCALE_MASK) == EMU_STATUS_VSCALE_VSCALE2);
758 #endif
759 
760  /* Enable writing to the MSC */
761  MSC->WRITECTRL |= MSC_WRITECTRL_WREN;
762 
763  /* Load address */
764  MSC->ADDRB = (uint32_t)startAddress;
765  MSC->WRITECMD = MSC_WRITECMD_LADDRIM;
766 
767  /* Check for invalid address */
768  if (MSC->STATUS & MSC_STATUS_INVADDR)
769  {
770  /* Disable writing to the MSC */
771  MSC->WRITECTRL &= ~MSC_WRITECTRL_WREN;
772  return mscReturnInvalidAddr;
773  }
774  /* Check for write protected page */
775  if (MSC->STATUS & MSC_STATUS_LOCKED)
776  {
777  /* Disable writing to the MSC */
778  MSC->WRITECTRL &= ~MSC_WRITECTRL_WREN;
779  return mscReturnLocked;
780  }
781  /* Send erase page command */
782  MSC->WRITECMD = MSC_WRITECMD_ERASEPAGE;
783 
784  /* Wait for the erase to complete */
785  while ((MSC->STATUS & MSC_STATUS_BUSY) && (timeOut != 0))
786  {
787  timeOut--;
788  }
789  if (timeOut == 0)
790  {
791  /* Disable writing to the MSC */
792  MSC->WRITECTRL &= ~MSC_WRITECTRL_WREN;
793  return mscReturnTimeOut;
794  }
795  /* Disable writing to the MSC */
796  MSC->WRITECTRL &= ~MSC_WRITECTRL_WREN;
797  return mscReturnOk;
798 }
800 
801 
802 /***************************************************************************/
840  void const *data,
841  uint32_t numBytes)
842 {
843  return MSC_WriteWordI(address, data, numBytes, mscWriteIntSafe);
844 }
846 
847 
848 #if !defined( _EFM32_GECKO_FAMILY )
849 /***************************************************************************/
884  void const *data,
885  uint32_t numBytes)
886 {
887  return MSC_WriteWordI(address, data, numBytes, mscWriteFast);
888 }
890 
891 #endif
892 
893 
894 #if defined( _MSC_MASSLOCK_MASK )
895 /***************************************************************************/
907 {
908  /* Enable writing to the MSC */
909  MSC->WRITECTRL |= MSC_WRITECTRL_WREN;
910 
911  /* Unlock device mass erase */
912  MSC->MASSLOCK = MSC_MASSLOCK_LOCKKEY_UNLOCK;
913 
914  /* Erase first 512K block */
915  MSC->WRITECMD = MSC_WRITECMD_ERASEMAIN0;
916 
917  /* Waiting for erase to complete */
918  while ((MSC->STATUS & MSC_STATUS_BUSY));
919 
920 #if ((FLASH_SIZE >= (512 * 1024)) && defined( _MSC_WRITECMD_ERASEMAIN1_MASK ))
921  /* Erase second 512K block */
922  MSC->WRITECMD = MSC_WRITECMD_ERASEMAIN1;
923 
924  /* Waiting for erase to complete */
925  while ((MSC->STATUS & MSC_STATUS_BUSY));
926 #endif
927 
928  /* Restore mass erase lock */
929  MSC->MASSLOCK = MSC_MASSLOCK_LOCKKEY_LOCK;
930 
931  /* This will only successfully return if calling function is also in SRAM */
932  return mscReturnOk;
933 }
935 
936 #endif
937 
940 #endif /* defined(MSC_COUNT) && (MSC_COUNT > 0) */
Clock management unit (CMU) API.
#define MSC_TIMEBASE_PERIOD_5US
Definition: efm32hg_msc.h:388
uint32_t SystemCoreClockGet(void)
Get the current core clock frequency.
Emlib peripheral API "assert" implementation.
#define MSC_MASSLOCK_LOCKKEY_UNLOCK
Definition: efm32hg_msc.h:404
#define MSC_WRITECMD_ERASEPAGE
Definition: efm32hg_msc.h:135
#define FLASH_PAGE_SIZE
#define MSC_STATUS_INVADDR
Definition: efm32hg_msc.h:200
#define _MSC_TIMEBASE_BASE_MASK
Definition: efm32hg_msc.h:377
#define MSC_WRITECMD_ERASEMAIN0
Definition: efm32hg_msc.h:160
#define MSC_READCTRL_MODE_WS0
Definition: efm32hg_msc.h:94
MSC_RAMFUNC_DECLARATOR MSC_Status_TypeDef MSC_MassErase(void)
Erase entire flash in one operation.
Definition: em_msc.c:906
#define MSC_WRITECMD_WRITEONCE
Definition: efm32hg_msc.h:145
void MSC_Init(void)
Enables the flash controller for writing.
Definition: em_msc.c:157
void MSC_Deinit(void)
Disables the flash controller for writing.
Definition: em_msc.c:218
#define MSC_RAMFUNC_DEFINITION_END
Expands to SL_RAMFUNC_DEFINITION_END if EM_MSC_RUN_FROM_FLASH is undefined and to nothing if EM_MSC_R...
Definition: em_msc.h:463
#define MSC_UNLOCK_CODE
#define MSC_WRITECTRL_WREN
Definition: efm32hg_msc.h:116
#define MSC_PROGRAM_TIMEOUT
The timeout used while waiting for the flash to become ready after a write. This number indicates the...
Definition: em_msc.h:110
void MSC_ExecConfigSet(MSC_ExecConfig_TypeDef *execConfig)
Set MSC code execution configuration.
Definition: em_msc.c:234
#define _MSC_TIMEBASE_PERIOD_MASK
Definition: efm32hg_msc.h:382
Flash controller (MSC) peripheral API.
#define _MSC_READCTRL_MODE_MASK
Definition: efm32hg_msc.h:90
#define MSC_WRITECMD_WRITETRIG
Definition: efm32hg_msc.h:150
#define MSC_TIMEBASE_PERIOD_1US
Definition: efm32hg_msc.h:387
#define MSC_RAMFUNC_DECLARATOR
Expands to SL_RAMFUNC_DECLARATOR if EM_MSC_RUN_FROM_FLASH is undefined and to nothing if EM_MSC_RUN_F...
Definition: em_msc.h:459
MSC_RAMFUNC_DECLARATOR MSC_Status_TypeDef MSC_WriteWordFast(uint32_t *address, void const *data, uint32_t numBytes)
Writes data to flash memory. This function is faster than MSC_WriteWord(), but it disables interrupts...
Definition: em_msc.c:883
#define MSC_READCTRL_AIDIS
Definition: efm32hg_msc.h:102
#define MSC_STATUS_LOCKED
Definition: efm32hg_msc.h:195
MSC_RAMFUNC_DECLARATOR MSC_Status_TypeDef MSC_WriteWord(uint32_t *address, void const *data, uint32_t numBytes)
Writes data to flash memory. This function is interrupt safe, but slower than MSC_WriteWordFast(), which writes to flash with interrupts disabled. Write data must be aligned to words and contain a number of bytes that is divisable by four.
Definition: em_msc.c:839
#define MSC_STATUS_BUSY
Definition: efm32hg_msc.h:190
#define _MSC_TIMEBASE_BASE_SHIFT
Definition: efm32hg_msc.h:376
#define MSC_STATUS_WORDTIMEOUT
Definition: efm32hg_msc.h:210
#define MSC_WRITECMD_LADDRIM
Definition: efm32hg_msc.h:130
MSC_Status_TypeDef
Definition: em_msc.h:133
#define MSC
#define MSC_READCTRL_MODE_WS1
Definition: efm32hg_msc.h:96
uint32_t SystemCoreClock
System System Clock Frequency (Core Clock).
#define EMU
#define MSC_MASSLOCK_LOCKKEY_LOCK
Definition: efm32hg_msc.h:400
System API.
#define MSC_RAMFUNC_DEFINITION_BEGIN
Expands to SL_RAMFUNC_DEFINITION_BEGIN if EM_MSC_RUN_FROM_FLASH is undefined and to nothing if EM_MSC...
Definition: em_msc.h:461
#define MSC_READCTRL_IFCDIS
Definition: efm32hg_msc.h:97
uint32_t CMU_ClockFreqGet(CMU_Clock_TypeDef clock)
Get clock frequency for a clock point.
Definition: em_cmu.c:1550
#define MSC_STATUS_WDATAREADY
Definition: efm32hg_msc.h:205
MSC_RAMFUNC_DECLARATOR MSC_Status_TypeDef MSC_ErasePage(uint32_t *startAddress)
Erases a page in flash memory.
Definition: em_msc.c:748