1 /***************************************************************************//** 2 * @file 3 * @brief Core interrupt handling 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 #ifndef EM_CORE_H 31 #define EM_CORE_H 32 33 #include "em_device.h" 34 #include "em_common.h" 35 36 #include <stdbool.h> 37 38 #if defined(EMLIB_USER_CONFIG) 39 #include "emlib_config.h" 40 #endif 41 42 #if defined(SL_COMPONENT_CATALOG_PRESENT) 43 #include "sl_component_catalog.h" 44 #endif 45 46 /***************************************************************************//** 47 * @addtogroup core 48 * @{ 49 ******************************************************************************/ 50 51 /******************************************************************************* 52 ******************************* DEFINES *********************************** 53 ******************************************************************************/ 54 55 /** Use PRIMASK register to disable interrupts in ATOMIC sections. */ 56 #define CORE_ATOMIC_METHOD_PRIMASK 0 57 58 /** Use BASEPRI register to disable interrupts in ATOMIC sections. */ 59 #define CORE_ATOMIC_METHOD_BASEPRI 1 60 61 /** Number of words in a NVIC mask set. */ 62 #define CORE_NVIC_REG_WORDS ((EXT_IRQ_COUNT + 31) / 32) 63 64 /** Number of entries in a default interrupt vector table. */ 65 #define CORE_DEFAULT_VECTOR_TABLE_ENTRIES (EXT_IRQ_COUNT + 16) 66 67 // Interrupt priorities based on processor architecture 68 #if defined(__CM3_REV) || defined(__CM4_REV) || defined(__CM7_REV) \ 69 || defined(__CM23_REV) || defined(__CM33_REV) 70 #define CORE_INTERRUPT_HIGHEST_PRIORITY 0 71 #define CORE_INTERRUPT_DEFAULT_PRIORITY 5 72 #define CORE_INTERRUPT_LOWEST_PRIORITY 7 73 74 #define CORE_ATOMIC_METHOD_DEFAULT CORE_ATOMIC_METHOD_BASEPRI 75 #elif defined(__CM0_REV) || defined(__CM0PLUS_REV) 76 #define CORE_INTERRUPT_HIGHEST_PRIORITY 0 77 #define CORE_INTERRUPT_DEFAULT_PRIORITY 1 78 #define CORE_INTERRUPT_LOWEST_PRIORITY 3 79 80 #define CORE_ATOMIC_METHOD_DEFAULT CORE_ATOMIC_METHOD_PRIMASK 81 #endif 82 83 #if !defined(CORE_ATOMIC_BASE_PRIORITY_LEVEL) 84 /** The interrupt priority level disabled within ATOMIC regions. Interrupts 85 * with priority level equal to or lower than this definition will be disabled 86 * within ATOMIC regions. */ 87 #define CORE_ATOMIC_BASE_PRIORITY_LEVEL 3 88 #endif 89 90 #if !defined(CORE_ATOMIC_METHOD) 91 /** Specify which method to use when implementing ATOMIC sections. You can 92 * select between BASEPRI or PRIMASK method. 93 * @note On Cortex-M0+ devices only PRIMASK can be used. */ 94 #if !defined(SL_CATALOG_DEVICE_INIT_NVIC_PRESENT) 95 #define CORE_ATOMIC_METHOD CORE_ATOMIC_METHOD_PRIMASK 96 #else 97 #define CORE_ATOMIC_METHOD CORE_ATOMIC_METHOD_DEFAULT 98 #endif 99 #endif 100 101 // Compile time sanity check. 102 #if (CORE_NVIC_REG_WORDS > 3) 103 #error "em_core: Unexpected NVIC external interrupt count." 104 #endif 105 106 #ifdef __cplusplus 107 extern "C" { 108 #endif 109 110 /******************************************************************************* 111 ************************ MACRO API *************************************** 112 ******************************************************************************/ 113 114 // 115 // CRITICAL section macro API. 116 // 117 118 /** Allocate storage for PRIMASK or BASEPRI value for use by 119 * CORE_ENTER/EXIT_ATOMIC() and CORE_ENTER/EXIT_CRITICAL() macros. */ 120 #define CORE_DECLARE_IRQ_STATE CORE_irqState_t irqState 121 122 /** CRITICAL style interrupt disable. */ 123 #define CORE_CRITICAL_IRQ_DISABLE() CORE_CriticalDisableIrq() 124 125 /** CRITICAL style interrupt enable. */ 126 #define CORE_CRITICAL_IRQ_ENABLE() CORE_CriticalEnableIrq() 127 128 /** Convenience macro for implementing a CRITICAL section. */ 129 #define CORE_CRITICAL_SECTION(yourcode) \ 130 { \ 131 CORE_DECLARE_IRQ_STATE; \ 132 CORE_ENTER_CRITICAL(); \ 133 { \ 134 yourcode \ 135 } \ 136 CORE_EXIT_CRITICAL(); \ 137 } 138 139 /** Enter CRITICAL section. Assumes that a @ref CORE_DECLARE_IRQ_STATE exist in 140 * scope. */ 141 #define CORE_ENTER_CRITICAL() irqState = CORE_EnterCritical() 142 143 /** Exit CRITICAL section. Assumes that a @ref CORE_DECLARE_IRQ_STATE exist in 144 * scope. */ 145 #define CORE_EXIT_CRITICAL() CORE_ExitCritical(irqState) 146 147 /** CRITICAL style yield. */ 148 #define CORE_YIELD_CRITICAL() CORE_YieldCritical() 149 150 // 151 // ATOMIC section macro API. 152 // 153 154 /** ATOMIC style interrupt disable. */ 155 #define CORE_ATOMIC_IRQ_DISABLE() CORE_AtomicDisableIrq() 156 157 /** ATOMIC style interrupt enable. */ 158 #define CORE_ATOMIC_IRQ_ENABLE() CORE_AtomicEnableIrq() 159 160 /** Convenience macro for implementing an ATOMIC section. */ 161 #define CORE_ATOMIC_SECTION(yourcode) \ 162 { \ 163 CORE_DECLARE_IRQ_STATE; \ 164 CORE_ENTER_ATOMIC(); \ 165 { \ 166 yourcode \ 167 } \ 168 CORE_EXIT_ATOMIC(); \ 169 } 170 171 /** Enter ATOMIC section. Assumes that a @ref CORE_DECLARE_IRQ_STATE exist in 172 * scope. */ 173 #define CORE_ENTER_ATOMIC() irqState = CORE_EnterAtomic() 174 175 /** Exit ATOMIC section. Assumes that a @ref CORE_DECLARE_IRQ_STATE exist in 176 * scope. */ 177 #define CORE_EXIT_ATOMIC() CORE_ExitAtomic(irqState) 178 179 /** ATOMIC style yield. */ 180 #define CORE_YIELD_ATOMIC() CORE_YieldAtomic() 181 182 // 183 // NVIC mask section macro API. 184 // 185 186 /** Allocate storage for NVIC interrupt masks for use by 187 * CORE_ENTER/EXIT_NVIC() macros. */ 188 #define CORE_DECLARE_NVIC_STATE CORE_nvicMask_t nvicState 189 190 /** Allocate storage for NVIC interrupt masks. 191 * @param[in] x 192 * The storage variable name to use.*/ 193 #define CORE_DECLARE_NVIC_MASK(x) CORE_nvicMask_t x 194 195 /** Allocate storage for and zero initialize NVIC interrupt mask. 196 * @param[in] x 197 * The storage variable name to use.*/ 198 #define CORE_DECLARE_NVIC_ZEROMASK(x) CORE_nvicMask_t x = { { 0 } } 199 200 /** NVIC mask style interrupt disable. 201 * @param[in] mask 202 * Mask specifying which NVIC interrupts to disable. */ 203 #define CORE_NVIC_DISABLE(mask) CORE_NvicDisableMask(mask) 204 205 /** NVIC mask style interrupt enable. 206 * @param[in] mask 207 * Mask specifying which NVIC interrupts to enable. */ 208 #define CORE_NVIC_ENABLE(mask) CORE_NvicEnableMask(mask) 209 210 /** Convenience macro for implementing a NVIC mask section. 211 * @param[in] mask 212 * Mask specifying which NVIC interrupts to disable within the section. 213 * @param[in] yourcode 214 * The code for the section. */ 215 #define CORE_NVIC_SECTION(mask, yourcode) \ 216 { \ 217 CORE_DECLARE_NVIC_STATE; \ 218 CORE_ENTER_NVIC(mask); \ 219 { \ 220 yourcode \ 221 } \ 222 CORE_EXIT_NVIC(); \ 223 } 224 225 /** Enter NVIC mask section. Assumes that a @ref CORE_DECLARE_NVIC_STATE exist 226 * in scope. 227 * @param[in] disable 228 * Mask specifying which NVIC interrupts to disable within the section. */ 229 #define CORE_ENTER_NVIC(disable) CORE_EnterNvicMask(&nvicState, disable) 230 231 /** Exit NVIC mask section. Assumes that a @ref CORE_DECLARE_NVIC_STATE exist 232 * in scope. */ 233 #define CORE_EXIT_NVIC() CORE_NvicEnableMask(&nvicState) 234 235 /** NVIC maks style yield. 236 * @param[in] enable 237 * Mask specifying which NVIC interrupts to briefly enable. */ 238 #define CORE_YIELD_NVIC(enable) CORE_YieldNvicMask(enable) 239 240 // 241 // Miscellaneous macros. 242 // 243 244 /** Check if IRQ is disabled. */ 245 #define CORE_IRQ_DISABLED() CORE_IrqIsDisabled() 246 247 /** Check if inside an IRQ handler. */ 248 #define CORE_IN_IRQ_CONTEXT() CORE_InIrqContext() 249 250 /******************************************************************************* 251 ************************* TYPEDEFS **************************************** 252 ******************************************************************************/ 253 254 /** Storage for PRIMASK or BASEPRI value. */ 255 typedef uint32_t CORE_irqState_t; 256 257 /** Storage for NVIC interrupt masks. */ 258 typedef struct { 259 uint32_t a[CORE_NVIC_REG_WORDS]; /*!< Array of NVIC mask words. */ 260 } CORE_nvicMask_t; 261 262 /******************************************************************************* 263 ***************************** PROTOTYPES ********************************** 264 ******************************************************************************/ 265 266 void CORE_CriticalDisableIrq(void); 267 void CORE_CriticalEnableIrq(void); 268 void CORE_ExitCritical(CORE_irqState_t irqState); 269 void CORE_YieldCritical(void); 270 CORE_irqState_t CORE_EnterCritical(void); 271 272 void CORE_AtomicDisableIrq(void); 273 void CORE_AtomicEnableIrq(void); 274 void CORE_ExitAtomic(CORE_irqState_t irqState); 275 void CORE_YieldAtomic(void); 276 CORE_irqState_t CORE_EnterAtomic(void); 277 278 bool CORE_InIrqContext(void); 279 bool CORE_IrqIsBlocked(IRQn_Type irqN); 280 bool CORE_IrqIsDisabled(void); 281 282 void CORE_GetNvicEnabledMask(CORE_nvicMask_t *mask); 283 bool CORE_GetNvicMaskDisableState(const CORE_nvicMask_t *mask); 284 285 void CORE_EnterNvicMask(CORE_nvicMask_t *nvicState, 286 const CORE_nvicMask_t *disable); 287 void CORE_NvicDisableMask(const CORE_nvicMask_t *disable); 288 void CORE_NvicEnableMask(const CORE_nvicMask_t *enable); 289 void CORE_YieldNvicMask(const CORE_nvicMask_t *enable); 290 void CORE_NvicMaskSetIRQ(IRQn_Type irqN, CORE_nvicMask_t *mask); 291 void CORE_NvicMaskClearIRQ(IRQn_Type irqN, CORE_nvicMask_t *mask); 292 bool CORE_NvicIRQDisabled(IRQn_Type irqN); 293 294 void *CORE_GetNvicRamTableHandler(IRQn_Type irqN); 295 void CORE_SetNvicRamTableHandler(IRQn_Type irqN, void *handler); 296 void CORE_InitNvicVectorTable(uint32_t *sourceTable, 297 uint32_t sourceSize, 298 uint32_t *targetTable, 299 uint32_t targetSize, 300 void *defaultHandler, 301 bool overwriteActive); 302 303 #ifdef __cplusplus 304 } 305 #endif 306 307 /** @} (end addtogroup core) */ 308 309 #endif /* EM_CORE_H */ 310