LCOV - code coverage report
Current view: top level - zephyr/drivers/interrupt_controller - intc_esp32.h Coverage Total Hit
Test: new.info Lines: 23.2 % 56 13
Test Date: 2025-09-05 22:20:39

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

Generated by: LCOV version 2.0-1