esp_intr_alloc.h
1 // Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #ifndef __ESP_INTR_ALLOC_H__ 16 #define __ESP_INTR_ALLOC_H__ 17 18 #include <stdint.h> 19 #include <stdbool.h> 20 #include "esp_err.h" 21 22 #ifdef __cplusplus 23 extern "C" { 24 #endif 25 26 27 /** @addtogroup Intr_Alloc 28 * @{ 29 */ 30 31 32 /** @brief Interrupt allocation flags 33 * 34 * These flags can be used to specify which interrupt qualities the 35 * code calling esp_intr_alloc* needs. 36 * 37 */ 38 39 //Keep the LEVELx values as they are here; they match up with (1<<level) 40 #define ESP_INTR_FLAG_LEVEL1 (1<<1) ///< Accept a Level 1 interrupt vector (lowest priority) 41 #define ESP_INTR_FLAG_LEVEL2 (1<<2) ///< Accept a Level 2 interrupt vector 42 #define ESP_INTR_FLAG_LEVEL3 (1<<3) ///< Accept a Level 3 interrupt vector 43 #define ESP_INTR_FLAG_LEVEL4 (1<<4) ///< Accept a Level 4 interrupt vector 44 #define ESP_INTR_FLAG_LEVEL5 (1<<5) ///< Accept a Level 5 interrupt vector 45 #define ESP_INTR_FLAG_LEVEL6 (1<<6) ///< Accept a Level 6 interrupt vector 46 #define ESP_INTR_FLAG_NMI (1<<7) ///< Accept a Level 7 interrupt vector (highest priority) 47 #define ESP_INTR_FLAG_SHARED (1<<8) ///< Interrupt can be shared between ISRs 48 #define ESP_INTR_FLAG_EDGE (1<<9) ///< Edge-triggered interrupt 49 #define ESP_INTR_FLAG_IRAM (1<<10) ///< ISR can be called if cache is disabled 50 #define ESP_INTR_FLAG_INTRDISABLED (1<<11) ///< Return with this interrupt disabled 51 52 #define ESP_INTR_FLAG_LOWMED (ESP_INTR_FLAG_LEVEL1|ESP_INTR_FLAG_LEVEL2|ESP_INTR_FLAG_LEVEL3) ///< Low and medium prio interrupts. These can be handled in C. 53 #define ESP_INTR_FLAG_HIGH (ESP_INTR_FLAG_LEVEL4|ESP_INTR_FLAG_LEVEL5|ESP_INTR_FLAG_LEVEL6|ESP_INTR_FLAG_NMI) ///< High level interrupts. Need to be handled in assembly. 54 55 #define ESP_INTR_FLAG_LEVELMASK (ESP_INTR_FLAG_LEVEL1|ESP_INTR_FLAG_LEVEL2|ESP_INTR_FLAG_LEVEL3| \ 56 ESP_INTR_FLAG_LEVEL4|ESP_INTR_FLAG_LEVEL5|ESP_INTR_FLAG_LEVEL6| \ 57 ESP_INTR_FLAG_NMI) ///< Mask for all level flags 58 59 60 /** @addtogroup Intr_Alloc_Pseudo_Src 61 * @{ 62 */ 63 64 /** 65 * The esp_intr_alloc* functions can allocate an int for all ETS_*_INTR_SOURCE interrupt sources that 66 * are routed through the interrupt mux. Apart from these sources, each core also has some internal 67 * sources that do not pass through the interrupt mux. To allocate an interrupt for these sources, 68 * pass these pseudo-sources to the functions. 69 */ 70 #define ETS_INTERNAL_TIMER0_INTR_SOURCE -1 ///< Platform timer 0 interrupt source 71 #define ETS_INTERNAL_TIMER1_INTR_SOURCE -2 ///< Platform timer 1 interrupt source 72 #define ETS_INTERNAL_TIMER2_INTR_SOURCE -3 ///< Platform timer 2 interrupt source 73 #define ETS_INTERNAL_SW0_INTR_SOURCE -4 ///< Software int source 1 74 #define ETS_INTERNAL_SW1_INTR_SOURCE -5 ///< Software int source 2 75 #define ETS_INTERNAL_PROFILING_INTR_SOURCE -6 ///< Int source for profiling 76 77 /**@}*/ 78 79 /** Provides SystemView with positive IRQ IDs, otherwise scheduler events are not shown properly 80 */ 81 #define ETS_INTERNAL_INTR_SOURCE_OFF (-ETS_INTERNAL_PROFILING_INTR_SOURCE) 82 83 /** Enable interrupt by interrupt number */ 84 #define ESP_INTR_ENABLE(inum) esp_intr_enable_source(inum) 85 86 /** Disable interrupt by interrupt number */ 87 #define ESP_INTR_DISABLE(inum) esp_intr_disable_source(inum) 88 89 /** Function prototype for interrupt handler function */ 90 typedef void (*intr_handler_t)(void *arg); 91 92 /** Interrupt handler associated data structure */ 93 typedef struct intr_handle_data_t intr_handle_data_t; 94 95 /** Handle to an interrupt handler */ 96 typedef intr_handle_data_t* intr_handle_t ; 97 98 /** 99 * @brief Mark an interrupt as a shared interrupt 100 * 101 * This will mark a certain interrupt on the specified CPU as 102 * an interrupt that can be used to hook shared interrupt handlers 103 * to. 104 * 105 * @param intno The number of the interrupt (0-31) 106 * @param cpu CPU on which the interrupt should be marked as shared (0 or 1) 107 * @param is_in_iram Shared interrupt is for handlers that reside in IRAM and 108 * the int can be left enabled while the flash cache is disabled. 109 * 110 * @return ESP_ERR_INVALID_ARG if cpu or intno is invalid 111 * ESP_OK otherwise 112 */ 113 esp_err_t esp_intr_mark_shared(int intno, int cpu, bool is_in_iram); 114 115 /** 116 * @brief Reserve an interrupt to be used outside of this framework 117 * 118 * This will mark a certain interrupt on the specified CPU as 119 * reserved, not to be allocated for any reason. 120 * 121 * @param intno The number of the interrupt (0-31) 122 * @param cpu CPU on which the interrupt should be marked as shared (0 or 1) 123 * 124 * @return ESP_ERR_INVALID_ARG if cpu or intno is invalid 125 * ESP_OK otherwise 126 */ 127 esp_err_t esp_intr_reserve(int intno, int cpu); 128 129 /** 130 * @brief Allocate an interrupt with the given parameters. 131 * 132 * This finds an interrupt that matches the restrictions as given in the flags 133 * parameter, maps the given interrupt source to it and hooks up the given 134 * interrupt handler (with optional argument) as well. If needed, it can return 135 * a handle for the interrupt as well. 136 * 137 * The interrupt will always be allocated on the core that runs this function. 138 * 139 * If ESP_INTR_FLAG_IRAM flag is used, and handler address is not in IRAM or 140 * RTC_FAST_MEM, then ESP_ERR_INVALID_ARG is returned. 141 * 142 * @param source The interrupt source. One of the ETS_*_INTR_SOURCE interrupt mux 143 * sources, as defined in soc/soc.h, or one of the internal 144 * ETS_INTERNAL_*_INTR_SOURCE sources as defined in this header. 145 * @param flags An ORred mask of the ESP_INTR_FLAG_* defines. These restrict the 146 * choice of interrupts that this routine can choose from. If this value 147 * is 0, it will default to allocating a non-shared interrupt of level 148 * 1, 2 or 3. If this is ESP_INTR_FLAG_SHARED, it will allocate a shared 149 * interrupt of level 1. Setting ESP_INTR_FLAG_INTRDISABLED will return 150 * from this function with the interrupt disabled. 151 * @param handler The interrupt handler. Must be NULL when an interrupt of level >3 152 * is requested, because these types of interrupts aren't C-callable. 153 * @param arg Optional argument for passed to the interrupt handler 154 * @param ret_handle Pointer to an intr_handle_t to store a handle that can later be 155 * used to request details or free the interrupt. Can be NULL if no handle 156 * is required. 157 * 158 * @return ESP_ERR_INVALID_ARG if the combination of arguments is invalid. 159 * ESP_ERR_NOT_FOUND No free interrupt found with the specified flags 160 * ESP_OK otherwise 161 */ 162 esp_err_t esp_intr_alloc(int source, int flags, intr_handler_t handler, void *arg, intr_handle_t *ret_handle); 163 164 165 /** 166 * @brief Allocate an interrupt with the given parameters. 167 * 168 * 169 * This essentially does the same as esp_intr_alloc, but allows specifying a register and mask 170 * combo. For shared interrupts, the handler is only called if a read from the specified 171 * register, ANDed with the mask, returns non-zero. By passing an interrupt status register 172 * address and a fitting mask, this can be used to accelerate interrupt handling in the case 173 * a shared interrupt is triggered; by checking the interrupt statuses first, the code can 174 * decide which ISRs can be skipped 175 * 176 * @param source The interrupt source. One of the ETS_*_INTR_SOURCE interrupt mux 177 * sources, as defined in soc/soc.h, or one of the internal 178 * ETS_INTERNAL_*_INTR_SOURCE sources as defined in this header. 179 * @param flags An ORred mask of the ESP_INTR_FLAG_* defines. These restrict the 180 * choice of interrupts that this routine can choose from. If this value 181 * is 0, it will default to allocating a non-shared interrupt of level 182 * 1, 2 or 3. If this is ESP_INTR_FLAG_SHARED, it will allocate a shared 183 * interrupt of level 1. Setting ESP_INTR_FLAG_INTRDISABLED will return 184 * from this function with the interrupt disabled. 185 * @param intrstatusreg The address of an interrupt status register 186 * @param intrstatusmask A mask. If a read of address intrstatusreg has any of the bits 187 * that are 1 in the mask set, the ISR will be called. If not, it will be 188 * skipped. 189 * @param handler The interrupt handler. Must be NULL when an interrupt of level >3 190 * is requested, because these types of interrupts aren't C-callable. 191 * @param arg Optional argument for passed to the interrupt handler 192 * @param ret_handle Pointer to an intr_handle_t to store a handle that can later be 193 * used to request details or free the interrupt. Can be NULL if no handle 194 * is required. 195 * 196 * @return ESP_ERR_INVALID_ARG if the combination of arguments is invalid. 197 * ESP_ERR_NOT_FOUND No free interrupt found with the specified flags 198 * ESP_OK otherwise 199 */ 200 esp_err_t esp_intr_alloc_intrstatus(int source, int flags, uint32_t intrstatusreg, uint32_t intrstatusmask, intr_handler_t handler, void *arg, intr_handle_t *ret_handle); 201 202 203 /** 204 * @brief Disable and free an interrupt. 205 * 206 * Use an interrupt handle to disable the interrupt and release the resources associated with it. 207 * If the current core is not the core that registered this interrupt, this routine will be assigned to 208 * the core that allocated this interrupt, blocking and waiting until the resource is successfully released. 209 * 210 * @note 211 * When the handler shares its source with other handlers, the interrupt status 212 * bits it's responsible for should be managed properly before freeing it. see 213 * ``esp_intr_disable`` for more details. Please do not call this function in ``esp_ipc_call_blocking``. 214 * 215 * @param handle The handle, as obtained by esp_intr_alloc or esp_intr_alloc_intrstatus 216 * 217 * @return ESP_ERR_INVALID_ARG the handle is NULL 218 * ESP_FAIL failed to release this handle 219 * ESP_OK otherwise 220 */ 221 esp_err_t esp_intr_free(intr_handle_t handle); 222 223 224 /** 225 * @brief Get CPU number an interrupt is tied to 226 * 227 * @param handle The handle, as obtained by esp_intr_alloc or esp_intr_alloc_intrstatus 228 * 229 * @return The core number where the interrupt is allocated 230 */ 231 int esp_intr_get_cpu(intr_handle_t handle); 232 233 /** 234 * @brief Get the allocated interrupt for a certain handle 235 * 236 * @param handle The handle, as obtained by esp_intr_alloc or esp_intr_alloc_intrstatus 237 * 238 * @return The interrupt number 239 */ 240 int esp_intr_get_intno(intr_handle_t handle); 241 242 /** 243 * @brief Disable the interrupt associated with the handle 244 * 245 * @note 246 * 1. For local interrupts (ESP_INTERNAL_* sources), this function has to be called on the 247 * CPU the interrupt is allocated on. Other interrupts have no such restriction. 248 * 2. When several handlers sharing a same interrupt source, interrupt status bits, which are 249 * handled in the handler to be disabled, should be masked before the disabling, or handled 250 * in other enabled interrupts properly. Miss of interrupt status handling will cause infinite 251 * interrupt calls and finally system crash. 252 * 253 * @param handle The handle, as obtained by esp_intr_alloc or esp_intr_alloc_intrstatus 254 * 255 * @return ESP_ERR_INVALID_ARG if the combination of arguments is invalid. 256 * ESP_OK otherwise 257 */ 258 esp_err_t esp_intr_disable(intr_handle_t handle); 259 260 /** 261 * @brief Enable the interrupt associated with the handle 262 * 263 * @note For local interrupts (ESP_INTERNAL_* sources), this function has to be called on the 264 * CPU the interrupt is allocated on. Other interrupts have no such restriction. 265 * 266 * @param handle The handle, as obtained by esp_intr_alloc or esp_intr_alloc_intrstatus 267 * 268 * @return ESP_ERR_INVALID_ARG if the combination of arguments is invalid. 269 * ESP_OK otherwise 270 */ 271 esp_err_t esp_intr_enable(intr_handle_t handle); 272 273 /** 274 * @brief Set the "in IRAM" status of the handler. 275 * 276 * @note Does not work on shared interrupts. 277 * 278 * @param handle The handle, as obtained by esp_intr_alloc or esp_intr_alloc_intrstatus 279 * @param is_in_iram Whether the handler associated with this handle resides in IRAM. 280 * Handlers residing in IRAM can be called when cache is disabled. 281 * 282 * @return ESP_ERR_INVALID_ARG if the combination of arguments is invalid. 283 * ESP_OK otherwise 284 */ 285 esp_err_t esp_intr_set_in_iram(intr_handle_t handle, bool is_in_iram); 286 287 /** 288 * @brief Disable interrupts that aren't specifically marked as running from IRAM 289 */ 290 void esp_intr_noniram_disable(void); 291 292 /** 293 * @brief Re-enable interrupts disabled by esp_intr_noniram_disable 294 */ 295 void esp_intr_noniram_enable(void); 296 297 /** 298 * @brief enable the interrupt source based on its number 299 * @param inum interrupt number from 0 to 31 300 */ 301 void esp_intr_enable_source(int inum); 302 303 /** 304 * @brief disable the interrupt source based on its number 305 * @param inum interrupt number from 0 to 31 306 */ 307 void esp_intr_disable_source(int inum); 308 309 /**@}*/ 310 311 312 #ifdef __cplusplus 313 } 314 #endif 315 316 #endif