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