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