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