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