1 /***************************************************************************//**
2 * @file
3 * @brief Flash controller (MSC) Peripheral API
4 *******************************************************************************
5 * # License
6 * <b>Copyright 2018 Silicon Laboratories Inc. www.silabs.com</b>
7 *******************************************************************************
8 *
9 * SPDX-License-Identifier: Zlib
10 *
11 * The licensor of this software is Silicon Laboratories Inc.
12 *
13 * This software is provided 'as-is', without any express or implied
14 * warranty. In no event will the authors be held liable for any damages
15 * arising from the use of this software.
16 *
17 * Permission is granted to anyone to use this software for any purpose,
18 * including commercial applications, and to alter it and redistribute it
19 * freely, subject to the following restrictions:
20 *
21 * 1. The origin of this software must not be misrepresented; you must not
22 * claim that you wrote the original software. If you use this software
23 * in a product, an acknowledgment in the product documentation would be
24 * appreciated but is not required.
25 * 2. Altered source versions must be plainly marked as such, and must not be
26 * misrepresented as being the original software.
27 * 3. This notice may not be removed or altered from any source distribution.
28 *
29 ******************************************************************************/
30
31 #include "em_msc.h"
32 #if defined(MSC_COUNT) && (MSC_COUNT > 0)
33
34 #include "sl_assert.h"
35 #include "em_cmu.h"
36 #include "sl_common.h"
37 #include "em_core.h"
38 #include "em_system.h"
39
40 /** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
41
42 #if defined(__ICCARM__)
43 /* Suppress warnings originating from use of EFM_ASSERT() with IAR Embedded Workbench */
44 #pragma diag_suppress=Ta022,Ta023
45 #endif
46
47 #if defined(EM_MSC_RUN_FROM_FLASH) && defined(_EFM32_GECKO_FAMILY)
48 #error "Running Flash write/erase operations from Flash is not supported on EFM32G."
49 #endif
50
51 /*******************************************************************************
52 ****************************** DEFINES ******************************
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 #define FLASH_PAGE_MASK (~(FLASH_PAGE_SIZE - 1U))
66
67 #if defined(_MSC_ECCCTRL_MASK) \
68 || defined(_SYSCFG_DMEM0ECCCTRL_MASK) \
69 || defined(_MPAHBRAM_CTRL_MASK)
70 #if defined(_SILICON_LABS_32B_SERIES_1_CONFIG_1)
71 /* On Series 1 Config 1 EFM32GG11, ECC is supported for RAM0 and RAM1
72 banks (not RAM2). It is necessary to figure out which is biggest to
73 calculate the number of DMA descriptors needed. */
74 #define ECC_RAM_SIZE_MAX (SL_MAX(RAM0_MEM_SIZE, RAM1_MEM_SIZE))
75
76 #define ECC_RAM0_MEM_BASE (RAM0_MEM_BASE)
77 #define ECC_RAM0_MEM_SIZE (RAM0_MEM_SIZE)
78
79 #define ECC_RAM1_MEM_BASE (RAM1_MEM_BASE)
80 #define ECC_RAM1_MEM_SIZE (RAM1_MEM_SIZE)
81
82 #define ECC_CTRL_REG (MSC->ECCCTRL)
83 #define ECC_RAM0_SYNDROMES_INIT (MSC_ECCCTRL_RAMECCEWEN)
84 #define ECC_RAM0_CORRECTION_EN (MSC_ECCCTRL_RAMECCCHKEN)
85 #define ECC_RAM1_SYNDROMES_INIT (MSC_ECCCTRL_RAM1ECCEWEN)
86 #define ECC_RAM1_CORRECTION_EN (MSC_ECCCTRL_RAM1ECCCHKEN)
87
88 #define ECC_IFC_REG (MSC->IFC)
89 #define ECC_IFC_MASK (MSC_IFC_RAMERR1B | MSC_IFC_RAMERR2B \
90 | MSC_IFC_RAM1ERR1B | MSC_IFC_RAM1ERR2B)
91
92 #define ECC_FAULT_CTRL_REG (MSC->CTRL)
93 #define ECC_FAULT_EN (MSC_CTRL_RAMECCERRFAULTEN)
94
95 #elif defined(_SILICON_LABS_GECKO_INTERNAL_SDID_106)
96 /* On Series 1 Config 2 EFM32GG12, ECC is supported for RAM0, RAM1 and
97 RAM2 banks. All banks are of equal size. */
98 #define ECC_RAM_SIZE_MAX (RAM0_MEM_SIZE)
99
100 #define ECC_RAM0_MEM_BASE (RAM0_MEM_BASE)
101 #define ECC_RAM0_MEM_SIZE (RAM0_MEM_SIZE)
102
103 #define ECC_RAM1_MEM_BASE (RAM1_MEM_BASE)
104 #define ECC_RAM1_MEM_SIZE (RAM1_MEM_SIZE)
105
106 #define ECC_RAM2_MEM_BASE (RAM2_MEM_BASE)
107 #define ECC_RAM2_MEM_SIZE (RAM2_MEM_SIZE)
108
109 #define ECC_CTRL_REG (MSC->ECCCTRL)
110 #define ECC_RAM0_SYNDROMES_INIT (MSC_ECCCTRL_RAMECCEWEN)
111 #define ECC_RAM0_CORRECTION_EN (MSC_ECCCTRL_RAMECCCHKEN)
112 #define ECC_RAM1_SYNDROMES_INIT (MSC_ECCCTRL_RAM1ECCEWEN)
113 #define ECC_RAM1_CORRECTION_EN (MSC_ECCCTRL_RAM1ECCCHKEN)
114 #define ECC_RAM2_SYNDROMES_INIT (MSC_ECCCTRL_RAM2ECCEWEN)
115 #define ECC_RAM2_CORRECTION_EN (MSC_ECCCTRL_RAM2ECCCHKEN)
116
117 #define ECC_IFC_REG (MSC->IFC)
118 #define ECC_IFC_MASK (MSC_IFC_RAMERR1B | MSC_IFC_RAMERR2B \
119 | MSC_IFC_RAM1ERR1B | MSC_IFC_RAM1ERR2B \
120 | MSC_IFC_RAM2ERR1B | MSC_IFC_RAM2ERR2B)
121
122 #define ECC_FAULT_CTRL_REG (MSC->CTRL)
123 #define ECC_FAULT_EN (MSC_CTRL_RAMECCERRFAULTEN)
124
125 #elif defined(_SILICON_LABS_32B_SERIES_2)
126
127 #if defined(_SILICON_LABS_32B_SERIES_2_CONFIG_1)
128
129 /* On Series 2 Config 1, aka EFR32XG21, ECC is supported for the
130 main DMEM RAM banks which is controlled with one ECC encoder/decoder. */
131 #define ECC_RAM0_SYNDROMES_INIT (SYSCFG_DMEM0ECCCTRL_RAMECCEWEN)
132 #define ECC_RAM0_CORRECTION_EN (SYSCFG_DMEM0ECCCTRL_RAMECCCHKEN)
133
134 #elif (defined(_SILICON_LABS_32B_SERIES_2_CONFIG_2) \
135 || defined(_SILICON_LABS_32B_SERIES_2_CONFIG_7))
136
137 /* On Series 2 Config 2, aka EFR32XG22, ECC is supported for the
138 main DMEM RAM banks which is controlled with one ECC encoder/decoder. */
139 #define ECC_RAM0_SYNDROMES_INIT (SYSCFG_DMEM0ECCCTRL_RAMECCEN)
140 #define ECC_RAM0_CORRECTION_EN (SYSCFG_DMEM0ECCCTRL_RAMECCEWEN)
141
142 #define ECC_IF_REG (SYSCFG->IF)
143 #define ECC_IF_1BIT_ERROR (SYSCFG_IF_RAMERR1B)
144
145 #elif defined(_MPAHBRAM_CTRL_MASK)
146
147 /* From Series 2 Config 3, aka EFR32XG23, ECC is now standalone in the
148 * MPAHBRAM module */
149 #define ECC_RAM0_SYNDROMES_INIT (MPAHBRAM_CTRL_ECCWEN)
150 #define ECC_RAM0_CORRECTION_EN (MPAHBRAM_CTRL_ECCEN)
151
152 #define ECC_IF_REG (DMEM->IF)
153 /* number of AHB ports is between 1 and 4 */
154 #if defined(MPAHBRAM_IF_AHB3ERR1B)
155 #define ECC_IF_1BIT_ERROR (MPAHBRAM_IF_AHB0ERR1B | MPAHBRAM_IF_AHB1ERR1B | MPAHBRAM_IF_AHB2ERR1B | MPAHBRAM_IF_AHB3ERR1B)
156 #elif defined(MPAHBRAM_IF_AHB2ERR1B)
157 #define ECC_IF_1BIT_ERROR (MPAHBRAM_IF_AHB0ERR1B | MPAHBRAM_IF_AHB1ERR1B | MPAHBRAM_IF_AHB2ERR1B)
158 #elif defined(MPAHBRAM_IF_AHB1ERR1B)
159 #define ECC_IF_1BIT_ERROR (MPAHBRAM_IF_AHB0ERR1B | MPAHBRAM_IF_AHB1ERR1B)
160 #else
161 #define ECC_IF_1BIT_ERROR (MPAHBRAM_IF_AHB0ERR1B)
162 #endif
163
164 #else
165
166 #error "Unknown device"
167
168 #endif /* #if defined(if defined(_SILICON_LABS_32B_SERIES_2_CONFIG_1) */
169
170 #define ECC_RAM_SIZE_MAX (RAM_MEM_SIZE)
171 #define ECC_RAM0_MEM_BASE (SRAM_BASE)
172 #define ECC_RAM0_MEM_SIZE (SRAM_SIZE)
173
174 #if (defined(_SILICON_LABS_32B_SERIES_2_CONFIG_1) \
175 || defined(_SILICON_LABS_32B_SERIES_2_CONFIG_2) \
176 || defined(_SILICON_LABS_32B_SERIES_2_CONFIG_7))
177 #define ECC_CTRL_REG (SYSCFG->DMEM0ECCCTRL)
178 #define ECC_IFC_REG (SYSCFG->IF_CLR)
179 #define ECC_IFC_MASK (SYSCFG_IF_RAMERR1B | SYSCFG_IF_RAMERR2B)
180 #define ECC_FAULT_CTRL_REG (SYSCFG->CTRL)
181 #define ECC_FAULT_EN (SYSCFG_CTRL_RAMECCERRFAULTEN)
182
183 #elif defined(_MPAHBRAM_CTRL_MASK)
184 #define ECC_CTRL_REG (DMEM->CTRL)
185 #define ECC_IFC_REG (DMEM->IF_CLR)
186 #define ECC_IFC_MASK (_MPAHBRAM_IF_MASK)
187 #define ECC_FAULT_CTRL_REG (DMEM->CTRL)
188 #define ECC_FAULT_EN (MPAHBRAM_CTRL_ECCERRFAULTEN)
189 #endif
190
191 #else
192
193 #error Unknown device.
194
195 #endif
196
197 #define ECC_DMA_MAX_XFERCNT (_LDMA_CH_CTRL_XFERCNT_MASK \
198 >> _LDMA_CH_CTRL_XFERCNT_SHIFT)
199 #define ECC_DMA_DESC_SIZE ((ECC_DMA_MAX_XFERCNT + 1) * 4) /* 4 bytes units */
200
201 #define ECC_DMA_DESCS (ECC_RAM_SIZE_MAX / ECC_DMA_DESC_SIZE)
202
203 #endif /* #if defined(_MSC_ECCCTRL_MASK) */
204
205 /***************************************************************************//**
206 * @brief
207 * Get locked status of the MSC registers.
208 *
209 * @detail
210 * MSC_IS_LOCKED() is implemented as a macro because it's used inside functions
211 * that can be placed either in flash or in RAM.
212 ******************************************************************************/
213 #if defined(_MSC_STATUS_REGLOCK_MASK)
214 #define MSC_IS_LOCKED() ((MSC->STATUS & _MSC_STATUS_REGLOCK_MASK) != 0U)
215 #else
216 #define MSC_IS_LOCKED() ((MSC->LOCK & _MSC_LOCK_MASK) != 0U)
217 #endif
218
219 /*******************************************************************************
220 ****************************** TYPEDEFS ******************************
221 ******************************************************************************/
222
223 #if defined(_MSC_ECCCTRL_MASK) \
224 || defined(_SYSCFG_DMEM0ECCCTRL_MASK) \
225 || defined(_MPAHBRAM_CTRL_MASK)
226 typedef struct {
227 uint32_t initSyndromeEnable;
228 uint32_t correctionEnable;
229 uint32_t base;
230 uint32_t size;
231 } MSC_EccBank_Typedef;
232
233 #endif
234
235 /*******************************************************************************
236 ****************************** LOCALS *******************************
237 ******************************************************************************/
238 #if defined(_MSC_ECCCTRL_MASK) \
239 || defined(_SYSCFG_DMEM0ECCCTRL_MASK) \
240 || defined(_MPAHBRAM_CTRL_MASK)
241 static const MSC_EccBank_Typedef eccBankTbl[MSC_ECC_BANKS] =
242 {
243 {
244 ECC_RAM0_SYNDROMES_INIT, ECC_RAM0_CORRECTION_EN,
245 ECC_RAM0_MEM_BASE, ECC_RAM0_MEM_SIZE
246 },
247 #if MSC_ECC_BANKS > 1
248 {
249 ECC_RAM1_SYNDROMES_INIT, ECC_RAM1_CORRECTION_EN,
250 ECC_RAM1_MEM_BASE, ECC_RAM1_MEM_SIZE
251 },
252 #if MSC_ECC_BANKS > 2
253 {
254 ECC_RAM2_SYNDROMES_INIT, ECC_RAM2_CORRECTION_EN,
255 ECC_RAM2_MEM_BASE, ECC_RAM2_MEM_SIZE
256 },
257 #endif
258 #endif
259 };
260 #endif
261
262 /*******************************************************************************
263 ****************************** FUNCTIONS ******************************
264 ******************************************************************************/
265 MSC_RAMFUNC_DECLARATOR MSC_Status_TypeDef
266 MSC_WriteWordI(uint32_t *address,
267 void const *data,
268 uint32_t numBytes);
269
270 MSC_RAMFUNC_DECLARATOR MSC_Status_TypeDef
271 MSC_LoadWriteData(uint32_t* data,
272 uint32_t numWords);
273
274 MSC_RAMFUNC_DECLARATOR MSC_Status_TypeDef
275 MSC_LoadVerifyAddress(uint32_t* address);
276
277 /** @endcond */
278
279 /***************************************************************************//**
280 * @addtogroup msc
281 * @{
282 ******************************************************************************/
283
284 /*******************************************************************************
285 ************************** GLOBAL FUNCTIONS *******************************
286 ******************************************************************************/
287
288 #if defined(_SILICON_LABS_32B_SERIES_2)
289
290 /** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
291
292 /***************************************************************************//**
293 * @brief
294 * Wait for a specified MSC status or timeout.
295 *
296 * @param[in] mask
297 * MSC->STATUS register mask to apply when testing for specified status.
298 * @param[in] value
299 * The value the MSC->STATUS test is waiting to see.
300 * @return
301 * Returns the status of a write or erase operation, @ref MSC_Status_TypeDef
302 * @verbatim
303 * mscReturnOk - Specified status criteria fulfilled.
304 * mscReturnInvalidAddr - Operation tried to write or erase a non-flash area.
305 * flashReturnLocked - MSC registers are locked or the operation tried to
306 * write or erase a locked area of the flash.
307 * flashReturnTimeOut - Operation timed out.
308 * @endverbatim
309 ******************************************************************************/
310 MSC_RAMFUNC_DEFINITION_BEGIN
mscStatusWait(uint32_t mask,uint32_t value)311 msc_Return_TypeDef mscStatusWait(uint32_t mask, uint32_t value)
312 {
313 uint32_t timeOut = MSC_PROGRAM_TIMEOUT;
314
315 while (timeOut) {
316 uint32_t status = MSC->STATUS;
317
318 /* if INVADDR is asserted by MSC, BUSY will never go high, can be checked early */
319 if (status & MSC_STATUS_INVADDR) {
320 return mscReturnInvalidAddr;
321 }
322
323 /*
324 * if requested operation fails because flash is locked, BUSY will be high
325 * for a few cycles and it's not safe to clear WRITECTRL.WREN during that
326 * period. mscStatusWait should return only when it's safe to do so.
327 *
328 * So if user is checking BUSY flag, make sure it matches user's expected
329 * value and only then check the lock bits. Otherwise, do check early and
330 * bail out if necessary.
331 */
332
333 if ((!(mask & MSC_STATUS_BUSY))
334 && (status & (MSC_STATUS_LOCKED | MSC_STATUS_REGLOCK))) {
335 return mscReturnLocked;
336 }
337
338 if ((status & mask) == value) {
339 if (status & (MSC_STATUS_LOCKED | MSC_STATUS_REGLOCK)) {
340 return mscReturnLocked;
341 } else {
342 return mscReturnOk;
343 }
344 }
345
346 timeOut--;
347 }
348
349 return mscReturnTimeOut;
350 }
351 MSC_RAMFUNC_DEFINITION_END
352
353 /***************************************************************************//**
354 * @brief
355 * Writes data to flash memory. It is assumed that start address is word
356 * aligned and that numBytes is an integer multiple of four, and that the
357 * write operation does not cross a flash page boundary.
358 *
359 * @param[in] address
360 * Pointer to the flash word to write to. Must be aligned to words.
361 * @param[in] data
362 * Data to write to flash.
363 * @param[in] numBytes
364 * Number of bytes to write to flash. NB: Must be divisable by four.
365 * @return
366 * Returns the status of the write operation, @ref MSC_Status_TypeDef
367 * @verbatim
368 * flashReturnOk - Operation completed successfully.
369 * flashReturnInvalidAddr - Operation tried to write to a non-flash area.
370 * flashReturnLocked - MSC registers are locked or the operation tried to
371 * program a locked area of the flash.
372 * flashReturnTimeOut - Operation timed out.
373 * @endverbatim
374 ******************************************************************************/
375 MSC_RAMFUNC_DEFINITION_BEGIN
writeBurst(uint32_t address,const uint32_t * data,uint32_t numBytes)376 msc_Return_TypeDef writeBurst(uint32_t address,
377 const uint32_t *data,
378 uint32_t numBytes)
379 {
380 msc_Return_TypeDef retVal;
381
382 MSC->ADDRB = address;
383
384 if (MSC->STATUS & MSC_STATUS_INVADDR) {
385 return mscReturnInvalidAddr;
386 }
387
388 MSC->WDATA = *data++;
389 numBytes -= 4;
390
391 while (numBytes) {
392 retVal = mscStatusWait(MSC_STATUS_WDATAREADY, MSC_STATUS_WDATAREADY);
393
394 if (retVal != mscReturnOk) {
395 MSC->WRITECMD = MSC_WRITECMD_WRITEEND;
396 return retVal;
397 }
398
399 MSC->WDATA = *data++;
400 numBytes -= 4;
401 }
402
403 MSC->WRITECMD = MSC_WRITECMD_WRITEEND;
404
405 retVal = mscStatusWait((MSC_STATUS_BUSY | MSC_STATUS_PENDING), 0);
406
407 if (retVal == mscReturnOk) {
408 // We need to check twice to be sure
409 retVal = mscStatusWait((MSC_STATUS_BUSY | MSC_STATUS_PENDING), 0);
410 }
411
412 return retVal;
413 }
414 MSC_RAMFUNC_DEFINITION_END
415
416 /** @endcond */
417
418 /***************************************************************************//**
419 * @brief
420 * Initialize MSC module. Puts MSC hw in a known state.
421 ******************************************************************************/
MSC_Init(void)422 void MSC_Init(void)
423 {
424 #if defined(_CMU_CLKEN1_MASK)
425 CMU->CLKEN1_SET = CMU_CLKEN1_MSC;
426 #endif
427 // Unlock MSC
428 MSC->LOCK = MSC_LOCK_LOCKKEY_UNLOCK;
429 // Disable flash write
430 MSC->WRITECTRL_CLR = MSC_WRITECTRL_WREN;
431 }
432
433 /***************************************************************************//**
434 * @brief
435 * Turn off MSC flash write enable and lock MSC registers.
436 ******************************************************************************/
MSC_Deinit(void)437 void MSC_Deinit(void)
438 {
439 // Unlock MSC
440 MSC->LOCK = MSC_LOCK_LOCKKEY_UNLOCK;
441 // Disable flash write
442 MSC->WRITECTRL_CLR = MSC_WRITECTRL_WREN;
443 // Lock MSC
444 MSC->LOCK = MSC_LOCK_LOCKKEY_LOCK;
445 #if defined(_CMU_CLKEN1_MASK)
446 CMU->CLKEN1_CLR = CMU_CLKEN1_MSC;
447 #endif
448 }
449
450 /***************************************************************************//**
451 * @brief
452 * Set MSC code execution configuration
453 *
454 * @param[in] execConfig
455 * Code execution configuration
456 ******************************************************************************/
MSC_ExecConfigSet(MSC_ExecConfig_TypeDef * execConfig)457 void MSC_ExecConfigSet(MSC_ExecConfig_TypeDef *execConfig)
458 {
459 uint32_t mscReadCtrl;
460
461 #if defined(MSC_RDATACTRL_DOUTBUFEN)
462 mscReadCtrl = MSC->RDATACTRL & ~MSC_RDATACTRL_DOUTBUFEN;
463
464 if (execConfig->doutBufEn) {
465 mscReadCtrl |= MSC_RDATACTRL_DOUTBUFEN;
466 }
467
468 MSC->RDATACTRL = mscReadCtrl;
469 #elif defined(MSC_READCTRL_DOUTBUFEN)
470 mscReadCtrl = MSC->READCTRL & ~MSC_READCTRL_DOUTBUFEN;
471
472 if (execConfig->doutBufEn) {
473 mscReadCtrl |= MSC_READCTRL_DOUTBUFEN;
474 }
475 MSC->READCTRL = mscReadCtrl;
476 #endif
477 }
478
479 /***************************************************************************//**
480 * @brief
481 * Erases a page in flash memory.
482 *
483 * For IAR Embedded Workbench, Simplicity Studio and GCC this will be achieved
484 * automatically by using attributes in the function proctype. For Keil
485 * uVision you must define a section called "ram_code" and place this manually
486 * in your project's scatter file.
487 *
488 * @param[in] startAddress
489 * Pointer to the flash page to erase. Must be aligned to beginning of page
490 * boundary.
491 * @return
492 * Returns the status of erase operation, @ref MSC_Status_TypeDef
493 * @verbatim
494 * mscReturnOk - Operation completed successfully.
495 * mscReturnInvalidAddr - Operation tried to erase a non-flash area.
496 * flashReturnLocked - MSC registers are locked or the operation tried to
497 * erase a locked area of the flash.
498 * flashReturnTimeOut - Operation timed out.
499 * @endverbatim
500 ******************************************************************************/
501 MSC_RAMFUNC_DEFINITION_BEGIN
MSC_ErasePage(uint32_t * startAddress)502 MSC_Status_TypeDef MSC_ErasePage(uint32_t *startAddress)
503 {
504 MSC_Status_TypeDef retVal;
505 bool wasLocked;
506
507 // Address must be aligned to page boundary
508 EFM_ASSERT((((uint32_t)startAddress) & (FLASH_PAGE_SIZE - 1U)) == 0);
509
510 #if defined(_CMU_CLKEN1_MASK)
511 CMU->CLKEN1_SET = CMU_CLKEN1_MSC;
512 #endif
513 wasLocked = MSC_IS_LOCKED();
514 MSC->LOCK = MSC_LOCK_LOCKKEY_UNLOCK;
515
516 MSC->WRITECTRL_SET = MSC_WRITECTRL_WREN;
517 MSC->ADDRB = (uint32_t)startAddress;
518 MSC->WRITECMD = MSC_WRITECMD_ERASEPAGE;
519
520 retVal = mscStatusWait((MSC_STATUS_BUSY | MSC_STATUS_PENDING), 0);
521
522 if (retVal == mscReturnOk) {
523 // We need to check twice to be sure
524 retVal = mscStatusWait((MSC_STATUS_BUSY | MSC_STATUS_PENDING), 0);
525 }
526
527 MSC->WRITECTRL_CLR = MSC_WRITECTRL_WREN;
528
529 if (wasLocked) {
530 MSC->LOCK = MSC_LOCK_LOCKKEY_LOCK;
531 }
532
533 return retVal;
534 }
535 MSC_RAMFUNC_DEFINITION_END
536
537 /***************************************************************************//**
538 * @brief
539 * Writes data to flash memory. Write data must be aligned to words and
540 * contain a number of bytes that is divisible by four.
541 * @note
542 * It is recommended to erase the flash page before performing a write.
543 *
544 * For IAR Embedded Workbench, Simplicity Studio and GCC this will be achieved
545 * automatically by using attributes in the function proctype. For Keil
546 * uVision you must define a section called "ram_code" and place this manually
547 * in your project's scatter file.
548 *
549 * The Flash memory is organized into 64-bit wide double-words.
550 * Each 64-bit double-word can be written only twice using burst write
551 * operation between erasing cycles. The user's application must store data in
552 * RAM to sustain burst write operation.
553 *
554 * EFR32XG21 RevC is not able to program every word twice before the next erase.
555 *
556 * @param[in] address
557 * Pointer to the flash word to write to. Must be aligned to words.
558 * @param[in] data
559 * Data to write to flash.
560 * @param[in] numBytes
561 * Number of bytes to write to flash. NB: Must be divisable by four.
562 * @return
563 * Returns the status of the write operation, @ref MSC_Status_TypeDef
564 * @verbatim
565 * flashReturnOk - Operation completed successfully.
566 * flashReturnInvalidAddr - Operation tried to write to a non-flash area.
567 * flashReturnLocked - MSC registers are locked or the operation tried to
568 * program a locked area of the flash.
569 * flashReturnTimeOut - Operation timed out.
570 * @endverbatim
571 ******************************************************************************/
572 MSC_RAMFUNC_DEFINITION_BEGIN
MSC_WriteWord(uint32_t * address,void const * data,uint32_t numBytes)573 MSC_Status_TypeDef MSC_WriteWord(uint32_t *address,
574 void const *data,
575 uint32_t numBytes)
576 {
577 uint32_t addr;
578 const uint8_t *pData;
579 uint32_t burstLen;
580 MSC_Status_TypeDef retVal = mscReturnOk;
581 bool wasLocked;
582
583 // Check alignment (must be aligned to words)
584 EFM_ASSERT(((uint32_t)address & 0x3U) == 0);
585 // Check number of bytes, must be divisable by four
586 EFM_ASSERT((numBytes & 0x3U) == 0);
587
588 #if defined(_CMU_CLKEN1_MASK)
589 CMU->CLKEN1_SET = CMU_CLKEN1_MSC;
590 #endif
591 wasLocked = MSC_IS_LOCKED();
592 MSC->LOCK = MSC_LOCK_LOCKKEY_UNLOCK;
593
594 // Enable flash write
595 MSC->WRITECTRL_SET = MSC_WRITECTRL_WREN;
596
597 addr = (uint32_t)address;
598 pData = (uint8_t*)data;
599
600 while (numBytes) {
601 // Max burst length is up to next flash page boundary
602 burstLen = SL_MIN(numBytes,
603 ((addr + FLASH_PAGE_SIZE) & FLASH_PAGE_MASK) - addr);
604
605 if ((retVal = writeBurst(addr, (const uint32_t*)pData, burstLen))
606 != mscReturnOk) {
607 break;
608 }
609
610 addr += burstLen;
611 pData += burstLen;
612 numBytes -= burstLen;
613 }
614
615 // Disable flash write
616 MSC->WRITECTRL_CLR = MSC_WRITECTRL_WREN;
617
618 if (wasLocked) {
619 MSC->LOCK = MSC_LOCK_LOCKKEY_LOCK;
620 }
621
622 return retVal;
623 }
624 MSC_RAMFUNC_DEFINITION_END
625
626 MSC_RAMFUNC_DEFINITION_BEGIN
MSC_MassErase(void)627 MSC_Status_TypeDef MSC_MassErase(void)
628 {
629 MSC_Status_TypeDef retVal;
630
631 if (MSC_IS_LOCKED()) {
632 return mscReturnLocked;
633 }
634
635 MSC->WRITECTRL_SET = MSC_WRITECTRL_WREN; // Set write enable bit
636 MSC->MISCLOCKWORD_CLR = MSC_MISCLOCKWORD_MELOCKBIT; // Enable Write ctrl access
637 MSC->WRITECMD = MSC_WRITECMD_ERASEMAIN0; // Start Mass erase procedure
638 retVal = mscStatusWait(MSC_STATUS_BUSY, 0); // Wait for end of busy flag or a problem (INVADDR, LOCK, REGLOCK, TIMEOUT)
639 MSC->MISCLOCKWORD_SET = MSC_MISCLOCKWORD_MELOCKBIT; // Reenable mass erase lock bit
640 MSC->WRITECTRL_CLR = MSC_WRITECTRL_WREN; // Disable Write ctrl access
641
642 return retVal;
643 }
644 MSC_RAMFUNC_DEFINITION_END
645
646 /***************************************************************************//**
647 * @brief
648 * Writes data to flash memory using the DMA.
649 *
650 * @details
651 * This function uses the LDMA to write data to the internal flash memory.
652 * This is the fastest way to write data to the flash and should be used when
653 * the application wants to achieve write speeds like they are reported in the
654 * datasheet. Note that copying data from flash to flash will be slower than
655 * copying from RAM to flash. So the source data must be in RAM in order to
656 * see the write speeds similar to the datasheet numbers.
657 *
658 * @note
659 * This function requires that the LDMA and LDMAXBAR clock is enabled.
660 *
661 * @param[in] ch
662 * DMA channel to use
663 *
664 * @param[in] address
665 * A pointer to the flash word to write to. Must be aligned to words.
666 *
667 * @param[in] data
668 * Data to write to flash.
669 *
670 * @param[in] numBytes
671 * A number of bytes to write from flash. NB: Must be divisible by four.
672 *
673 * @return
674 * Returns the status of the write operation.
675 * @verbatim
676 * flashReturnOk - The operation completed successfully.
677 * flashReturnInvalidAddr - The operation tried to erase a non-flash area.
678 * @endverbatim
679 ******************************************************************************/
MSC_WriteWordDma(int ch,uint32_t * address,const void * data,uint32_t numBytes)680 MSC_Status_TypeDef MSC_WriteWordDma(int ch,
681 uint32_t *address,
682 const void *data,
683 uint32_t numBytes)
684 {
685 uint32_t words = numBytes / 4;
686 uint32_t burstLen;
687 uint32_t src = (uint32_t) data;
688 uint32_t dst = (uint32_t) address;
689 bool wasLocked;
690
691 EFM_ASSERT((ch >= 0) && (ch < (int)DMA_CHAN_COUNT));
692
693 LDMA->EN_SET = 0x1;
694 LDMAXBAR->CH[ch].REQSEL = LDMAXBAR_CH_REQSEL_SOURCESEL_MSC
695 | LDMAXBAR_CH_REQSEL_SIGSEL_MSCWDATA;
696 LDMA->CH[ch].CFG = _LDMA_CH_CFG_RESETVALUE;
697 LDMA->CH[ch].LOOP = _LDMA_CH_LOOP_RESETVALUE;
698 LDMA->CH[ch].LINK = _LDMA_CH_LINK_RESETVALUE;
699
700 #if defined(_CMU_CLKEN1_MASK)
701 CMU->CLKEN1_SET = CMU_CLKEN1_MSC;
702 #endif
703 // Unlock MSC
704 wasLocked = MSC_IS_LOCKED();
705 MSC->LOCK = MSC_LOCK_LOCKKEY_UNLOCK;
706 // Enable writing to the MSC module.
707 MSC->WRITECTRL |= MSC_WRITECTRL_WREN;
708
709 while (numBytes) {
710 // Max burst length is up to next flash page boundary
711 burstLen = SL_MIN(numBytes,
712 ((dst + FLASH_PAGE_SIZE) & FLASH_PAGE_MASK) - dst);
713 words = burstLen / 4;
714
715 // Load the address.
716 MSC->ADDRB = dst;
717
718 // Check for an invalid address.
719 if (MSC->STATUS & MSC_STATUS_INVADDR) {
720 return mscReturnInvalidAddr;
721 }
722
723 LDMA->CH[ch].CTRL = LDMA_CH_CTRL_DSTINC_NONE
724 | LDMA_CH_CTRL_SIZE_WORD
725 | ((words - 1) << _LDMA_CH_CTRL_XFERCNT_SHIFT);
726 LDMA->CH[ch].SRC = (uint32_t)src;
727 LDMA->CH[ch].DST = (uint32_t)&MSC->WDATA;
728
729 // Enable channel
730 LDMA->CHEN_SET = (0x1 << ch);
731
732 while ((LDMA->CHDONE & (0x1 << ch)) == 0x0) {
733 ;
734 }
735
736 LDMA->CHDONE_CLR = (0x1 << ch);
737 LDMA->CHDIS_SET = (0x1 << ch);
738 MSC->WRITECMD = MSC_WRITECMD_WRITEEND;
739
740 dst += burstLen;
741 src += burstLen;
742 numBytes -= burstLen;
743 }
744
745 // Disable writing to the MSC module.
746 MSC->WRITECTRL &= ~MSC_WRITECTRL_WREN;
747 if (wasLocked) {
748 MSC->LOCK = MSC_LOCK_LOCKKEY_LOCK;
749 }
750
751 return mscReturnOk;
752 }
753
754 #else // defined(_SILICON_LABS_32B_SERIES_2)
755
756 /***************************************************************************//**
757 * @brief
758 * Enables the flash controller for writing.
759 * @note
760 * This function must be called before flash operations when
761 * AUXHFRCO clock has been changed from a default band.
762 ******************************************************************************/
MSC_Init(void)763 void MSC_Init(void)
764 {
765 #if defined(_MSC_TIMEBASE_MASK)
766 uint32_t freq, cycles;
767 #endif
768
769 #if defined(_EMU_STATUS_VSCALE_MASK) && defined(_SILICON_LABS_32B_SERIES_1)
770 /* VSCALE must be done. Flash erase and write requires VSCALE2. */
771 EFM_ASSERT(!(EMU->STATUS & _EMU_STATUS_VSCALEBUSY_MASK));
772 EFM_ASSERT((EMU->STATUS & _EMU_STATUS_VSCALE_MASK) == EMU_STATUS_VSCALE_VSCALE2);
773 #endif
774
775 /* Unlock the MSC module. */
776 MSC->LOCK = MSC_UNLOCK_CODE;
777 /* Disable writing to the Flash. */
778 MSC->WRITECTRL &= ~MSC_WRITECTRL_WREN;
779
780 #if defined(_MSC_TIMEBASE_MASK)
781 /* Configure MSC->TIMEBASE according to a selected frequency. */
782 freq = CMU_ClockFreqGet(cmuClock_AUX);
783
784 /* Timebase 5us is used for the 1/1.2 MHz band only. Note that the 1 MHz band
785 is tuned to 1.2 MHz on newer revisions. */
786 if (freq > 1200000) {
787 /* Calculate a number of clock cycles for 1 us as a base period. */
788 freq = (freq * 11) / 10;
789 cycles = (freq / 1000000) + 1;
790
791 /* Configure clock cycles for flash timing. */
792 MSC->TIMEBASE = (MSC->TIMEBASE & ~(_MSC_TIMEBASE_BASE_MASK
793 | _MSC_TIMEBASE_PERIOD_MASK))
794 | MSC_TIMEBASE_PERIOD_1US
795 | (cycles << _MSC_TIMEBASE_BASE_SHIFT);
796 } else {
797 /* Calculate a number of clock cycles for 5 us as a base period. */
798 freq = (freq * 5 * 11) / 10;
799 cycles = (freq / 1000000) + 1;
800
801 /* Configure clock cycles for flash timing */
802 MSC->TIMEBASE = (MSC->TIMEBASE & ~(_MSC_TIMEBASE_BASE_MASK
803 | _MSC_TIMEBASE_PERIOD_MASK))
804 | MSC_TIMEBASE_PERIOD_5US
805 | (cycles << _MSC_TIMEBASE_BASE_SHIFT);
806 }
807 #endif
808 }
809
810 /***************************************************************************//**
811 * @brief
812 * Disables the flash controller for writing.
813 ******************************************************************************/
MSC_Deinit(void)814 void MSC_Deinit(void)
815 {
816 /* Disable writing to the Flash. */
817 MSC->WRITECTRL &= ~MSC_WRITECTRL_WREN;
818 /* Lock the MSC module.*/
819 MSC->LOCK = 0;
820 }
821
822 /***************************************************************************//**
823 * @brief
824 * Set the MSC code execution configuration.
825 *
826 * @param[in] execConfig
827 * The code execution configuration.
828 ******************************************************************************/
MSC_ExecConfigSet(MSC_ExecConfig_TypeDef * execConfig)829 void MSC_ExecConfigSet(MSC_ExecConfig_TypeDef *execConfig)
830 {
831 uint32_t mscReadCtrl;
832
833 #if defined(MSC_READCTRL_MODE_WS0SCBTP)
834 mscReadCtrl = MSC->READCTRL & _MSC_READCTRL_MODE_MASK;
835 if ((mscReadCtrl == MSC_READCTRL_MODE_WS0) && (execConfig->scbtEn)) {
836 mscReadCtrl |= MSC_READCTRL_MODE_WS0SCBTP;
837 } else if ((mscReadCtrl == MSC_READCTRL_MODE_WS1) && (execConfig->scbtEn)) {
838 mscReadCtrl |= MSC_READCTRL_MODE_WS1SCBTP;
839 } else if ((mscReadCtrl == MSC_READCTRL_MODE_WS0SCBTP) && (!execConfig->scbtEn)) {
840 mscReadCtrl |= MSC_READCTRL_MODE_WS0;
841 } else if ((mscReadCtrl == MSC_READCTRL_MODE_WS1SCBTP) && (!execConfig->scbtEn)) {
842 mscReadCtrl |= MSC_READCTRL_MODE_WS1;
843 } else {
844 /* No change needed. */
845 }
846 #endif
847
848 mscReadCtrl = MSC->READCTRL & ~(0
849 #if defined(MSC_READCTRL_SCBTP)
850 | MSC_READCTRL_SCBTP
851 #endif
852 #if defined(MSC_READCTRL_USEHPROT)
853 | MSC_READCTRL_USEHPROT
854 #endif
855 #if defined(MSC_READCTRL_PREFETCH)
856 | MSC_READCTRL_PREFETCH
857 #endif
858 #if defined(MSC_READCTRL_ICCDIS)
859 | MSC_READCTRL_ICCDIS
860 #endif
861 #if defined(MSC_READCTRL_AIDIS)
862 | MSC_READCTRL_AIDIS
863 #endif
864 #if defined(MSC_READCTRL_IFCDIS)
865 | MSC_READCTRL_IFCDIS
866 #endif
867 );
868 mscReadCtrl |= (0
869 #if defined(MSC_READCTRL_SCBTP)
870 | (execConfig->scbtEn ? MSC_READCTRL_SCBTP : 0)
871 #endif
872 #if defined(MSC_READCTRL_USEHPROT)
873 | (execConfig->useHprot ? MSC_READCTRL_USEHPROT : 0)
874 #endif
875 #if defined(MSC_READCTRL_PREFETCH)
876 | (execConfig->prefetchEn ? MSC_READCTRL_PREFETCH : 0)
877 #endif
878 #if defined(MSC_READCTRL_ICCDIS)
879 | (execConfig->iccDis ? MSC_READCTRL_ICCDIS : 0)
880 #endif
881 #if defined(MSC_READCTRL_AIDIS)
882 | (execConfig->aiDis ? MSC_READCTRL_AIDIS : 0)
883 #endif
884 #if defined(MSC_READCTRL_IFCDIS)
885 | (execConfig->ifcDis ? MSC_READCTRL_IFCDIS : 0)
886 #endif
887 );
888
889 MSC->READCTRL = mscReadCtrl;
890 }
891
892 /** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
893
894 /***************************************************************************//**
895 * @brief
896 * Perform the address phase of the flash write cycle.
897 * @details
898 * This function performs the address phase of a flash write operation by
899 * writing the given flash address to the ADDRB register and issuing the
900 * LADDRIM command to load the address.
901 * @param[in] address
902 * An address in flash memory. Must be aligned at a 4 byte boundary.
903 * @return
904 * Returns the status of the address load operation, @ref MSC_Status_TypeDef
905 * @verbatim
906 * mscReturnOk - The operation completed successfully.
907 * mscReturnInvalidAddr - The operation tried to erase a non-flash area.
908 * mscReturnLocked - The operation tried to erase a locked area of the Flash.
909 * @endverbatim
910 ******************************************************************************/
911 MSC_RAMFUNC_DEFINITION_BEGIN
MSC_LoadVerifyAddress(uint32_t * address)912 MSC_Status_TypeDef MSC_LoadVerifyAddress(uint32_t* address)
913 {
914 uint32_t timeOut;
915
916 /* Wait for the MSC to become ready. */
917 timeOut = MSC_PROGRAM_TIMEOUT;
918 while ((MSC->STATUS & MSC_STATUS_BUSY) && (timeOut != 0)) {
919 timeOut--;
920 }
921
922 /* Check for timeout. */
923 if (timeOut == 0) {
924 return mscReturnTimeOut;
925 }
926 /* Load the address. */
927 MSC->ADDRB = (uint32_t)address;
928 MSC->WRITECMD = MSC_WRITECMD_LADDRIM;
929
930 /* Check for an invalid address. */
931 if (MSC->STATUS & MSC_STATUS_INVADDR) {
932 return mscReturnInvalidAddr;
933 }
934 return mscReturnOk;
935 }
936 MSC_RAMFUNC_DEFINITION_END
937
938 /***************************************************************************//**
939 * @brief
940 * Perform a flash data write phase.
941 * @details
942 * This function performs the data phase of a flash write operation by loading
943 * the given number of 32-bit words to the WDATA register.
944 * @param[in] data
945 * A pointer to the first data word to load.
946 * @param[in] numWords
947 * A number of data words (32-bit) to load.
948 * @return
949 * Returns the status of the data load operation.
950 * @verbatim
951 * mscReturnOk - An operation completed successfully.
952 * mscReturnTimeOut - An operation timed out waiting for the flash operation
953 * to complete.
954 * @endverbatim
955 ******************************************************************************/
956 MSC_RAMFUNC_DEFINITION_BEGIN
MSC_LoadWriteData(uint32_t * data,uint32_t numWords)957 MSC_Status_TypeDef MSC_LoadWriteData(uint32_t* data,
958 uint32_t numWords)
959 {
960 uint32_t timeOut;
961 uint32_t wordIndex;
962 bool useWDouble = false;
963 MSC_Status_TypeDef retval = mscReturnOk;
964
965 #if defined(_SILICON_LABS_32B_SERIES_0) && defined(_MSC_WRITECTRL_WDOUBLE_MASK)
966 /* If the LPWRITE (Low Power Write) is NOT enabled, set WDOUBLE (Write Double word). */
967 if (!(MSC->WRITECTRL & MSC_WRITECTRL_LPWRITE)) {
968 /* If the number of words to be written is odd, align by writing
969 a single word first, before setting the WDOUBLE bit. */
970 if (numWords & 0x1) {
971 /* Wait for the MSC to become ready for the next word. */
972 timeOut = MSC_PROGRAM_TIMEOUT;
973 while ((!(MSC->STATUS & MSC_STATUS_WDATAREADY)) && (timeOut != 0)) {
974 timeOut--;
975 }
976 /* Check for timeout. */
977 if (timeOut == 0) {
978 return mscReturnTimeOut;
979 }
980
981 /* Clear the double word option to write the initial single word. */
982 MSC->WRITECTRL &= ~MSC_WRITECTRL_WDOUBLE;
983 /* Write first data word. */
984 MSC->WDATA = *data++;
985 MSC->WRITECMD = MSC_WRITECMD_WRITEONCE;
986
987 /* Wait for the operation to finish. It may be required to change the WDOUBLE
988 configuration after the initial write. It should not be changed while BUSY. */
989 timeOut = MSC_PROGRAM_TIMEOUT;
990 while ((MSC->STATUS & MSC_STATUS_BUSY) && (timeOut != 0)) {
991 timeOut--;
992 }
993 /* Check for timeout. */
994 if (timeOut == 0) {
995 return mscReturnTimeOut;
996 }
997 /* Check for a write protected flash area. */
998 if (MSC->STATUS & MSC_STATUS_LOCKED) {
999 return mscReturnLocked;
1000 }
1001 /* Subtract this initial odd word for the write loop below. */
1002 numWords -= 1;
1003 retval = mscReturnOk;
1004 }
1005 /* Set the double word option to write two words per
1006 data phase. */
1007 MSC->WRITECTRL |= MSC_WRITECTRL_WDOUBLE;
1008 useWDouble = true;
1009 }
1010 #endif /* defined( _MSC_WRITECTRL_LPWRITE_MASK ) && defined( _MSC_WRITECTRL_WDOUBLE_MASK ) */
1011
1012 /* Write the rest as a double word write if wordsPerDataPhase == 2 */
1013 if (numWords > 0) {
1014 /* Requires a system core clock at 1MHz or higher */
1015 EFM_ASSERT(SystemCoreClock >= 1000000);
1016 wordIndex = 0;
1017 while (wordIndex < numWords) {
1018 if (!useWDouble) {
1019 MSC->WDATA = *data++;
1020 wordIndex++;
1021 MSC->WRITECMD = MSC_WRITECMD_WRITEONCE;
1022 } else {
1023 /* Trigger a double write according to flash properties. */
1024 #if defined(_SILICON_LABS_32B_SERIES_0) && defined(_MSC_WRITECTRL_WDOUBLE_MASK)
1025 MSC->WDATA = *data++;
1026 while (!(MSC->STATUS & MSC_STATUS_WDATAREADY)) ;
1027 MSC->WDATA = *data++;
1028 wordIndex += 2;
1029 MSC->WRITECMD = MSC_WRITECMD_WRITEONCE;
1030 #endif
1031 }
1032
1033 /* Wait for the transaction to finish. */
1034 timeOut = MSC_PROGRAM_TIMEOUT;
1035 while ((MSC->STATUS & MSC_STATUS_BUSY) && (timeOut != 0)) {
1036 timeOut--;
1037 }
1038 /* Check for a timeout. */
1039 if (timeOut == 0) {
1040 retval = mscReturnTimeOut;
1041 break;
1042 }
1043 /* Check for a write protected flash area. */
1044 if (MSC->STATUS & MSC_STATUS_LOCKED) {
1045 retval = mscReturnLocked;
1046 break;
1047 }
1048 #if defined(_EFM32_GECKO_FAMILY)
1049 MSC->ADDRB += 4;
1050 MSC->WRITECMD = MSC_WRITECMD_LADDRIM;
1051 #endif
1052 }
1053 }
1054
1055 #if defined(_MSC_WRITECTRL_WDOUBLE_MASK)
1056 /* Clear a double word option, which should not be left on when returning. */
1057 MSC->WRITECTRL &= ~MSC_WRITECTRL_WDOUBLE;
1058 #endif
1059
1060 return retval;
1061 }
1062 MSC_RAMFUNC_DEFINITION_END
1063
1064 /***************************************************************************//**
1065 * @brief
1066 * An internal flash write function.
1067 * @param[in] address
1068 * A write address.
1069 * @param[in] data
1070 * A pointer to the first data word to load.
1071 * @param[in] numBytes
1072 * A nsumber of data bytes to load, which must be a multiple of 4 bytes.
1073 * @return
1074 * Returns the status of the data load operation.
1075 ******************************************************************************/
1076 MSC_RAMFUNC_DEFINITION_BEGIN
MSC_WriteWordI(uint32_t * address,void const * data,uint32_t numBytes)1077 MSC_Status_TypeDef MSC_WriteWordI(uint32_t *address,
1078 void const *data,
1079 uint32_t numBytes)
1080 {
1081 uint32_t wordCount;
1082 uint32_t numWords;
1083 uint32_t pageWords;
1084 uint32_t* pData;
1085 bool wasLocked;
1086 MSC_Status_TypeDef retval = mscReturnOk;
1087
1088 wasLocked = MSC_IS_LOCKED();
1089 MSC->LOCK = MSC_LOCK_LOCKKEY_UNLOCK;
1090
1091 /* Check alignment (must be aligned to words). */
1092 EFM_ASSERT(((uint32_t) address & 0x3) == 0);
1093
1094 /* Check a number of bytes. Must be divisible by four. */
1095 EFM_ASSERT((numBytes & 0x3) == 0);
1096
1097 #if defined(_EMU_STATUS_VSCALE_MASK) && defined(_SILICON_LABS_32B_SERIES_1)
1098 /* VSCALE must be done and flash write requires VSCALE2. */
1099 EFM_ASSERT(!(EMU->STATUS & _EMU_STATUS_VSCALEBUSY_MASK));
1100 EFM_ASSERT((EMU->STATUS & _EMU_STATUS_VSCALE_MASK) == EMU_STATUS_VSCALE_VSCALE2);
1101 #endif
1102
1103 /* Enable writing to the MSC module. */
1104 MSC->WRITECTRL |= MSC_WRITECTRL_WREN;
1105
1106 /* Convert bytes to words. */
1107 numWords = numBytes >> 2;
1108 EFM_ASSERT(numWords > 0);
1109
1110 /* The following loop splits the data into chunks corresponding to flash pages.
1111 The address is loaded only once per page because the hardware automatically
1112 increments the address internally for each data load inside a page. */
1113 for (wordCount = 0, pData = (uint32_t *)data; wordCount < numWords; ) {
1114 /* First, the address is loaded. The address is auto-incremented within a page.
1115 Therefore, the address phase is only needed once for each page. */
1116 retval = MSC_LoadVerifyAddress(address + wordCount);
1117 if (mscReturnOk != retval) {
1118 /* Disable writing to the MSC module. */
1119 MSC->WRITECTRL &= ~MSC_WRITECTRL_WREN;
1120 if (wasLocked) {
1121 MSC->LOCK = MSC_LOCK_LOCKKEY_LOCK;
1122 }
1123 return retval;
1124 }
1125 /* Compute the number of words to write to the current page. */
1126 pageWords =
1127 (FLASH_PAGE_SIZE
1128 - (((uint32_t) (address + wordCount)) & (FLASH_PAGE_SIZE - 1)))
1129 / sizeof(uint32_t);
1130 if (pageWords > numWords - wordCount) {
1131 pageWords = numWords - wordCount;
1132 }
1133 /* Write the data in the current page. */
1134 retval = MSC_LoadWriteData(pData, pageWords);
1135 if (mscReturnOk != retval) {
1136 break;
1137 }
1138 wordCount += pageWords;
1139 pData += pageWords;
1140 }
1141
1142 #if defined(ERRATA_FIX_FLASH_E201_EN)
1143 /* Fix for errata FLASH_E201 - Potential program failure after Power On.
1144 *
1145 * Check if the first word was programmed correctly. If a failure is detected,
1146 * retry programming of the first word.
1147 *
1148 * A full description of the errata is in the errata document. */
1149 pData = (uint32_t *) data;
1150 if (*address != *pData) {
1151 retval = MSC_LoadVerifyAddress(address);
1152 if (mscReturnOk == retval) {
1153 retval = MSC_LoadWriteData(pData, 1);
1154 }
1155 }
1156 #endif
1157
1158 /* Disable writing to the MSC module. */
1159 MSC->WRITECTRL &= ~MSC_WRITECTRL_WREN;
1160
1161 #if defined(_MSC_WRITECTRL_WDOUBLE_MASK)
1162 #if (WORDS_PER_DATA_PHASE == 2)
1163 /* Turn off the double word write cycle support. */
1164 MSC->WRITECTRL &= ~MSC_WRITECTRL_WDOUBLE;
1165 #endif
1166 #endif
1167 if (wasLocked) {
1168 MSC->LOCK = MSC_LOCK_LOCKKEY_LOCK;
1169 }
1170 return retval;
1171 }
1172 MSC_RAMFUNC_DEFINITION_END
1173
1174 /** @endcond */
1175
1176 /***************************************************************************//**
1177 * @brief
1178 * Erases a page in flash memory.
1179 * @note
1180 * For the Gecko family, it is required to run this function from RAM.
1181 *
1182 * For IAR Embedded Workbench, Simplicity Studio and GCC, this is
1183 * achieved automatically by using attributes in the function proctype. For Keil
1184 * uVision IDE, define a section called "ram_code" and place this manually in
1185 * the project's scatter file.
1186 *
1187 * @param[in] startAddress
1188 * A pointer to the flash page to erase. Must be aligned to the beginning of the page
1189 * boundary.
1190 * @return
1191 * Returns the status of erase operation, @ref MSC_Status_TypeDef
1192 * @verbatim
1193 * mscReturnOk - The operation completed successfully.
1194 * mscReturnInvalidAddr - The operation tried to erase a non-flash area.
1195 * mscReturnLocked - The operation tried to erase a locked area of the flash.
1196 * mscReturnTimeOut - The operation timed out waiting for the flash operation
1197 * to complete.
1198 * @endverbatim
1199 ******************************************************************************/
1200 MSC_RAMFUNC_DEFINITION_BEGIN
MSC_ErasePage(uint32_t * startAddress)1201 MSC_Status_TypeDef MSC_ErasePage(uint32_t *startAddress)
1202 {
1203 uint32_t timeOut = MSC_PROGRAM_TIMEOUT;
1204 bool wasLocked;
1205
1206 wasLocked = MSC_IS_LOCKED();
1207 MSC->LOCK = MSC_LOCK_LOCKKEY_UNLOCK;
1208
1209 /* An address must be aligned to pages. */
1210 EFM_ASSERT((((uint32_t) startAddress) & (FLASH_PAGE_SIZE - 1)) == 0);
1211 #if defined(_EMU_STATUS_VSCALE_MASK) && defined(_SILICON_LABS_32B_SERIES_1)
1212 /* VSCALE must be done and flash erase requires VSCALE2. */
1213 EFM_ASSERT(!(EMU->STATUS & _EMU_STATUS_VSCALEBUSY_MASK));
1214 EFM_ASSERT((EMU->STATUS & _EMU_STATUS_VSCALE_MASK) == EMU_STATUS_VSCALE_VSCALE2);
1215 #endif
1216
1217 /* Enable writing to the MSC module. */
1218 MSC->WRITECTRL |= MSC_WRITECTRL_WREN;
1219
1220 /* Load an address. */
1221 MSC->ADDRB = (uint32_t)startAddress;
1222 MSC->WRITECMD = MSC_WRITECMD_LADDRIM;
1223
1224 /* Check for an invalid address. */
1225 if (MSC->STATUS & MSC_STATUS_INVADDR) {
1226 /* Disable writing to the MSC module. */
1227 MSC->WRITECTRL &= ~MSC_WRITECTRL_WREN;
1228 if (wasLocked) {
1229 MSC->LOCK = MSC_LOCK_LOCKKEY_LOCK;
1230 }
1231 return mscReturnInvalidAddr;
1232 }
1233
1234 /* Send erase page command. */
1235 MSC->WRITECMD = MSC_WRITECMD_ERASEPAGE;
1236
1237 /* Wait for the erase to complete. */
1238 while ((MSC->STATUS & MSC_STATUS_BUSY) && (timeOut != 0)) {
1239 timeOut--;
1240 }
1241 /* Check for write protected page. */
1242 if (MSC->STATUS & MSC_STATUS_LOCKED) {
1243 /* Disable writing to the MSC module. */
1244 MSC->WRITECTRL &= ~MSC_WRITECTRL_WREN;
1245 if (wasLocked) {
1246 MSC->LOCK = MSC_LOCK_LOCKKEY_LOCK;
1247 }
1248 return mscReturnLocked;
1249 }
1250 if (timeOut == 0) {
1251 /* Disable writing to the MSC module. */
1252 MSC->WRITECTRL &= ~MSC_WRITECTRL_WREN;
1253 if (wasLocked) {
1254 MSC->LOCK = MSC_LOCK_LOCKKEY_LOCK;
1255 }
1256 return mscReturnTimeOut;
1257 }
1258 /* Disable writing to the MSC module. */
1259 MSC->WRITECTRL &= ~MSC_WRITECTRL_WREN;
1260 if (wasLocked) {
1261 MSC->LOCK = MSC_LOCK_LOCKKEY_LOCK;
1262 }
1263 return mscReturnOk;
1264 }
1265 MSC_RAMFUNC_DEFINITION_END
1266
1267 /***************************************************************************//**
1268 * @brief
1269 * Writes data to flash memory. This function is interrupt-safe, but slower than
1270 * MSC_WriteWordFast(), which writes to flash with interrupts disabled.
1271 * Write data must be aligned to words and contain a number of bytes that is
1272 * divisible by four.
1273 * @note
1274 * It is recommended to erase the flash page before performing a write.
1275 *
1276 * For the Gecko family, it is required to run this function from RAM.
1277 *
1278 * For IAR Embedded Workbench, Simplicity Studio and GCC,
1279 * this is done automatically by using attributes in the function proctype.
1280 * For Keil uVision IDE, define a section called "ram_code" and place it
1281 * manually in the project's scatter file.
1282 *
1283 * This function requires a system core clock at 1 MHz or higher.
1284 *
1285 * @param[in] address
1286 * A pointer to the flash word to write to. Must be aligned to words.
1287 * @param[in] data
1288 * Data to write to flash.
1289 * @param[in] numBytes
1290 * A number of bytes to write from flash. NB: Must be divisible by four.
1291 * @return
1292 * Returns the status of the write operation.
1293 * @verbatim
1294 * flashReturnOk - The operation completed successfully.
1295 * flashReturnInvalidAddr - The operation tried to erase a non-flash area.
1296 * flashReturnLocked - The operation tried to erase a locked area of the Flash.
1297 * flashReturnTimeOut - The operation timed out waiting for the flash operation
1298 * to complete, or the MSC module timed out waiting for the software to write
1299 * the next word into the DWORD register.
1300 * @endverbatim
1301 ******************************************************************************/
1302 MSC_RAMFUNC_DEFINITION_BEGIN
MSC_WriteWord(uint32_t * address,void const * data,uint32_t numBytes)1303 MSC_Status_TypeDef MSC_WriteWord(uint32_t *address,
1304 void const *data,
1305 uint32_t numBytes)
1306 {
1307 return MSC_WriteWordI(address, data, numBytes);
1308 }
1309 MSC_RAMFUNC_DEFINITION_END
1310
1311 /***************************************************************************//**
1312 * @brief
1313 * Writes data to flash memory. This function is faster than MSC_WriteWord(),
1314 * but it disables interrupts. Write data must be aligned to words and contain
1315 * a number of bytes that is divisible by four.
1316 * @warning
1317 * This function is only available for certain devices.
1318 * @note
1319 * It is recommended to erase the flash page before performing a write.
1320 * It is required to run this function from RAM on parts that include a
1321 * flash write buffer.
1322 *
1323 * For IAR Embedded Workbench, Simplicity Studio and GCC,
1324 * this is done automatically by using attributes in the function proctype.
1325 * For Keil uVision IDE, define a section called "ram_code" and place this manually
1326 * in the project's scatter file.
1327 *
1328 * @deprecated
1329 * This function is deprecated, the functionality is the same as calling
1330 * @ref MSC_WriteWord().
1331 *
1332 * @param[in] address
1333 * A pointer to the flash word to write to. Must be aligned to words.
1334 * @param[in] data
1335 * Data to write to flash.
1336 * @param[in] numBytes
1337 * A number of bytes to write from the Flash. NB: Must be divisible by four.
1338 * @return
1339 * Returns the status of the write operation.
1340 * @verbatim
1341 * flashReturnOk - The operation completed successfully.
1342 * flashReturnInvalidAddr - The operation tried to erase a non-flash area.
1343 * flashReturnLocked - The operation tried to erase a locked area of the flash.
1344 * flashReturnTimeOut - The operation timed out waiting for flash operation
1345 * to complete. Or the MSC timed out waiting for the software to write
1346 * the next word into the DWORD register.
1347 * @endverbatim
1348 ******************************************************************************/
1349 MSC_RAMFUNC_DEFINITION_BEGIN
MSC_WriteWordFast(uint32_t * address,void const * data,uint32_t numBytes)1350 MSC_Status_TypeDef MSC_WriteWordFast(uint32_t *address,
1351 void const *data,
1352 uint32_t numBytes)
1353 {
1354 return MSC_WriteWord(address, data, numBytes);
1355 }
1356 MSC_RAMFUNC_DEFINITION_END
1357
1358 #if (_SILICON_LABS_32B_SERIES > 0)
1359 /***************************************************************************//**
1360 * @brief
1361 * Writes data from RAM to flash memory using the DMA.
1362 *
1363 * @details
1364 * This function uses the LDMA to write data to the internal flash memory.
1365 * This is the fastest way to write data to the flash and should be used when
1366 * the application wants to achieve write speeds like they are reported in the
1367 * datasheet. Note that this function only supports writing data from RAM to
1368 * flash, it does not support writing data from flash to flash.
1369 *
1370 * @note
1371 * This function requires that the LDMA clock is enabled.
1372 *
1373 * @param[in] ch
1374 * DMA channel to use
1375 *
1376 * @param[in] address
1377 * A pointer to the flash word to write to. Must be aligned to words.
1378 *
1379 * @param[in] data
1380 * Data to write to flash. Note that this argument must be an address in RAM.
1381 * This function does not support copying data from flash to flash on series-1
1382 * devices.
1383 *
1384 * @param[in] numBytes
1385 * A number of bytes to write from flash. NB: Must be divisible by four.
1386 *
1387 * @return
1388 * Returns the status of the write operation.
1389 * @verbatim
1390 * flashReturnOk - The operation completed successfully.
1391 * flashReturnInvalidAddr - The operation tried to erase a non-flash area.
1392 * @endverbatim
1393 ******************************************************************************/
MSC_WriteWordDma(int ch,uint32_t * address,const void * data,uint32_t numBytes)1394 MSC_Status_TypeDef MSC_WriteWordDma(int ch,
1395 uint32_t *address,
1396 const void *data,
1397 uint32_t numBytes)
1398 {
1399 uint32_t words = numBytes / 4;
1400 uint32_t burstLen;
1401 uint32_t src = (uint32_t) data;
1402 uint32_t dst = (uint32_t) address;
1403 bool wasLocked;
1404
1405 EFM_ASSERT((ch >= 0) && (ch < (int)DMA_CHAN_COUNT));
1406
1407 // Verify that the data argument is in RAM
1408 if (((uint32_t)data < SRAM_BASE) || ((uint32_t)data > (SRAM_BASE + SRAM_SIZE))) {
1409 EFM_ASSERT(false);
1410 return mscReturnInvalidAddr;
1411 }
1412
1413 LDMA->CH[ch].REQSEL = LDMA_CH_REQSEL_SOURCESEL_MSC
1414 | LDMA_CH_REQSEL_SIGSEL_MSCWDATA;
1415 LDMA->CH[ch].CFG = _LDMA_CH_CFG_RESETVALUE;
1416 LDMA->CH[ch].LOOP = _LDMA_CH_LOOP_RESETVALUE;
1417 LDMA->CH[ch].LINK = _LDMA_CH_LINK_RESETVALUE;
1418
1419 wasLocked = MSC_IS_LOCKED();
1420 MSC->LOCK = MSC_LOCK_LOCKKEY_UNLOCK;
1421 // Enable writing to the MSC module.
1422 MSC->WRITECTRL |= MSC_WRITECTRL_WREN;
1423
1424 while (numBytes) {
1425 // Max burst length is up to next flash page boundary
1426 burstLen = SL_MIN(numBytes,
1427 ((dst + FLASH_PAGE_SIZE) & FLASH_PAGE_MASK) - dst);
1428 words = burstLen / 4;
1429
1430 // Load the address.
1431 MSC->ADDRB = dst;
1432 MSC->WRITECMD = MSC_WRITECMD_LADDRIM;
1433
1434 // Check for an invalid address.
1435 if (MSC->STATUS & MSC_STATUS_INVADDR) {
1436 return mscReturnInvalidAddr;
1437 }
1438
1439 LDMA->CH[ch].CTRL = LDMA_CH_CTRL_DSTINC_NONE
1440 | LDMA_CH_CTRL_SIZE_WORD
1441 | ((words - 1) << _LDMA_CH_CTRL_XFERCNT_SHIFT);
1442 LDMA->CH[ch].SRC = (uint32_t)src;
1443 LDMA->CH[ch].DST = (uint32_t)&MSC->WDATA;
1444
1445 // Enable channel
1446 LDMA->CHEN |= (0x1 << ch);
1447 MSC->WRITECMD = MSC_WRITECMD_WRITETRIG;
1448
1449 while ((LDMA->CHDONE & (0x1 << ch)) == 0x0) {
1450 ;
1451 }
1452 BUS_RegMaskedClear(&LDMA->CHDONE, (0x1 << ch));
1453 BUS_RegMaskedClear(&LDMA->CHEN, (0x1 << ch));
1454
1455 dst += burstLen;
1456 src += burstLen;
1457 numBytes -= burstLen;
1458 }
1459
1460 MSC->WRITECMD = MSC_WRITECMD_WRITEEND;
1461
1462 // Disable writing to the MSC module.
1463 MSC->WRITECTRL &= ~MSC_WRITECTRL_WREN;
1464 if (wasLocked) {
1465 MSC->LOCK = MSC_LOCK_LOCKKEY_LOCK;
1466 }
1467
1468 return mscReturnOk;
1469 }
1470 #endif
1471
1472 #if defined(_MSC_MASSLOCK_MASK)
1473 SL_RAMFUNC_DEFINITION_BEGIN
MSC_MassErase(void)1474 MSC_Status_TypeDef MSC_MassErase(void)
1475 {
1476 bool wasLocked;
1477 wasLocked = MSC_IS_LOCKED();
1478 MSC->LOCK = MSC_LOCK_LOCKKEY_UNLOCK;
1479
1480 /* Enable writing to the MSC module. */
1481 MSC->WRITECTRL |= MSC_WRITECTRL_WREN;
1482
1483 /* Unlock the device mass erase. */
1484 MSC->MASSLOCK = MSC_MASSLOCK_LOCKKEY_UNLOCK;
1485
1486 /* Erase the first 512 K block. */
1487 MSC->WRITECMD = MSC_WRITECMD_ERASEMAIN0;
1488
1489 /* Waiting for erase to complete. */
1490 while ((MSC->STATUS & MSC_STATUS_BUSY) != 0U) {
1491 }
1492
1493 #if ((FLASH_SIZE >= (512 * 1024)) && defined(_MSC_WRITECMD_ERASEMAIN1_MASK))
1494 /* Erase the second 512 K block. */
1495 MSC->WRITECMD = MSC_WRITECMD_ERASEMAIN1;
1496
1497 /* Waiting for erase to complete. */
1498 while ((MSC->STATUS & MSC_STATUS_BUSY) != 0U) {
1499 }
1500 #endif
1501
1502 /* Restore the mass erase lock. */
1503 MSC->MASSLOCK = MSC_MASSLOCK_LOCKKEY_LOCK;
1504
1505 /* Disable writing to the MSC module. */
1506 MSC->WRITECTRL &= ~MSC_WRITECTRL_WREN;
1507
1508 if (wasLocked) {
1509 MSC->LOCK = MSC_LOCK_LOCKKEY_LOCK;
1510 }
1511
1512 /* This will only successfully return if calling function is also in SRAM. */
1513 return mscReturnOk;
1514 }
1515 SL_RAMFUNC_DEFINITION_END
1516 #endif // defined(_MSC_MASSLOCK_MASK)
1517
1518 #endif // defined(_SILICON_LABS_32B_SERIES_2)
1519
1520 #if defined(_MSC_ECCCTRL_MASK) \
1521 || defined(_SYSCFG_DMEM0ECCCTRL_MASK) \
1522 || defined(_MPAHBRAM_CTRL_MASK)
1523
1524 #if defined(_SILICON_LABS_32B_SERIES_2_CONFIG_2) \
1525 || defined(_SILICON_LABS_32B_SERIES_2_CONFIG_7) \
1526 || defined(_MPAHBRAM_CTRL_MASK)
1527
1528 /***************************************************************************//**
1529 * @brief
1530 * Read and write existing values in RAM (for ECC initialization).
1531 *
1532 * @details
1533 * This function uses core to load and store the existing data
1534 * values in the given RAM bank.
1535 *
1536 * @param[in] eccBank
1537 * Pointer to ECC RAM bank (MSC_EccBank_Typedef)
1538 ******************************************************************************/
mscEccReadWriteExistingPio(const MSC_EccBank_Typedef * eccBank)1539 static void mscEccReadWriteExistingPio(const MSC_EccBank_Typedef *eccBank)
1540 {
1541 volatile uint32_t *ramptr = (volatile uint32_t *) eccBank->base;
1542 const uint32_t *endptr = (const uint32_t *) (eccBank->base + eccBank->size);
1543 volatile uint32_t *ctrlreg = &ECC_CTRL_REG;
1544 uint32_t enableEcc;
1545
1546 EFM_ASSERT(ramptr < endptr);
1547
1548 #if defined(_SILICON_LABS_32B_SERIES_2_CONFIG_2) || defined(_SILICON_LABS_32B_SERIES_2_CONFIG_7)
1549 enableEcc = eccBank->initSyndromeEnable;
1550 #elif defined(_MPAHBRAM_CTRL_MASK)
1551 /* MPAHBRAM ECC requires both ECCEN and ECCWEN to be set for the syndromes
1552 to be written in ECC */
1553 enableEcc = eccBank->correctionEnable;
1554 /* Enable ECC syndrome write */
1555 ECC_CTRL_REG |= eccBank->initSyndromeEnable;
1556
1557 ECC_IFC_REG = ECC_IFC_MASK;
1558 #endif
1559
1560 #ifndef __GNUC__
1561 #define __asm__ asm
1562 #endif
1563
1564 /*
1565 * Performs a read and write of all RAM address to initialize
1566 * ECC syndromes. ECC is initialized by reading a RAM address
1567 * while ECC is disabled and write it back while ECC is enabled.
1568 *
1569 * HardFault could occur if we try to read values from RAM while ECC
1570 * is enabled and not initialized. In this case, ECC tries to correct the
1571 * value and ended giving the wrong value which could be sometimes an
1572 * non-existing address.
1573 *
1574 * So for ECC initialization to work properly, this must ensures that while
1575 * ECC is enabled, RAM will be accessed only through writes, no reads shall
1576 * occur. It's hard to have such guarantee with C code, because the C
1577 * compiler with optimization settings, can get in the way
1578 * and do some unwanted reads while ECC is enabled. Assembly allows such
1579 * guarantee and let ECC be initialized without triggering errors.
1580 */
1581
1582 __asm__ volatile (
1583 "1:\n\t" /* define label 1 */
1584 "LDR r1, [%[ramptr]]\n\t" /* load content of ramptr into R1, ECC
1585 is disabled to get a correct value */
1586 "LDR r0, [%[ctrlreg]]\n\t" /* load ctrlreg content into R0 */
1587 "ORR r0, r0, %[enableEcc]\n\t" /* OR R0 and enableEcc, and store result
1588 in R0 */
1589 "STR r0, [%[ctrlreg]]\n\t" /* write R0 into ctrlreg, ECC is
1590 enabled from now on */
1591 "STR r1, [%[ramptr]]\n\t" /* write back ram content where it was,
1592 syndrome will be written in ECC */
1593 "BIC r0, r0, %[enableEcc]\n\t" /* bit clear enableEcc from R0, and store
1594 result in R0 */
1595 "STR r0, [%[ctrlreg]]\n\t" /* write R0 into ctrlreg, ECC is
1596 disabled */
1597 "ADDS %[ramptr], %[ramptr], #4\n\t" /* increment ramptr by 4 (size of
1598 a word) */
1599 "CMP %[ramptr], %[endptr]\n\t" /* compare ramptr and endptr... */
1600 "BCC 1b\n\t" /* ... and jump back to label 1 if Carrry
1601 Clear (meaning ramptr < endptr) */
1602 "ORR r0, r0, %[enableEcc]\n\t" /* and re-enable ECC ASAP to be sure no */
1603 "STR r0, [%[ctrlreg]]\n\t" /* STR occurs with ECC disabled */
1604 :[ramptr] "+r" (ramptr)
1605 :[endptr] "r" (endptr),
1606 [ctrlreg] "r" (ctrlreg),
1607 [enableEcc] "r" (enableEcc)
1608 : "r0", "r1", /* R0 and R1 used as temporary registers */
1609 "memory" /* Memory pointed by ramptr is modified */
1610 );
1611 }
1612
1613 #else
1614
1615 /***************************************************************************//**
1616 * @brief
1617 * DMA read and write existing values (for ECC initialization).
1618 *
1619 * @details
1620 * This function uses DMA to read and write the existing data values in
1621 * the RAM region specified by start and size. The function will use the
1622 * 2 DMA channels specified by the channels[2] array.
1623 *
1624 * @param[in] start
1625 * Start address of address range in RAM to read/write.
1626 *
1627 * @param[in] size
1628 * Size of address range in RAM to read/write.
1629 *
1630 * @param[in] channels[2]
1631 * Array of 2 DMA channels to use.
1632 ******************************************************************************/
1633 static void mscEccReadWriteExistingDma(uint32_t start,
1634 uint32_t size,
1635 uint32_t channels[2])
1636 {
1637 uint32_t descCnt = 0;
1638 volatile uint32_t dmaDesc[ECC_DMA_DESCS][4];
1639 uint32_t chMask = (1 << channels[0]) | (1 << channels[1]);
1640 /* Assert that the 2 DMA channel numbers are different. */
1641 EFM_ASSERT(channels[0] != channels[1]);
1642
1643 /* Make sure ECC_RAM_SIZE_MAX is a multiple of ECC_DMA_DESC_SIZE in order
1644 to match the total xfer size of the descriptor chain with the largest
1645 ECC RAM bank. */
1646 EFM_ASSERT((ECC_RAM_SIZE_MAX % ECC_DMA_DESC_SIZE) == 0);
1647
1648 /* Initialize LDMA descriptor chain. */
1649 do {
1650 dmaDesc[descCnt][0] = /* DMA desc CTRL word */
1651 LDMA_CH_CTRL_STRUCTTYPE_TRANSFER
1652 | LDMA_CH_CTRL_STRUCTREQ
1653 | _LDMA_CH_CTRL_XFERCNT_MASK
1654 | LDMA_CH_CTRL_BLOCKSIZE_ALL
1655 | LDMA_CH_CTRL_REQMODE_ALL
1656 | LDMA_CH_CTRL_SRCINC_ONE
1657 | LDMA_CH_CTRL_SIZE_WORD
1658 | LDMA_CH_CTRL_DSTINC_ONE;
1659
1660 /* source and destination address */
1661 dmaDesc[descCnt][1] = start;
1662 dmaDesc[descCnt][2] = start;
1663 /* link to next descriptor */
1664 dmaDesc[descCnt][3] = LDMA_CH_LINK_LINK
1665 | (((uint32_t) &dmaDesc[descCnt + 1][0])
1666 & _LDMA_CH_LINK_LINKADDR_MASK);
1667
1668 start += ECC_DMA_DESC_SIZE;
1669 size -= ECC_DMA_DESC_SIZE;
1670 descCnt++;
1671 } while (size);
1672
1673 /* Make sure descCnt is valid to avoid out-of-bounds access when writing to
1674 dmaDesc array. */
1675 if ((descCnt < 2) || (descCnt > ECC_DMA_DESCS)) {
1676 while (true) {
1677 EFM_ASSERT(false);
1678 }
1679 }
1680
1681 /* Now, divide the descriptor list in two parts, one for each channel,
1682 by setting the link bit and address 0 of the descriptor in the middle
1683 to 0. */
1684 dmaDesc[(descCnt / 2) - 1][3] = 0;
1685
1686 /* Set last descriptor link bit and address to 0. */
1687 dmaDesc[descCnt - 1][3] = 0;
1688
1689 #if !defined(_SILICON_LABS_32B_SERIES_2_CONFIG_1)
1690 /* Start the LDMA clock now */
1691 CMU_ClockEnable(cmuClock_LDMA, true);
1692 #if defined(_SILICON_LABS_32B_SERIES_2_CONFIG_2)
1693 CMU_ClockEnable(cmuClock_LDMAXBAR, true);
1694 #endif
1695 #endif
1696 /* Round robin scheduling for all channels (0 = no fixed priority channels).
1697 */
1698 LDMA->CTRL = 0 << _LDMA_CTRL_NUMFIXED_SHIFT;
1699 #if defined(LDMA_EN_EN)
1700 LDMA->EN = LDMA_EN_EN;
1701 #endif
1702 LDMA->CHEN = 0;
1703 LDMA->DBGHALT = 0;
1704 LDMA->REQDIS = 0;
1705
1706 /* Disable LDMA interrupts, and clear interrupt status. */
1707 LDMA->IEN = 0;
1708 #if defined (LDMA_HAS_SET_CLEAR)
1709 LDMA->IF_CLR = chMask;
1710 #else
1711 LDMA->IFC = chMask;
1712 #endif
1713
1714 /* Disable looping */
1715 LDMA->CH[channels[0]].LOOP = 0;
1716 LDMA->CH[channels[1]].LOOP = 0;
1717
1718 /* Set descriptor address for first channel. */
1719 LDMA->CH[channels[0]].LINK = ((uint32_t)&dmaDesc[0][0])
1720 & _LDMA_CH_LINK_LINKADDR_MASK;
1721 /* Set descriptor address for second channel. */
1722 LDMA->CH[channels[1]].LINK = ((uint32_t)&dmaDesc[descCnt / 2][0])
1723 & _LDMA_CH_LINK_LINKADDR_MASK;
1724 /* Clear the channel done flags. */
1725 BUS_RegMaskedClear(&LDMA->CHDONE, chMask);
1726
1727 /* Start transfer by loading descriptors. */
1728 LDMA->LINKLOAD = chMask;
1729
1730 /* Wait until finished. */
1731 while (!(
1732 #if defined(_LDMA_CHSTATUS_MASK)
1733 ((LDMA->CHSTATUS & chMask) == 0)
1734 #else
1735 ((LDMA->CHEN & chMask) == 0)
1736 #endif
1737 && ((LDMA->CHDONE & chMask) == chMask))) {
1738 }
1739
1740 #if !defined(_SILICON_LABS_32B_SERIES_2_CONFIG_1)
1741 /* Stop the LDMA clock now */
1742 CMU_ClockEnable(cmuClock_LDMA, false);
1743 #if defined(_SILICON_LABS_32B_SERIES_2_CONFIG_2)
1744 CMU_ClockEnable(cmuClock_LDMAXBAR, false);
1745 #endif
1746 #endif
1747 }
1748 #endif // #if defined(_SILICON_LABS_32B_SERIES_2_CONFIG_2) || defined(_MPAHBRAM_CTRL_MASK)
1749
1750 /***************************************************************************//**
1751 * @brief
1752 * Initialize ECC for a given memory bank.
1753 *
1754 * @brief
1755 * This function initializes ECC for a given memory bank which is specified
1756 * with the MSC_EccBank_Typedef structure input parameter.
1757 *
1758 * @param[in] eccBank
1759 * ECC memory bank device structure.
1760 *
1761 * @param[in] dmaChannels
1762 * Array of 2 DMA channels that may be used during ECC initialization.
1763 *
1764 ******************************************************************************/
mscEccBankInit(const MSC_EccBank_Typedef * eccBank,uint32_t dmaChannels[2])1765 static void mscEccBankInit(const MSC_EccBank_Typedef *eccBank,
1766 uint32_t dmaChannels[2])
1767 {
1768 CORE_DECLARE_IRQ_STATE;
1769
1770 CORE_ENTER_CRITICAL();
1771
1772 #if defined(_SILICON_LABS_32B_SERIES_2_CONFIG_2) \
1773 || defined(_SILICON_LABS_32B_SERIES_2_CONFIG_7) \
1774 || defined(_MPAHBRAM_CTRL_MASK)
1775 (void) dmaChannels;
1776 #if !defined(_MPAHBRAM_CTRL_MASK)
1777 /* Disable ECC write */
1778 ECC_CTRL_REG &= ~eccBank->initSyndromeEnable;
1779 #endif
1780 /* Initialize ECC syndromes by using core cpu to load and store the existing
1781 data values in RAM. */
1782 mscEccReadWriteExistingPio(eccBank);
1783 #else
1784 /* Enable ECC write */
1785 ECC_CTRL_REG |= eccBank->initSyndromeEnable;
1786 /* Initialize ECC syndromes by using DMA to read and write the existing
1787 data values in RAM. */
1788 mscEccReadWriteExistingDma(eccBank->base, eccBank->size, dmaChannels);
1789 #endif
1790
1791 /* Clear any ECC errors that may have been reported before or during
1792 initialization. */
1793 ECC_IFC_REG = ECC_IFC_MASK;
1794
1795 #if !defined(_MPAHBRAM_CTRL_MASK)
1796 /* Enable ECC decoder to detect and report ECC errors. */
1797 ECC_CTRL_REG |= eccBank->correctionEnable;
1798 #endif
1799
1800 CORE_EXIT_CRITICAL();
1801 }
1802
1803 /***************************************************************************//**
1804 * @brief
1805 * Disable ECC for a given memory bank.
1806 *
1807 * @brief
1808 * This function disables ECC for a given memory bank which is specified
1809 * with the MSC_EccBank_Typedef structure input parameter.
1810 *
1811 * @param[in] eccBank
1812 * ECC memory bank device structure.
1813 *
1814 ******************************************************************************/
mscEccBankDisable(const MSC_EccBank_Typedef * eccBank)1815 static void mscEccBankDisable(const MSC_EccBank_Typedef *eccBank)
1816 {
1817 /* Disable ECC write (encoder) and checking (decoder). */
1818 ECC_CTRL_REG &= ~(eccBank->initSyndromeEnable | eccBank->correctionEnable);
1819 }
1820
1821 /***************************************************************************//**
1822 * @brief
1823 * Configure Error Correcting Code (ECC).
1824 *
1825 * @details
1826 * This function configures ECC support according to the configuration
1827 * input parameter. If the user requests enabling ECC for a given RAM bank
1828 * this function will initialize ECC memory (syndromes) for the bank by
1829 * reading and writing the existing values in memory. I.e. all data is
1830 * preserved. The initialization process runs in a critical section
1831 * disallowing interrupts and thread scheduling, and will consume a
1832 * considerable amount of clock cycles. Therefore the user should carefully
1833 * assess where to call this function. The user can consider to increase
1834 * the clock frequency in order to reduce the execution time.
1835 * This function makes use of 2 DMA channels to move data to/from RAM in an
1836 * efficient way. The user can select which 2 DMA channels to use in order
1837 * to avoid conflicts with the application. However the user must make sure
1838 * that no other DMA operations takes place while this function is executing.
1839 * If the application has been using the DMA controller prior to calling this
1840 * function, the application will need to reinitialize DMA registers after
1841 * this function has completed.
1842 *
1843 * @note
1844 * This function protects the ECC initialization procedure from interrupts
1845 * and other threads by using a critical section (defined by em_core.h)
1846 * When running on RTOS the user may need to override CORE_EnterCritical
1847 * CORE_ExitCritical which are declared as 'SL_WEAK' in em_core.c.
1848 *
1849 * @param[in] eccConfig
1850 * ECC configuration
1851 ******************************************************************************/
MSC_EccConfigSet(MSC_EccConfig_TypeDef * eccConfig)1852 void MSC_EccConfigSet(MSC_EccConfig_TypeDef *eccConfig)
1853 {
1854 unsigned int cnt;
1855 #if defined(ECC_FAULT_CTRL_REG)
1856 uint32_t faultCtrlReg = ECC_FAULT_CTRL_REG;
1857 /* Disable ECC faults if ecc fault ctrl register is defined. */
1858 faultCtrlReg &= ~ECC_FAULT_EN;
1859 ECC_FAULT_CTRL_REG = faultCtrlReg;
1860 #endif
1861
1862 /* Loop through the ECC banks array, enable or disable according to
1863 the eccConfig->enableEccBank array. */
1864 for (cnt = 0; cnt < MSC_ECC_BANKS; cnt++) {
1865 if (eccConfig->enableEccBank[cnt]) {
1866 mscEccBankInit(&eccBankTbl[cnt], eccConfig->dmaChannels);
1867 } else {
1868 mscEccBankDisable(&eccBankTbl[cnt]);
1869 }
1870 }
1871
1872 #if defined(ECC_FAULT_CTRL_REG) && !defined(_SILICON_LABS_32B_SERIES_1_CONFIG_1)
1873 /*
1874 * Enable ECC faults if ecc fault ctrl register is set.
1875 * On Series 1 Config 1, aka EFM32GG11, ECC faults should stay disabled.
1876 * Reload register first, in case it was modified and/or shared by bank
1877 * init functions.
1878 */
1879 faultCtrlReg = ECC_FAULT_CTRL_REG;
1880 faultCtrlReg |= ECC_FAULT_EN;
1881 ECC_FAULT_CTRL_REG = faultCtrlReg;
1882 #endif
1883 }
1884
1885 #endif /* #if defined(_MSC_ECCCTRL_MASK) */
1886
1887 #if defined(_SYSCFG_DMEM0PORTMAPSEL_MASK)
1888 /***************************************************************************//**
1889 * @brief
1890 * Set MPAHBRAM port to use to access DMEM.
1891 *
1892 * @details
1893 * This function configures which MPAHBRAM slave port is used to access DMEM.
1894 * Depending on the use case, it might improve performance by spreading the
1895 * load over the N ports (N is usually 2 or 4), instead of starving because a
1896 * port is used by another master.
1897 *
1898 * @param[in] master
1899 * AHBHOST master to be configured.
1900 * @param[in] port
1901 * AHBHOST slave port to use.
1902 ******************************************************************************/
MSC_DmemPortMapSet(MSC_DmemMaster_TypeDef master,uint8_t port)1903 void MSC_DmemPortMapSet(MSC_DmemMaster_TypeDef master, uint8_t port)
1904 {
1905 uint32_t bitfieldMask = DMEM_NUM_PORTS - 1;
1906
1907 /* make sure master is within the mask of port map that can be changed
1908 * make sure port is a sensible value
1909 */
1910 EFM_ASSERT(((1 << master) & _SYSCFG_DMEM0PORTMAPSEL_MASK) != 0x0);
1911 EFM_ASSERT(port < DMEM_NUM_PORTS);
1912
1913 #if defined(CMU_CLKEN0_SYSCFG)
1914 bool disableSyscfgClk = false;
1915
1916 if (!(CMU->CLKEN0 & _CMU_CLKEN0_SYSCFG_MASK)) {
1917 disableSyscfgClk = true;
1918 CMU->CLKEN0_SET = CMU_CLKEN0_SYSCFG;
1919 }
1920 #endif
1921
1922 BUS_RegMaskedWrite(&SYSCFG->DMEM0PORTMAPSEL,
1923 bitfieldMask << master,
1924 (uint32_t)port << master);
1925
1926 #if defined(CMU_CLKEN0_SYSCFG)
1927 if (disableSyscfgClk) {
1928 CMU->CLKEN0_CLR = CMU_CLKEN0_SYSCFG;
1929 }
1930 #endif
1931 }
1932 #endif
1933
1934 #if defined(_MPAHBRAM_CTRL_AHBPORTPRIORITY_MASK)
1935 /***************************************************************************//**
1936 * @brief
1937 * Set MPAHBRAM port priority for arbitration when multiple concurrent
1938 * transactions to DMEM.
1939 *
1940 * @details
1941 * This function configures which MPAHBRAM slave port will have priority.
1942 * The AHB port arbitration default scheme, round-robin arbitration, is
1943 * selected when portPriority == mscPortPriorityNone.
1944 *
1945 * @note
1946 * Doing this can potentially starve the others AHB port(s).
1947 *
1948 * @param[in] portPriority
1949 * AHBHOST slave port having elevated priority.
1950 ******************************************************************************/
MSC_PortSetPriority(MSC_PortPriority_TypeDef portPriority)1951 void MSC_PortSetPriority(MSC_PortPriority_TypeDef portPriority)
1952 {
1953 EFM_ASSERT(portPriority < ((DMEM_NUM_PORTS + 1) << _MPAHBRAM_CTRL_AHBPORTPRIORITY_SHIFT));
1954
1955 BUS_RegMaskedWrite(&DMEM->CTRL,
1956 _MPAHBRAM_CTRL_AHBPORTPRIORITY_MASK,
1957 (uint32_t)portPriority << _MPAHBRAM_CTRL_AHBPORTPRIORITY_SHIFT);
1958 }
1959
1960 /***************************************************************************//**
1961 * @brief
1962 * Get MPAHBRAM port arbitration priority selection.
1963 *
1964 * @details
1965 * This function returns the AHBHOST slave with raised priority.
1966 *
1967 * @return
1968 * Returns the AHBHOST slave port given priority or none.
1969 ******************************************************************************/
MSC_PortGetCurrentPriority(void)1970 MSC_PortPriority_TypeDef MSC_PortGetCurrentPriority(void)
1971 {
1972 uint32_t port = 0;
1973
1974 port = BUS_RegMaskedRead(&DMEM->CTRL,
1975 _MPAHBRAM_CTRL_AHBPORTPRIORITY_MASK);
1976
1977 return (MSC_PortPriority_TypeDef)(port >> _MPAHBRAM_CTRL_AHBPORTPRIORITY_SHIFT);
1978 }
1979 #endif /* if defined(_MPAHBRAM_CTRL_AHBPORTPRIORITY_MASK) */
1980
1981 /** @} (end addtogroup msc) */
1982 #endif /* defined(MSC_COUNT) && (MSC_COUNT > 0) */
1983