LCOV - code coverage report
Current view: top level - zephyr/drivers/interrupt_controller - intc_esp32.h Hit Total Coverage
Test: new.info Lines: 14 56 25.0 %
Date: 2024-12-22 00:14:23

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

Generated by: LCOV version 1.14