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