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 #ifndef EM_MSC_H
32 #define EM_MSC_H
33
34 #include "em_device.h"
35 #if defined(MSC_COUNT) && (MSC_COUNT > 0)
36
37 #include <stdint.h>
38 #include <stdbool.h>
39 #include "em_bus.h"
40 #include "em_msc_compat.h"
41 #include "em_ramfunc.h"
42 #include "sl_assert.h"
43
44 #if defined(SL_CATALOG_TZ_SECURE_KEY_LIBRARY_NS_PRESENT)
45 #include "sli_tz_ns_interface.h"
46 #include "sli_tz_service_msc.h"
47 #endif
48
49 #ifdef __cplusplus
50 extern "C" {
51 #endif
52
53 /***************************************************************************//**
54 * @addtogroup msc MSC - Memory System Controller
55 * @brief Memory System Controller API
56 * @details
57 * Contains functions to control the MSC, primarily the Flash.
58 * Users can perform Flash memory write and erase operations, as well as
59 * optimization of the CPU instruction fetch interface for the application.
60 * Available instruction fetch features depends on the MCU or SoC family, but
61 * features such as instruction pre-fetch, cache, and configurable branch prediction
62 * are typically available.
63 *
64 * @note Flash wait-state configuration is handled by @ref cmu.
65 * When core clock configuration is changed by a call to functions such as
66 * CMU_ClockSelectSet() or CMU_HFRCOBandSet(), then Flash wait-state
67 * configuration is also updated.
68 *
69 * MSC resets into a safe state. To initialize the instruction interface
70 * to recommended settings:
71 * @include em_msc_init_exec.c
72 *
73 * @note The optimal configuration is highly application dependent. Performance
74 * benchmarking is supported by most families. See MSC_StartCacheMeasurement()
75 * and MSC_GetCacheMeasurement() for more details.
76 *
77 * @note
78 * The flash write and erase runs from RAM on the EFM32G devices. On all other
79 * devices the flash write and erase functions run from flash.
80 *
81 * @note
82 * Flash erase may add ms of delay to interrupt latency if executing from Flash.
83 *
84 * Flash write and erase operations are supported by @ref MSC_WriteWord(),
85 * @ref MSC_ErasePage(), and MSC_MassErase().
86 * Mass erase is supported for MCU and SoC families with larger Flash sizes.
87 *
88 * @note
89 * @ref MSC_Init() must be called prior to any Flash write or erase operation.
90 *
91 * The following steps are necessary to perform a page erase and write:
92 * @include em_msc_erase_write.c
93 *
94 * @deprecated
95 * The configuration called EM_MSC_RUN_FROM_FLASH is deprecated. This was
96 * previously used for allocating the flash write functions in either flash
97 * or RAM.
98 *
99 * @note
100 * The configuration EM_MSC_RUN_FROM_RAM is used for allocating the flash
101 * write functions in FLASH and RAM respectively. By default, flash write
102 * functions are placed in RAM on EFM32G and Series 2 devices
103 * automatically and that could not be changed. For other devices,
104 * flash write functions are placed in FLASH but that could be changed using
105 * EM_MSC_RUN_FROM_RAM.
106 *
107 * @deprecated
108 * The function called MSC_WriteWordFast() is deprecated.
109 *
110 * @{
111 ******************************************************************************/
112
113 /*******************************************************************************
114 ************************* DEFINES *****************************************
115 ******************************************************************************/
116
117 /**
118 * @brief
119 * Timeout used while waiting for Flash to become ready after a write.
120 * This number indicates the number of iterations to perform before
121 * issuing a timeout.
122 *
123 * @note
124 * Timeout is set very large (in the order of 100x longer than
125 * necessary). This is to avoid any corner case.
126 */
127 #define MSC_PROGRAM_TIMEOUT 10000000UL
128
129 /** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
130 #if (defined(_EFM32_GECKO_FAMILY) \
131 || defined(_SILICON_LABS_32B_SERIES_2) \
132 || defined(EM_MSC_RUN_FROM_RAM)) \
133 && !defined(SL_CATALOG_TZ_SECURE_KEY_LIBRARY_NS_PRESENT)
134 #define MSC_RAMFUNC_DECLARATOR SL_RAMFUNC_DECLARATOR
135 #define MSC_RAMFUNC_DEFINITION_BEGIN SL_RAMFUNC_DEFINITION_BEGIN
136 #define MSC_RAMFUNC_DEFINITION_END SL_RAMFUNC_DEFINITION_END
137 #else
138 #define MSC_RAMFUNC_DECLARATOR
139 #define MSC_RAMFUNC_DEFINITION_BEGIN
140 #define MSC_RAMFUNC_DEFINITION_END
141 #endif
142 /** @endcond */
143
144 /*******************************************************************************
145 ************************* TYPEDEFS ****************************************
146 ******************************************************************************/
147
148 /** Return codes for writing/erasing Flash. */
149 typedef enum {
150 mscReturnOk = 0, /**< Flash write/erase successful. */
151 mscReturnInvalidAddr = -1, /**< Invalid address. Write to an address that is not Flash. */
152 mscReturnLocked = -2, /**< Flash address is locked. */
153 mscReturnTimeOut = -3, /**< Timeout while writing to Flash. */
154 mscReturnUnaligned = -4 /**< Unaligned access to Flash. */
155 } MSC_Status_TypeDef;
156
157 #if defined(_MSC_READCTRL_BUSSTRATEGY_MASK)
158 /** Strategy for prioritized bus access. */
159 typedef enum {
160 mscBusStrategyCPU = MSC_READCTRL_BUSSTRATEGY_CPU, /**< Prioritize CPU bus accesses. */
161 mscBusStrategyDMA = MSC_READCTRL_BUSSTRATEGY_DMA, /**< Prioritize DMA bus accesses. */
162 mscBusStrategyDMAEM1 = MSC_READCTRL_BUSSTRATEGY_DMAEM1, /**< Prioritize DMAEM1 for bus accesses. */
163 mscBusStrategyNone = MSC_READCTRL_BUSSTRATEGY_NONE /**< No unit has bus priority. */
164 } MSC_BusStrategy_Typedef;
165 #endif
166
167 #if defined(_SYSCFG_DMEM0PORTMAPSEL_MASK)
168 /** AHBHOST masters that can use alternate MPAHBRAM ports. */
169 typedef enum {
170 mscDmemMasterLDMA = _SYSCFG_DMEM0PORTMAPSEL_LDMAPORTSEL_SHIFT,
171 mscDmemMasterSRWAES = _SYSCFG_DMEM0PORTMAPSEL_SRWAESPORTSEL_SHIFT,
172 mscDmemMasterAHBSRW = _SYSCFG_DMEM0PORTMAPSEL_AHBSRWPORTSEL_SHIFT,
173 mscDmemMasterSRWECA0 = _SYSCFG_DMEM0PORTMAPSEL_SRWECA0PORTSEL_SHIFT,
174 mscDmemMasterSRWECA1 = _SYSCFG_DMEM0PORTMAPSEL_SRWECA1PORTSEL_SHIFT,
175 #if defined(_SYSCFG_DMEM0PORTMAPSEL_MVPAHBDATA0PORTSEL_MASK)
176 mscDmemMasterMVPAHBDATA0 = _SYSCFG_DMEM0PORTMAPSEL_MVPAHBDATA0PORTSEL_SHIFT,
177 #endif
178 #if defined(_SYSCFG_DMEM0PORTMAPSEL_MVPAHBDATA1PORTSEL_MASK)
179 mscDmemMasterMVPAHBDATA1 = _SYSCFG_DMEM0PORTMAPSEL_MVPAHBDATA1PORTSEL_SHIFT,
180 #endif
181 #if defined(_SYSCFG_DMEM0PORTMAPSEL_MVPAHBDATA2PORTSEL_MASK)
182 mscDmemMasterMVPAHBDATA2 = _SYSCFG_DMEM0PORTMAPSEL_MVPAHBDATA2PORTSEL_SHIFT,
183 #endif
184 #if defined(_SYSCFG_DMEM0PORTMAPSEL_LDMA1PORTSEL_MASK)
185 mscDmemMasterLDMA1 = _SYSCFG_DMEM0PORTMAPSEL_LDMA1PORTSEL_SHIFT,
186 #endif
187 #if defined(_SYSCFG_DMEM0PORTMAPSEL_SRWLDMAPORTSEL_MASK)
188 mscDmemMasterSRWLDMA = _SYSCFG_DMEM0PORTMAPSEL_SRWLDMAPORTSEL_SHIFT,
189 #endif
190 #if defined(_SYSCFG_DMEM0PORTMAPSEL_USBPORTSEL_MASK)
191 mscDmemMasterUSB = _SYSCFG_DMEM0PORTMAPSEL_USBPORTSEL_SHIFT,
192 #endif
193 #if defined(_SYSCFG_DMEM0PORTMAPSEL_BUFCPORTSEL_MASK)
194 mscDmemMasterBUFC = _SYSCFG_DMEM0PORTMAPSEL_BUFCPORTSEL_SHIFT
195 #endif
196 } MSC_DmemMaster_TypeDef;
197 #endif
198
199 #if defined(_MPAHBRAM_CTRL_AHBPORTPRIORITY_MASK)
200 /** AHB port given priority. */
201 typedef enum {
202 mscPortPriorityNone = _MPAHBRAM_CTRL_AHBPORTPRIORITY_NONE,
203 mscPortPriorityPort0 = _MPAHBRAM_CTRL_AHBPORTPRIORITY_PORT0,
204 mscPortPriorityPort1 = _MPAHBRAM_CTRL_AHBPORTPRIORITY_PORT1,
205 #if defined(_MPAHBRAM_CTRL_AHBPORTPRIORITY_PORT2)
206 mscPortPriorityPort2 = _MPAHBRAM_CTRL_AHBPORTPRIORITY_PORT2,
207 #endif
208 #if defined(_MPAHBRAM_CTRL_AHBPORTPRIORITY_PORT3)
209 mscPortPriorityPort3 = _MPAHBRAM_CTRL_AHBPORTPRIORITY_PORT3,
210 #endif
211 } MSC_PortPriority_TypeDef;
212 #endif
213
214 #if defined(MSC_READCTRL_DOUTBUFEN) || defined(MSC_RDATACTRL_DOUTBUFEN)
215 /** Code execution configuration */
216 typedef struct {
217 bool doutBufEn; /**< Flash dout pipeline buffer enable */
218 } MSC_ExecConfig_TypeDef;
219
220 /** Default MSC ExecConfig initialization */
221 #define MSC_EXECCONFIG_DEFAULT \
222 { \
223 false, \
224 }
225
226 #else
227 /** Code execution configuration. */
228 typedef struct {
229 bool scbtEn; /**< Enable Suppressed Conditional Branch Target Prefetch. */
230 bool prefetchEn; /**< Enable MSC prefetching. */
231 bool ifcDis; /**< Disable instruction cache. */
232 bool aiDis; /**< Disable automatic cache invalidation on write or erase. */
233 bool iccDis; /**< Disable automatic caching of fetches in interrupt context. */
234 bool useHprot; /**< Use ahb_hprot to determine if the instruction is cacheable or not. */
235 } MSC_ExecConfig_TypeDef;
236
237 /** Default MSC ExecConfig initialization. */
238 #define MSC_EXECCONFIG_DEFAULT \
239 { \
240 false, \
241 true, \
242 false, \
243 false, \
244 false, \
245 false, \
246 }
247 #endif
248
249 #if defined(_MSC_ECCCTRL_MASK) \
250 || defined(_SYSCFG_DMEM0ECCCTRL_MASK) \
251 || defined(_MPAHBRAM_CTRL_MASK)
252
253 #if defined(_SILICON_LABS_32B_SERIES_1_CONFIG_1)
254 /** EFM32GG11B incorporates 2 memory banks including ECC support. */
255 #define MSC_ECC_BANKS (2)
256
257 /** Default MSC EccConfig initialization. */
258 #define MSC_ECCCONFIG_DEFAULT \
259 { \
260 { false, false }, \
261 { 0, 1 }, \
262 }
263
264 #elif defined(_SILICON_LABS_GECKO_INTERNAL_SDID_106)
265 /** EFM32GG12B incorporates 3 memory banks including ECC support. */
266 #define MSC_ECC_BANKS (3)
267
268 /** Default MSC EccConfig initialization. */
269 #define MSC_ECCCONFIG_DEFAULT \
270 { \
271 { false, false, false }, \
272 { 0, 1 }, \
273 }
274
275 #elif defined(_SILICON_LABS_32B_SERIES_2)
276
277 /** Series 2 chips incorporate 1 memory bank including ECC support. */
278 #define MSC_ECC_BANKS (1)
279 /** Default MSC EccConfig initialization */
280 #define MSC_ECCCONFIG_DEFAULT \
281 { \
282 { false }, \
283 { 0, 1 }, \
284 }
285
286 #else
287 #error Device not supported.
288 #endif
289
290 /** ECC configuration. */
291 typedef struct {
292 bool enableEccBank[MSC_ECC_BANKS]; /**< Array of bools to enable/disable
293 Error Correcting Code (ECC) for
294 each RAM bank that supports ECC on
295 the device. */
296 uint32_t dmaChannels[2]; /**< Array of 2 DMA channel numbers to
297 use for ECC initialization. */
298 } MSC_EccConfig_TypeDef;
299
300 #endif /* #if defined(_MSC_ECCCTRL_MASK) */
301
302 /** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
303 /* Deprecated type names. */
304 #define mscBusStrategy_Typedef MSC_BusStrategy_Typedef
305 #define msc_Return_TypeDef MSC_Status_TypeDef
306 /** @endcond */
307
308 /*******************************************************************************
309 ************************* Inline Functions ********************************
310 ******************************************************************************/
311
312 /***************************************************************************//**
313 * @brief
314 * Get the status of the MSC register lock.
315 *
316 * @return
317 * Boolean true if register lock is applied, false otherwise.
318 ******************************************************************************/
MSC_LockGetLocked(void)319 __STATIC_INLINE bool MSC_LockGetLocked(void)
320 {
321 #if defined(SL_CATALOG_TZ_SECURE_KEY_LIBRARY_NS_PRESENT)
322 return (bool)sli_tz_ns_interface_dispatch_simple(
323 (sli_tz_simple_veneer_fn)sli_tz_msc_get_locked,
324 SLI_TZ_DISPATCH_UNUSED_ARG);
325 #elif defined(_MSC_STATUS_REGLOCK_MASK)
326 return (MSC->STATUS & _MSC_STATUS_REGLOCK_MASK) != MSC_STATUS_REGLOCK_UNLOCKED;
327 #else
328 return (MSC->LOCK & _MSC_LOCK_MASK) != MSC_LOCK_LOCKKEY_UNLOCK;
329 #endif
330 }
331
332 /***************************************************************************//**
333 * @brief
334 * Set the MSC register lock to a locked state.
335 ******************************************************************************/
MSC_LockSetLocked(void)336 __STATIC_INLINE void MSC_LockSetLocked(void)
337 {
338 #if defined(SL_CATALOG_TZ_SECURE_KEY_LIBRARY_NS_PRESENT)
339 (void)sli_tz_ns_interface_dispatch_simple(
340 (sli_tz_simple_veneer_fn)sli_tz_msc_set_locked,
341 SLI_TZ_DISPATCH_UNUSED_ARG);
342 #else
343 MSC->LOCK = MSC_LOCK_LOCKKEY_LOCK;
344 #endif
345 }
346
347 /***************************************************************************//**
348 * @brief
349 * Set the MSC register lock to an unlocked state.
350 ******************************************************************************/
MSC_LockSetUnlocked(void)351 __STATIC_INLINE void MSC_LockSetUnlocked(void)
352 {
353 #if defined(SL_CATALOG_TZ_SECURE_KEY_LIBRARY_NS_PRESENT)
354 (void)sli_tz_ns_interface_dispatch_simple(
355 (sli_tz_simple_veneer_fn)sli_tz_msc_set_unlocked,
356 SLI_TZ_DISPATCH_UNUSED_ARG);
357 #else
358 MSC->LOCK = MSC_LOCK_LOCKKEY_UNLOCK;
359 #endif
360 }
361
362 /***************************************************************************//**
363 * @brief
364 * Get the current value of the read control register (MSC_READCTRL).
365 *
366 * @return
367 * The 32-bit value read from the MSC_READCTRL register.
368 ******************************************************************************/
MSC_ReadCTRLGet(void)369 __STATIC_INLINE uint32_t MSC_ReadCTRLGet(void)
370 {
371 #if defined(SL_CATALOG_TZ_SECURE_KEY_LIBRARY_NS_PRESENT)
372 return sli_tz_ns_interface_dispatch_simple(
373 (sli_tz_simple_veneer_fn)sli_tz_msc_get_readctrl,
374 SLI_TZ_DISPATCH_UNUSED_ARG);
375 #else
376 return MSC->READCTRL;
377 #endif
378 }
379
380 /***************************************************************************//**
381 * @brief
382 * Write a value to the read control register (MSC_READCTRL).
383 *
384 * @param[in] value
385 * The 32-bit value to write to the MSC_READCTRL register.
386 ******************************************************************************/
MSC_ReadCTRLSet(uint32_t value)387 __STATIC_INLINE void MSC_ReadCTRLSet(uint32_t value)
388 {
389 #if defined(SL_CATALOG_TZ_SECURE_KEY_LIBRARY_NS_PRESENT)
390 (void)sli_tz_ns_interface_dispatch_simple(
391 (sli_tz_simple_veneer_fn)sli_tz_msc_set_readctrl,
392 value);
393 #else
394 MSC->READCTRL = value;
395 #endif
396 }
397
398 #if defined(_MSC_PAGELOCK0_MASK) || defined(_MSC_INST_PAGELOCKWORD0_MASK)
399
400 /***************************************************************************//**
401 * @brief
402 * Set the lockbit for a flash page in order to prevent page writes/erases to
403 * the corresponding page.
404 *
405 * @param[in] page_number
406 * The index of the page to apply the pagelock to. Must be in the range
407 * [0, (flash_size / page_size) - 1].
408 ******************************************************************************/
MSC_PageLockSetLocked(uint32_t page_number)409 __STATIC_INLINE void MSC_PageLockSetLocked(uint32_t page_number)
410 {
411 #if defined(SL_CATALOG_TZ_SECURE_KEY_LIBRARY_NS_PRESENT)
412 (void)sli_tz_ns_interface_dispatch_simple(
413 (sli_tz_simple_veneer_fn)sli_tz_msc_set_pagelock,
414 page_number);
415 #else
416 EFM_ASSERT(page_number < (FLASH_SIZE / FLASH_PAGE_SIZE));
417
418 #if defined(_MSC_PAGELOCK0_MASK)
419 uint32_t *pagelock_registers = (uint32_t *)&MSC->PAGELOCK0;
420 #elif defined(_MSC_INST_PAGELOCKWORD0_MASK)
421 uint32_t *pagelock_registers = (uint32_t *)&MSC->INST_PAGELOCKWORD0;
422 #endif
423
424 pagelock_registers[page_number / 32] |= (1 << (page_number % 32));
425 #endif
426 }
427
428 /***************************************************************************//**
429 * @brief
430 * Get the value of the lockbit for a flash page.
431 *
432 * @param[in] page_number
433 * The index of the page to get the lockbit value from. Must be in the range
434 * [0, (flash_size / page_size) - 1].
435 *
436 * @return
437 * Boolean true if the page is locked, false otherwise.
438 ******************************************************************************/
MSC_PageLockGetLocked(uint32_t page_number)439 __STATIC_INLINE bool MSC_PageLockGetLocked(uint32_t page_number)
440 {
441 #if defined(SL_CATALOG_TZ_SECURE_KEY_LIBRARY_NS_PRESENT)
442 return (bool)sli_tz_ns_interface_dispatch_simple(
443 (sli_tz_simple_veneer_fn)sli_tz_msc_get_pagelock,
444 page_number);
445 #else
446 EFM_ASSERT(page_number < (FLASH_SIZE / FLASH_PAGE_SIZE));
447
448 #if defined(_MSC_PAGELOCK0_MASK)
449 uint32_t *pagelock_registers = (uint32_t *)&MSC->PAGELOCK0;
450 #elif defined(_MSC_INST_PAGELOCKWORD0_MASK)
451 uint32_t *pagelock_registers = (uint32_t *)&MSC->INST_PAGELOCKWORD0;
452 #endif
453
454 return pagelock_registers[page_number / 32] & (1 << (page_number % 32));
455 #endif
456 }
457
458 #endif // _MSC_PAGELOCK0_MASK || _MSC_INST_PAGELOCKWORD0_MASK
459
460 #if defined(_MSC_USERDATASIZE_MASK)
461
462 /***************************************************************************//**
463 * @brief
464 * Get the size of the user data region in flash.
465 *
466 * @return
467 * The size of the user data region divided by 256.
468 ******************************************************************************/
MSC_UserDataGetSize(void)469 __STATIC_INLINE uint32_t MSC_UserDataGetSize(void)
470 {
471 #if defined(SL_CATALOG_TZ_SECURE_KEY_LIBRARY_NS_PRESENT)
472 return sli_tz_ns_interface_dispatch_simple(
473 (sli_tz_simple_veneer_fn)sli_tz_msc_get_userdata_size,
474 SLI_TZ_DISPATCH_UNUSED_ARG);
475 #else
476 return MSC->USERDATASIZE;
477 #endif
478 }
479
480 #endif // _MSC_USERDATASIZE_MASK
481
482 #if defined(_MSC_MISCLOCKWORD_MASK)
483
484 /***************************************************************************//**
485 * @brief
486 * Get the current value of the mass erase and user data page lock word
487 * (MSC_MISCLOCKWORD).
488 *
489 * @return
490 * The 32-bit value read from the MSC_MISCLOCKWORD register.
491 ******************************************************************************/
MSC_MiscLockWordGet(void)492 __STATIC_INLINE uint32_t MSC_MiscLockWordGet(void)
493 {
494 #if defined(SL_CATALOG_TZ_SECURE_KEY_LIBRARY_NS_PRESENT)
495 return sli_tz_ns_interface_dispatch_simple(
496 (sli_tz_simple_veneer_fn)sli_tz_msc_get_misclockword,
497 SLI_TZ_DISPATCH_UNUSED_ARG);
498 #else
499 return MSC->MISCLOCKWORD;
500 #endif
501 }
502
503 /***************************************************************************//**
504 * @brief
505 * Write a value to the mass erase and user data page lock word
506 * (MSC_MISCLOCKWORD).
507 *
508 * @param[in] value
509 * The 32-bit value to write to the MSC_MISCLOCKWORD register.
510 ******************************************************************************/
MSC_MiscLockWordSet(uint32_t value)511 __STATIC_INLINE void MSC_MiscLockWordSet(uint32_t value)
512 {
513 #if defined(SL_CATALOG_TZ_SECURE_KEY_LIBRARY_NS_PRESENT)
514 (void)sli_tz_ns_interface_dispatch_simple(
515 (sli_tz_simple_veneer_fn)sli_tz_msc_set_misclockword,
516 value);
517 #else
518 MSC->MISCLOCKWORD = value;
519 #endif
520 }
521
522 #endif // _MSC_USERDATASIZE_MASK
523
524 #if !defined(SL_CATALOG_TZ_SECURE_KEY_LIBRARY_NS_PRESENT)
525
526 /***************************************************************************//**
527 * @brief
528 * Clear one or more pending MSC interrupts.
529 *
530 * @param[in] flags
531 * Pending MSC interrupt source to clear. Use a bitwise logic OR combination
532 * of valid interrupt flags for the MSC module (MSC_IF_nnn).
533 ******************************************************************************/
MSC_IntClear(uint32_t flags)534 __STATIC_INLINE void MSC_IntClear(uint32_t flags)
535 {
536 #if defined(MSC_HAS_SET_CLEAR)
537 MSC->IF_CLR = flags;
538 #else
539 MSC->IFC = flags;
540 #endif
541 }
542
543 /***************************************************************************//**
544 * @brief
545 * Disable one or more MSC interrupts.
546 *
547 * @param[in] flags
548 * MSC interrupt sources to disable. Use a bitwise logic OR combination of
549 * valid interrupt flags for the MSC module (MSC_IF_nnn).
550 ******************************************************************************/
MSC_IntDisable(uint32_t flags)551 __STATIC_INLINE void MSC_IntDisable(uint32_t flags)
552 {
553 #if defined(MSC_HAS_SET_CLEAR)
554 MSC->IEN_CLR = flags;
555 #else
556 MSC->IEN &= ~(flags);
557 #endif
558 }
559
560 /***************************************************************************//**
561 * @brief
562 * Enable one or more MSC interrupts.
563 *
564 * @note
565 * Depending on the use, a pending interrupt may already be set prior to
566 * enabling the interrupt. To ignore a pending interrupt, consider using
567 * MSC_IntClear() prior to enabling the interrupt.
568 *
569 * @param[in] flags
570 * MSC interrupt sources to enable. Use a bitwise logic OR combination of
571 * valid interrupt flags for the MSC module (MSC_IF_nnn).
572 ******************************************************************************/
MSC_IntEnable(uint32_t flags)573 __STATIC_INLINE void MSC_IntEnable(uint32_t flags)
574 {
575 #if defined(MSC_HAS_SET_CLEAR)
576 MSC->IEN_SET = flags;
577 #else
578 MSC->IEN |= flags;
579 #endif
580 }
581
582 /***************************************************************************//**
583 * @brief
584 * Get pending MSC interrupt flags.
585 *
586 * @note
587 * The event bits are not cleared by the use of this function.
588 *
589 * @return
590 * MSC interrupt sources pending. A bitwise logic OR combination of valid
591 * interrupt flags for the MSC module (MSC_IF_nnn).
592 ******************************************************************************/
MSC_IntGet(void)593 __STATIC_INLINE uint32_t MSC_IntGet(void)
594 {
595 return MSC->IF;
596 }
597
598 /***************************************************************************//**
599 * @brief
600 * Get enabled and pending MSC interrupt flags.
601 * Useful for handling more interrupt sources in the same interrupt handler.
602 *
603 * @note
604 * Interrupt flags are not cleared by the use of this function.
605 *
606 * @return
607 * Pending and enabled MSC interrupt sources.
608 * The return value is the bitwise AND of
609 * - the enabled interrupt sources in MSC_IEN and
610 * - the pending interrupt flags MSC_IF
611 ******************************************************************************/
MSC_IntGetEnabled(void)612 __STATIC_INLINE uint32_t MSC_IntGetEnabled(void)
613 {
614 uint32_t ien;
615
616 ien = MSC->IEN;
617 return MSC->IF & ien;
618 }
619
620 /***************************************************************************//**
621 * @brief
622 * Set one or more pending MSC interrupts from SW.
623 *
624 * @param[in] flags
625 * MSC interrupt sources to set to pending. Use a bitwise logic OR combination of
626 * valid interrupt flags for the MSC module (MSC_IF_nnn).
627 ******************************************************************************/
MSC_IntSet(uint32_t flags)628 __STATIC_INLINE void MSC_IntSet(uint32_t flags)
629 {
630 #if defined(MSC_HAS_SET_CLEAR)
631 MSC->IF_SET = flags;
632 #else
633 MSC->IFS = flags;
634 #endif
635 }
636
637 #if defined(MSC_IF_CHOF) && defined(MSC_IF_CMOF)
638 /***************************************************************************//**
639 * @brief
640 * Start measuring the cache hit ratio.
641 * @details
642 * Starts performance counters. It is defined inline to
643 * minimize the impact of this code on the measurement itself.
644 ******************************************************************************/
MSC_StartCacheMeasurement(void)645 __STATIC_INLINE void MSC_StartCacheMeasurement(void)
646 {
647 /* Clear CMOF and CHOF to catch these later. */
648 MSC->IFC = MSC_IF_CHOF | MSC_IF_CMOF;
649
650 /* Start performance counters. */
651 #if defined(_MSC_CACHECMD_MASK)
652 MSC->CACHECMD = MSC_CACHECMD_STARTPC;
653 #else
654 MSC->CMD = MSC_CMD_STARTPC;
655 #endif
656 }
657
658 /***************************************************************************//**
659 * @brief
660 * Stop measuring the hit rate.
661 * @note
662 * Defined inline to minimize the impact of this
663 * code on the measurement itself.
664 * Only works for relatively short sections of code.
665 * To measure longer sections of code, implement an IRQ Handler for
666 * the CHOF and CMOF overflow interrupts. These overflows need to be
667 * counted and included in the total.
668 * Functions can then be implemented as follows:
669 * @verbatim
670 * volatile uint32_t hitOverflows
671 * volatile uint32_t missOverflows
672 *
673 * void MSC_IRQHandler(void)
674 * {
675 * uint32_t flags;
676 * flags = MSC->IF;
677 * if (flags & MSC_IF_CHOF) {
678 * MSC->IFC = MSC_IF_CHOF;
679 * hitOverflows++;
680 * }
681 * if (flags & MSC_IF_CMOF) {
682 * MSC->IFC = MSC_IF_CMOF;
683 * missOverflows++;
684 * }
685 * }
686 *
687 * void startPerformanceCounters(void)
688 * {
689 * hitOverflows = 0;
690 * missOverflows = 0;
691 *
692 * MSC_IntEnable(MSC_IF_CHOF | MSC_IF_CMOF);
693 * NVIC_EnableIRQ(MSC_IRQn);
694 *
695 * MSC_StartCacheMeasurement();
696 * }
697 * @endverbatim
698 * @return
699 * Returns -1 if there has been no cache accesses.
700 * Returns -2 if there has been an overflow in the performance counters.
701 * If not, it will return the percentage of hits versus misses.
702 ******************************************************************************/
MSC_GetCacheMeasurement(void)703 __STATIC_INLINE int32_t MSC_GetCacheMeasurement(void)
704 {
705 int32_t total;
706 int32_t hits;
707 /* Stop counter before computing hit-rate. */
708 #if defined(_MSC_CACHECMD_MASK)
709 MSC->CACHECMD = MSC_CACHECMD_STOPPC;
710 #else
711 MSC->CMD = MSC_CMD_STOPPC;
712 #endif
713
714 /* Check for overflows in performance counters. */
715 if (MSC->IF & (MSC_IF_CHOF | MSC_IF_CMOF)) {
716 return -2;
717 }
718
719 hits = (int32_t)MSC->CACHEHITS;
720 total = (int32_t)MSC->CACHEMISSES + hits;
721
722 /* To avoid a division by zero. */
723 if (total == 0) {
724 return -1;
725 }
726
727 return (hits * 100) / total;
728 }
729
730 /***************************************************************************//**
731 * @brief
732 * Flush contents of instruction cache.
733 ******************************************************************************/
MSC_FlushCache(void)734 __STATIC_INLINE void MSC_FlushCache(void)
735 {
736 #if defined(_MSC_CACHECMD_MASK)
737 MSC->CACHECMD = MSC_CACHECMD_INVCACHE;
738 #else
739 MSC->CMD = MSC_CMD_INVCACHE;
740 #endif
741 }
742
743 /***************************************************************************//**
744 * @brief
745 * Enable or disable instruction cache functionality.
746 * @param[in] enable
747 * Enable instruction cache. Default is on.
748 ******************************************************************************/
MSC_EnableCache(bool enable)749 __STATIC_INLINE void MSC_EnableCache(bool enable)
750 {
751 BUS_RegBitWrite(&(MSC->READCTRL), _MSC_READCTRL_IFCDIS_SHIFT, !enable);
752 }
753
754 #if defined(MSC_READCTRL_ICCDIS)
755 /***************************************************************************//**
756 * @brief
757 * Enable or disable instruction cache functionality in IRQs.
758 * @param[in] enable
759 * Enable instruction cache. Default is on.
760 ******************************************************************************/
MSC_EnableCacheIRQs(bool enable)761 __STATIC_INLINE void MSC_EnableCacheIRQs(bool enable)
762 {
763 BUS_RegBitWrite(&(MSC->READCTRL), _MSC_READCTRL_ICCDIS_SHIFT, !enable);
764 }
765 #endif
766
767 /***************************************************************************//**
768 * @brief
769 * Enable or disable instruction cache flushing when writing to flash.
770 * @param[in] enable
771 * Enable automatic cache flushing. Default is on.
772 ******************************************************************************/
MSC_EnableAutoCacheFlush(bool enable)773 __STATIC_INLINE void MSC_EnableAutoCacheFlush(bool enable)
774 {
775 BUS_RegBitWrite(&(MSC->READCTRL), _MSC_READCTRL_AIDIS_SHIFT, !enable);
776 }
777 #endif /* defined( MSC_IF_CHOF ) && defined( MSC_IF_CMOF ) */
778
779 #if defined(_MSC_READCTRL_BUSSTRATEGY_MASK)
780 /***************************************************************************//**
781 * @brief
782 * Configure which unit should get priority on system bus.
783 * @param[in] mode
784 * Unit to prioritize bus accesses for.
785 ******************************************************************************/
MSC_BusStrategy(mscBusStrategy_Typedef mode)786 __STATIC_INLINE void MSC_BusStrategy(mscBusStrategy_Typedef mode)
787 {
788 MSC->READCTRL = (MSC->READCTRL & ~(_MSC_READCTRL_BUSSTRATEGY_MASK)) | mode;
789 }
790 #endif
791
792 /*******************************************************************************
793 ************************* PROTOTYPES **************************************
794 ******************************************************************************/
795
796 void MSC_ExecConfigSet(MSC_ExecConfig_TypeDef *execConfig);
797 #if defined(_MSC_ECCCTRL_MASK) \
798 || defined(_SYSCFG_DMEM0ECCCTRL_MASK) \
799 || defined(_MPAHBRAM_CTRL_MASK)
800 void MSC_EccConfigSet(MSC_EccConfig_TypeDef *eccConfig);
801 #endif
802
803 #if defined(_SYSCFG_DMEM0PORTMAPSEL_MASK)
804 void MSC_DmemPortMapSet(MSC_DmemMaster_TypeDef master, uint8_t port);
805 #endif
806
807 #if defined(_MPAHBRAM_CTRL_AHBPORTPRIORITY_MASK)
808 void MSC_PortSetPriority(MSC_PortPriority_TypeDef portPriority);
809 MSC_PortPriority_TypeDef MSC_PortGetCurrentPriority(void);
810 #endif
811
812 #if !defined(_SILICON_LABS_32B_SERIES_2)
813 /* Note that this function is deprecated because we no longer support
814 * placing msc code in ram. */
815 MSC_RAMFUNC_DECLARATOR
816 MSC_Status_TypeDef MSC_WriteWordFast(uint32_t *address,
817 void const *data,
818 uint32_t numBytes);
819 #endif
820
821 #if defined(MSC_WRITECMD_ERASEMAIN0)
822 /***************************************************************************//**
823 * @brief
824 * Erase the entire Flash in one operation.
825 *
826 * @note
827 * This command will erase the entire contents of the device.
828 * Use with care, both a debug session and all contents of the flash will be
829 * lost. The lock bit, MLW will prevent this operation from executing and
830 * might prevent a successful mass erase.
831 *
832 * @return
833 * Returns the status of the operation.
834 ******************************************************************************/
835 SL_RAMFUNC_DECLARATOR
836 MSC_Status_TypeDef MSC_MassErase(void);
837 #endif
838
839 #endif /* !SL_CATALOG_TZ_SECURE_KEY_LIBRARY_NS_PRESENT */
840
841 MSC_RAMFUNC_DECLARATOR
842 MSC_Status_TypeDef MSC_ErasePage(uint32_t *startAddress);
843
844 MSC_RAMFUNC_DECLARATOR
845 MSC_Status_TypeDef MSC_WriteWord(uint32_t *address,
846 void const *data,
847 uint32_t numBytes);
848
849 #if (_SILICON_LABS_32B_SERIES > 0)
850 MSC_Status_TypeDef MSC_WriteWordDma(int ch,
851 uint32_t *address,
852 const void *data,
853 uint32_t numBytes);
854 #endif
855
856 void MSC_Init(void);
857 void MSC_Deinit(void);
858
859 /** @} (end addtogroup msc) */
860
861 #ifdef __cplusplus
862 }
863 #endif
864
865 #endif /* defined(MSC_COUNT) && (MSC_COUNT > 0) */
866 #endif /* EM_MSC_H */
867