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