1 /***************************************************************************//**
2  * @file
3  * @brief Core interrupt handling API (Device Specific)
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 #ifndef EM_CORE_H
31 #define EM_CORE_H
32 
33 #include "em_device.h"
34 #include "em_core_generic.h"
35 #include "sl_common.h"
36 
37 #if defined(EMLIB_USER_CONFIG)
38 #include "emlib_config.h"
39 #endif
40 
41 #if defined(SL_COMPONENT_CATALOG_PRESENT)
42 #include "sl_component_catalog.h"
43 #endif
44 
45 #if defined(SL_CATALOG_EMLIB_CORE_DEBUG_CONFIG_PRESENT)
46 #include "emlib_core_debug_config.h"
47 #endif
48 
49 #if !defined(SL_EMLIB_CORE_ENABLE_INTERRUPT_DISABLED_TIMING)
50 #define SL_EMLIB_CORE_ENABLE_INTERRUPT_DISABLED_TIMING   0
51 #endif
52 
53 /***************************************************************************//**
54  * @addtogroup core
55  * @{
56  ******************************************************************************/
57 
58 /*******************************************************************************
59  *******************************   DEFINES   ***********************************
60  ******************************************************************************/
61 
62 /** Number of words in a NVIC mask set. */
63 #define CORE_NVIC_REG_WORDS   ((EXT_IRQ_COUNT + 31) / 32)
64 
65 /** Number of entries in a default interrupt vector table. */
66 #define CORE_DEFAULT_VECTOR_TABLE_ENTRIES   (EXT_IRQ_COUNT + 16)
67 
68 // Interrupt priorities based on processor architecture
69 #if defined(__CM3_REV) || defined(__CM4_REV) || defined(__CM7_REV) \
70   || defined(__CM23_REV) || defined(__CM33_REV)
71 
72 /** Highest priority for core interrupt. */
73 #define CORE_INTERRUPT_HIGHEST_PRIORITY 0
74 
75 /** Default priority for core interrupt. */
76 #define CORE_INTERRUPT_DEFAULT_PRIORITY 5
77 
78 /** Lowest priority for core interrupt. */
79 #define CORE_INTERRUPT_LOWEST_PRIORITY 7
80 
81 /** Default method to disable interrupts in ATOMIC sections. */
82 #define CORE_ATOMIC_METHOD_DEFAULT  CORE_ATOMIC_METHOD_BASEPRI
83 #elif defined(__CM0_REV) || defined(__CM0PLUS_REV)
84 
85 /** Highest priority for core interrupt. */
86 #define CORE_INTERRUPT_HIGHEST_PRIORITY 0
87 
88 /** Default priority for core interrupt. */
89 #define CORE_INTERRUPT_DEFAULT_PRIORITY 1
90 
91 /** Lowest priority for core interrupt. */
92 #define CORE_INTERRUPT_LOWEST_PRIORITY 3
93 
94 /** Default method to disable interrupts in ATOMIC sections. */
95 #define CORE_ATOMIC_METHOD_DEFAULT  CORE_ATOMIC_METHOD_PRIMASK
96 #endif
97 
98 #if !defined(CORE_ATOMIC_METHOD)
99 /** Specify which method to use when implementing ATOMIC sections. You can
100  *  select between BASEPRI or PRIMASK method.
101  *  @note On Cortex-M0+ devices only PRIMASK can be used. */
102 #if !defined(SL_CATALOG_DEVICE_INIT_NVIC_PRESENT)
103 #define CORE_ATOMIC_METHOD    CORE_ATOMIC_METHOD_PRIMASK
104 #else
105 #define CORE_ATOMIC_METHOD   CORE_ATOMIC_METHOD_DEFAULT
106 #endif
107 #endif
108 
109 // Compile time sanity check.
110 #if (CORE_NVIC_REG_WORDS > 3)
111 #error "em_core: Unexpected NVIC external interrupt count."
112 #endif
113 
114 #ifdef __cplusplus
115 extern "C" {
116 #endif
117 
118 /*******************************************************************************
119  ************************   MACRO API   ***************************************
120  ******************************************************************************/
121 
122 //
123 //  NVIC mask section macro API.
124 //
125 
126 /** Allocate storage for NVIC interrupt masks for use by
127  *  CORE_ENTER/EXIT_NVIC() macros. */
128 #define CORE_DECLARE_NVIC_STATE       CORE_nvicMask_t nvicState
129 
130 /** Allocate storage for NVIC interrupt masks.
131  *  @param[in] x
132  *    The storage variable name to use.*/
133 #define CORE_DECLARE_NVIC_MASK(x)     CORE_nvicMask_t x
134 
135 /** Allocate storage for and zero initialize NVIC interrupt mask.
136  *  @param[in] x
137  *    The storage variable name to use.*/
138 #define CORE_DECLARE_NVIC_ZEROMASK(x) CORE_nvicMask_t x = { { 0 } }
139 
140 /** NVIC mask style interrupt disable.
141  *  @param[in] mask
142  *    Mask specifying which NVIC interrupts to disable. */
143 #define CORE_NVIC_DISABLE(mask)   CORE_NvicDisableMask(mask)
144 
145 /** NVIC mask style interrupt enable.
146  *  @param[in] mask
147  *    Mask specifying which NVIC interrupts to enable. */
148 #define CORE_NVIC_ENABLE(mask)    CORE_NvicEnableMask(mask)
149 
150 /** Convenience macro for implementing a NVIC mask section.
151  *  @param[in] mask
152  *    Mask specifying which NVIC interrupts to disable within the section.
153  *  @param[in] yourcode
154  *    The code for the section. */
155 #define CORE_NVIC_SECTION(mask, yourcode) \
156   {                                       \
157     CORE_DECLARE_NVIC_STATE;              \
158     CORE_ENTER_NVIC(mask);                \
159     {                                     \
160       yourcode                            \
161     }                                     \
162     CORE_EXIT_NVIC();                     \
163   }
164 
165 /** Enter NVIC mask section. Assumes that a @ref CORE_DECLARE_NVIC_STATE exist
166  *  in scope.
167  *  @param[in] disable
168  *    Mask specifying which NVIC interrupts to disable within the section. */
169 #define CORE_ENTER_NVIC(disable)  CORE_EnterNvicMask(&nvicState, disable)
170 
171 /** Exit NVIC mask section. Assumes that a @ref CORE_DECLARE_NVIC_STATE exist
172  *  in scope. */
173 #define CORE_EXIT_NVIC()          CORE_NvicEnableMask(&nvicState)
174 
175 /** NVIC maks style yield.
176  * @param[in] enable
177  *   Mask specifying which NVIC interrupts to briefly enable. */
178 #define CORE_YIELD_NVIC(enable)   CORE_YieldNvicMask(enable)
179 
180 /*******************************************************************************
181  *************************   TYPEDEFS   ****************************************
182  ******************************************************************************/
183 
184 /** Storage for NVIC interrupt masks. */
185 typedef struct {
186   uint32_t a[CORE_NVIC_REG_WORDS];    /*!< Array of NVIC mask words. */
187 } CORE_nvicMask_t;
188 
189 /*******************************************************************************
190  *****************************   PROTOTYPES   **********************************
191  ******************************************************************************/
192 
193 bool  CORE_IrqIsBlocked(IRQn_Type irqN);
194 
195 void  CORE_GetNvicEnabledMask(CORE_nvicMask_t *mask);
196 bool  CORE_GetNvicMaskDisableState(const CORE_nvicMask_t *mask);
197 
198 void  CORE_EnterNvicMask(CORE_nvicMask_t *nvicState,
199                          const CORE_nvicMask_t *disable);
200 void  CORE_NvicDisableMask(const CORE_nvicMask_t *disable);
201 void  CORE_NvicEnableMask(const CORE_nvicMask_t *enable);
202 void  CORE_YieldNvicMask(const CORE_nvicMask_t *enable);
203 void  CORE_NvicMaskSetIRQ(IRQn_Type irqN, CORE_nvicMask_t *mask);
204 void  CORE_NvicMaskClearIRQ(IRQn_Type irqN, CORE_nvicMask_t *mask);
205 bool  CORE_NvicIRQDisabled(IRQn_Type irqN);
206 
207 void *CORE_GetNvicRamTableHandler(IRQn_Type irqN);
208 void  CORE_SetNvicRamTableHandler(IRQn_Type irqN, void *handler);
209 void  CORE_InitNvicVectorTable(uint32_t *sourceTable,
210                                uint32_t sourceSize,
211                                uint32_t *targetTable,
212                                uint32_t targetSize,
213                                void *defaultHandler,
214                                bool overwriteActive);
215 
216 #if (SL_EMLIB_CORE_ENABLE_INTERRUPT_DISABLED_TIMING == 1)
217 uint32_t CORE_get_max_time_critical_section(void);
218 uint32_t CORE_get_max_time_atomic_section(void);
219 void CORE_clear_max_time_critical_section(void);
220 void CORE_clear_max_time_atomic_section(void);
221 #endif
222 
223 #ifdef __cplusplus
224 }
225 #endif
226 
227 /** @} (end addtogroup core) */
228 
229 #endif /* EM_CORE_H */
230