2020-12-28 23:31:54 -05:00
// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD
2016-11-25 04:33:51 -05:00
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
2020-12-28 23:31:54 -05:00
//
2016-11-25 04:33:51 -05:00
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
# include <stdint.h>
# include <stdio.h>
# include <stdlib.h>
# include <stdbool.h>
# include <string.h>
2020-09-29 19:44:12 -04:00
# include <esp_types.h>
# include <limits.h>
# include <assert.h>
2020-12-28 23:31:54 -05:00
# include "sdkconfig.h"
2016-11-25 04:33:51 -05:00
# include "freertos/FreeRTOS.h"
# include "freertos/task.h"
# include "esp_err.h"
# include "esp_log.h"
2019-03-26 04:30:43 -04:00
# include "esp_intr_alloc.h"
2016-11-25 04:33:51 -05:00
# include "esp_attr.h"
2020-09-29 19:44:12 -04:00
# include "hal/cpu_hal.h"
# include "hal/interrupt_controller_hal.h"
2016-11-25 04:33:51 -05:00
2019-08-15 03:05:59 -04:00
# if !CONFIG_FREERTOS_UNICORE
# include "esp_ipc.h"
# endif
2016-11-25 04:33:51 -05:00
static const char * TAG = " intr_alloc " ;
# define ETS_INTERNAL_TIMER0_INTR_NO 6
# define ETS_INTERNAL_TIMER1_INTR_NO 15
# define ETS_INTERNAL_TIMER2_INTR_NO 16
# define ETS_INTERNAL_SW0_INTR_NO 7
# define ETS_INTERNAL_SW1_INTR_NO 29
# define ETS_INTERNAL_PROFILING_INTR_NO 11
/*
Define this to debug the choices made when allocating the interrupt . This leads to much debugging
output within a critical region , which can lead to weird effects like e . g . the interrupt watchdog
being triggered , that is why it is separate from the normal LOG * scheme .
*/
2020-12-28 23:31:54 -05:00
// #define DEBUG_INT_ALLOC_DECISIONS
2016-11-25 04:33:51 -05:00
# ifdef DEBUG_INT_ALLOC_DECISIONS
# define ALCHLOG(...) ESP_EARLY_LOGD(TAG, __VA_ARGS__)
# else
# define ALCHLOG(...) do {} while (0)
# endif
typedef struct shared_vector_desc_t shared_vector_desc_t ;
typedef struct vector_desc_t vector_desc_t ;
struct shared_vector_desc_t {
2016-12-07 08:30:21 -05:00
int disabled : 1 ;
int source : 8 ;
2016-11-25 04:33:51 -05:00
volatile uint32_t * statusreg ;
uint32_t statusmask ;
intr_handler_t isr ;
void * arg ;
shared_vector_desc_t * next ;
} ;
# define VECDESC_FL_RESERVED (1<<0)
# define VECDESC_FL_INIRAM (1<<1)
# define VECDESC_FL_SHARED (1<<2)
# define VECDESC_FL_NONSHARED (1<<3)
2016-12-07 08:30:21 -05:00
//Pack using bitfields for better memory use
2016-11-25 04:33:51 -05:00
struct vector_desc_t {
2016-12-07 08:30:21 -05:00
int flags : 16 ; //OR of VECDESC_FLAG_* defines
unsigned int cpu : 1 ;
unsigned int intno : 5 ;
int source : 8 ; //Interrupt mux flags, used when not shared
2016-11-25 04:33:51 -05:00
shared_vector_desc_t * shared_vec_info ; //used when VECDESC_FL_SHARED
vector_desc_t * next ;
} ;
2016-12-07 08:30:21 -05:00
struct intr_handle_data_t {
2016-11-25 04:33:51 -05:00
vector_desc_t * vector_desc ;
shared_vector_desc_t * shared_vector_desc ;
} ;
2017-03-21 23:07:37 -04:00
typedef struct non_shared_isr_arg_t non_shared_isr_arg_t ;
struct non_shared_isr_arg_t {
intr_handler_t isr ;
void * isr_arg ;
int source ;
} ;
2016-11-25 04:33:51 -05:00
2016-12-07 08:30:21 -05:00
//Linked list of vector descriptions, sorted by cpu.intno value
2017-08-18 03:15:47 -04:00
static vector_desc_t * vector_desc_head = NULL ;
2016-11-25 04:33:51 -05:00
//This bitmask has an 1 if the int should be disabled when the flash is disabled.
2020-09-29 19:44:12 -04:00
static uint32_t non_iram_int_mask [ SOC_CPU_CORES_NUM ] ;
2016-11-25 04:33:51 -05:00
//This bitmask has 1 in it if the int was disabled using esp_intr_noniram_disable.
2020-09-29 19:44:12 -04:00
static uint32_t non_iram_int_disabled [ SOC_CPU_CORES_NUM ] ;
static bool non_iram_int_disabled_flag [ SOC_CPU_CORES_NUM ] ;
2016-11-25 04:33:51 -05:00
2017-03-21 23:07:37 -04:00
# if CONFIG_SYSVIEW_ENABLE
extern uint32_t port_switch_flag [ ] ;
# endif
2016-11-25 04:33:51 -05:00
static portMUX_TYPE spinlock = portMUX_INITIALIZER_UNLOCKED ;
//Inserts an item into vector_desc list so that the list is sorted
2016-12-07 08:30:21 -05:00
//with an incrementing cpu.intno value.
2017-03-21 23:07:37 -04:00
static void insert_vector_desc ( vector_desc_t * to_insert )
2016-11-25 04:33:51 -05:00
{
vector_desc_t * vd = vector_desc_head ;
vector_desc_t * prev = NULL ;
while ( vd ! = NULL ) {
2016-12-07 08:30:21 -05:00
if ( vd - > cpu > to_insert - > cpu ) break ;
if ( vd - > cpu = = to_insert - > cpu & & vd - > intno > = to_insert - > intno ) break ;
2016-11-25 04:33:51 -05:00
prev = vd ;
vd = vd - > next ;
}
2018-05-12 23:46:09 -04:00
if ( ( vector_desc_head = = NULL ) | | ( prev = = NULL ) ) {
2016-11-25 04:33:51 -05:00
//First item
2018-05-12 23:46:09 -04:00
to_insert - > next = vd ;
2016-11-25 04:33:51 -05:00
vector_desc_head = to_insert ;
} else {
prev - > next = to_insert ;
to_insert - > next = vd ;
}
}
//Returns a vector_desc entry for an intno/cpu, or NULL if none exists.
2017-03-21 23:07:37 -04:00
static vector_desc_t * find_desc_for_int ( int intno , int cpu )
2016-11-25 04:33:51 -05:00
{
vector_desc_t * vd = vector_desc_head ;
while ( vd ! = NULL ) {
2016-12-07 08:30:21 -05:00
if ( vd - > cpu = = cpu & & vd - > intno = = intno ) break ;
2016-11-25 04:33:51 -05:00
vd = vd - > next ;
}
return vd ;
}
//Returns a vector_desc entry for an intno/cpu.
//Either returns a preexisting one or allocates a new one and inserts
2016-12-06 01:20:12 -05:00
//it into the list. Returns NULL on malloc fail.
2017-03-21 23:07:37 -04:00
static vector_desc_t * get_desc_for_int ( int intno , int cpu )
2016-11-25 04:33:51 -05:00
{
vector_desc_t * vd = find_desc_for_int ( intno , cpu ) ;
if ( vd = = NULL ) {
2017-09-22 04:02:39 -04:00
vector_desc_t * newvd = heap_caps_malloc ( sizeof ( vector_desc_t ) , MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT ) ;
2016-12-06 01:20:12 -05:00
if ( newvd = = NULL ) return NULL ;
2016-11-25 04:33:51 -05:00
memset ( newvd , 0 , sizeof ( vector_desc_t ) ) ;
2016-12-07 08:30:21 -05:00
newvd - > intno = intno ;
newvd - > cpu = cpu ;
2016-11-25 04:33:51 -05:00
insert_vector_desc ( newvd ) ;
return newvd ;
} else {
return vd ;
}
}
2017-08-18 03:15:47 -04:00
//Returns a vector_desc entry for an source, the cpu parameter is used to tell GPIO_INT and GPIO_NMI from different CPUs
static vector_desc_t * find_desc_for_source ( int source , int cpu )
{
vector_desc_t * vd = vector_desc_head ;
while ( vd ! = NULL ) {
if ( ! ( vd - > flags & VECDESC_FL_SHARED ) ) {
if ( vd - > source = = source & & cpu = = vd - > cpu ) break ;
} else if ( vd - > cpu = = cpu ) {
// check only shared vds for the correct cpu, otherwise skip
bool found = false ;
shared_vector_desc_t * svd = vd - > shared_vec_info ;
assert ( svd ! = NULL ) ;
while ( svd ) {
if ( svd - > source = = source ) {
found = true ;
break ;
}
svd = svd - > next ;
}
if ( found ) break ;
}
vd = vd - > next ;
}
return vd ;
}
2016-11-25 04:33:51 -05:00
esp_err_t esp_intr_mark_shared ( int intno , int cpu , bool is_int_ram )
{
if ( intno > 31 ) return ESP_ERR_INVALID_ARG ;
2020-09-29 19:44:12 -04:00
if ( cpu > = SOC_CPU_CORES_NUM ) return ESP_ERR_INVALID_ARG ;
2016-11-25 04:33:51 -05:00
portENTER_CRITICAL ( & spinlock ) ;
vector_desc_t * vd = get_desc_for_int ( intno , cpu ) ;
2016-12-06 01:20:12 -05:00
if ( vd = = NULL ) {
portEXIT_CRITICAL ( & spinlock ) ;
return ESP_ERR_NO_MEM ;
2017-03-21 23:07:37 -04:00
}
2016-11-25 04:33:51 -05:00
vd - > flags = VECDESC_FL_SHARED ;
if ( is_int_ram ) vd - > flags | = VECDESC_FL_INIRAM ;
portEXIT_CRITICAL ( & spinlock ) ;
return ESP_OK ;
}
esp_err_t esp_intr_reserve ( int intno , int cpu )
{
if ( intno > 31 ) return ESP_ERR_INVALID_ARG ;
2020-09-29 19:44:12 -04:00
if ( cpu > = SOC_CPU_CORES_NUM ) return ESP_ERR_INVALID_ARG ;
2016-11-25 04:33:51 -05:00
portENTER_CRITICAL ( & spinlock ) ;
vector_desc_t * vd = get_desc_for_int ( intno , cpu ) ;
2016-12-06 01:20:12 -05:00
if ( vd = = NULL ) {
portEXIT_CRITICAL ( & spinlock ) ;
return ESP_ERR_NO_MEM ;
2017-03-21 23:07:37 -04:00
}
2016-11-25 04:33:51 -05:00
vd - > flags = VECDESC_FL_RESERVED ;
portEXIT_CRITICAL ( & spinlock ) ;
return ESP_OK ;
}
2017-08-18 03:15:47 -04:00
static bool is_vect_desc_usable ( vector_desc_t * vd , int flags , int cpu , int force )
{
//Check if interrupt is not reserved by design
int x = vd - > intno ;
2020-09-29 19:44:12 -04:00
if ( interrupt_controller_hal_get_cpu_desc_flags ( x , cpu ) = = INTDESC_RESVD ) {
2017-08-23 23:46:19 -04:00
ALCHLOG ( " ....Unusable: reserved " ) ;
2017-08-18 03:15:47 -04:00
return false ;
}
2020-09-29 19:44:12 -04:00
if ( interrupt_controller_hal_get_cpu_desc_flags ( x , cpu ) = = INTDESC_SPECIAL & & force = = - 1 ) {
2017-08-23 23:46:19 -04:00
ALCHLOG ( " ....Unusable: special-purpose int " ) ;
2017-08-18 03:15:47 -04:00
return false ;
}
2020-12-16 12:20:38 -05:00
# ifndef SOC_CPU_HAS_FLEXIBLE_INTC
2017-08-18 03:15:47 -04:00
//Check if the interrupt level is acceptable
2020-12-28 23:31:54 -05:00
if ( ! ( flags & ( 1 < < interrupt_controller_hal_get_level ( x ) ) ) ) {
2017-08-23 23:46:19 -04:00
ALCHLOG ( " ....Unusable: incompatible level " ) ;
2020-12-16 12:20:38 -05:00
return false ;
2017-08-18 03:15:47 -04:00
}
//check if edge/level type matches what we want
2020-12-16 12:20:38 -05:00
if ( ( ( flags & ESP_INTR_FLAG_EDGE ) & & ( interrupt_controller_hal_get_type ( x ) = = INTTP_LEVEL ) ) | |
2020-12-28 23:31:54 -05:00
( ( ( ! ( flags & ESP_INTR_FLAG_EDGE ) ) & & ( interrupt_controller_hal_get_type ( x ) = = INTTP_EDGE ) ) ) ) {
ALCHLOG ( " ....Unusable: incompatible trigger type " ) ;
2017-08-18 03:15:47 -04:00
return false ;
}
2020-12-16 12:20:38 -05:00
# endif
2017-08-18 03:15:47 -04:00
//check if interrupt is reserved at runtime
if ( vd - > flags & VECDESC_FL_RESERVED ) {
2017-08-23 23:46:19 -04:00
ALCHLOG ( " ....Unusable: reserved at runtime. " ) ;
2017-08-18 03:15:47 -04:00
return false ;
}
2019-04-08 06:02:05 -04:00
2017-08-18 03:15:47 -04:00
//Ints can't be both shared and non-shared.
assert ( ! ( ( vd - > flags & VECDESC_FL_SHARED ) & & ( vd - > flags & VECDESC_FL_NONSHARED ) ) ) ;
//check if interrupt already is in use by a non-shared interrupt
if ( vd - > flags & VECDESC_FL_NONSHARED ) {
2017-08-23 23:46:19 -04:00
ALCHLOG ( " ....Unusable: already in (non-shared) use. " ) ;
2017-08-18 03:15:47 -04:00
return false ;
}
// check shared interrupt flags
if ( vd - > flags & VECDESC_FL_SHARED ) {
if ( flags & ESP_INTR_FLAG_SHARED ) {
bool in_iram_flag = ( ( flags & ESP_INTR_FLAG_IRAM ) ! = 0 ) ;
bool desc_in_iram_flag = ( ( vd - > flags & VECDESC_FL_INIRAM ) ! = 0 ) ;
//Bail out if int is shared, but iram property doesn't match what we want.
if ( ( vd - > flags & VECDESC_FL_SHARED ) & & ( desc_in_iram_flag ! = in_iram_flag ) ) {
2017-08-23 23:46:19 -04:00
ALCHLOG ( " ....Unusable: shared but iram prop doesn't match " ) ;
2017-08-18 03:15:47 -04:00
return false ;
}
} else {
//We need an unshared IRQ; can't use shared ones; bail out if this is shared.
2017-08-23 23:46:19 -04:00
ALCHLOG ( " ...Unusable: int is shared, we need non-shared. " ) ;
2017-08-18 03:15:47 -04:00
return false ;
}
2020-09-29 19:44:12 -04:00
} else if ( interrupt_controller_hal_has_handler ( x , cpu ) ) {
//Check if interrupt already is allocated by interrupt_controller_hal_set_int_handler
2017-08-23 23:46:19 -04:00
ALCHLOG ( " ....Unusable: already allocated " ) ;
2017-08-18 03:15:47 -04:00
return false ;
}
2019-04-08 06:02:05 -04:00
2017-08-18 03:15:47 -04:00
return true ;
}
2016-11-25 04:33:51 -05:00
//Locate a free interrupt compatible with the flags given.
//The 'force' argument can be -1, or 0-31 to force checking a certain interrupt.
2016-12-07 08:30:21 -05:00
//When a CPU is forced, the INTDESC_SPECIAL marked interrupts are also accepted.
2017-08-18 03:15:47 -04:00
static int get_available_int ( int flags , int cpu , int force , int source )
2016-11-25 04:33:51 -05:00
{
int x ;
int best = - 1 ;
int bestLevel = 9 ;
int bestSharedCt = INT_MAX ;
2020-09-29 19:44:12 -04:00
2016-11-25 04:33:51 -05:00
//Default vector desc, for vectors not in the linked list
vector_desc_t empty_vect_desc ;
memset ( & empty_vect_desc , 0 , sizeof ( vector_desc_t ) ) ;
2017-08-18 03:15:47 -04:00
2016-11-25 04:33:51 -05:00
//Level defaults to any low/med interrupt
if ( ! ( flags & ESP_INTR_FLAG_LEVELMASK ) ) flags | = ESP_INTR_FLAG_LOWMED ;
2017-08-23 23:46:19 -04:00
ALCHLOG ( " get_available_int: try to find existing. Cpu: %d, Source: %d " , cpu , source ) ;
2017-08-18 03:15:47 -04:00
vector_desc_t * vd = find_desc_for_source ( source , cpu ) ;
if ( vd ) {
// if existing vd found, don't need to search any more.
2017-08-23 23:46:19 -04:00
ALCHLOG ( " get_avalible_int: existing vd found. intno: %d " , vd - > intno ) ;
2017-08-18 03:15:47 -04:00
if ( force ! = - 1 & & force ! = vd - > intno ) {
2017-08-23 23:46:19 -04:00
ALCHLOG ( " get_avalible_int: intr forced but not matach existing. existing intno: %d, force: %d " , vd - > intno , force ) ;
2017-08-18 03:15:47 -04:00
} else if ( ! is_vect_desc_usable ( vd , flags , cpu , force ) ) {
2017-08-23 23:46:19 -04:00
ALCHLOG ( " get_avalible_int: existing vd invalid. " ) ;
2017-08-18 03:15:47 -04:00
} else {
best = vd - > intno ;
}
return best ;
}
if ( force ! = - 1 ) {
2017-08-23 23:46:19 -04:00
ALCHLOG ( " get_available_int: try to find force. Cpu: %d, Source: %d, Force: %d " , cpu , source , force ) ;
2017-08-18 03:15:47 -04:00
//if force assigned, don't need to search any more.
vd = find_desc_for_int ( force , cpu ) ;
if ( vd = = NULL ) {
//if existing vd not found, just check the default state for the intr.
empty_vect_desc . intno = force ;
2019-04-08 06:02:05 -04:00
vd = & empty_vect_desc ;
2017-08-18 03:15:47 -04:00
}
if ( is_vect_desc_usable ( vd , flags , cpu , force ) ) {
best = vd - > intno ;
} else {
2017-08-23 23:46:19 -04:00
ALCHLOG ( " get_avalible_int: forced vd invalid. " ) ;
2019-04-08 06:02:05 -04:00
}
2017-08-18 03:15:47 -04:00
return best ;
}
2017-08-23 23:46:19 -04:00
ALCHLOG ( " get_free_int: start looking. Current cpu: %d " , cpu ) ;
2017-08-18 03:15:47 -04:00
//No allocated handlers as well as forced intr, iterate over the 32 possible interrupts
2016-12-06 01:20:12 -05:00
for ( x = 0 ; x < 32 ; x + + ) {
2016-11-25 04:33:51 -05:00
//Grab the vector_desc for this vector.
2017-08-18 03:15:47 -04:00
vd = find_desc_for_int ( x , cpu ) ;
if ( vd = = NULL ) {
empty_vect_desc . intno = x ;
vd = & empty_vect_desc ;
2016-11-25 04:33:51 -05:00
}
2017-08-18 03:15:47 -04:00
2017-08-23 23:46:19 -04:00
ALCHLOG ( " Int %d reserved %d level %d %s hasIsr %d " ,
2020-09-29 19:44:12 -04:00
x , interrupt_controller_hal_get_cpu_desc_flags ( x , cpu ) = = INTDESC_RESVD , interrupt_controller_hal_get_level ( x ) ,
interrupt_controller_hal_get_type ( x ) = = INTTP_LEVEL ? " LEVEL " : " EDGE " , interrupt_controller_hal_has_handler ( x , cpu ) ) ;
2019-04-08 06:02:05 -04:00
2017-08-18 03:15:47 -04:00
if ( ! is_vect_desc_usable ( vd , flags , cpu , force ) ) continue ;
2016-11-25 04:33:51 -05:00
if ( flags & ESP_INTR_FLAG_SHARED ) {
//We're allocating a shared int.
2019-04-08 06:02:05 -04:00
2016-11-25 04:33:51 -05:00
//See if int already is used as a shared interrupt.
if ( vd - > flags & VECDESC_FL_SHARED ) {
//We can use this already-marked-as-shared interrupt. Count the already attached isrs in order to see
//how useful it is.
int no = 0 ;
shared_vector_desc_t * svdesc = vd - > shared_vec_info ;
while ( svdesc ! = NULL ) {
no + + ;
svdesc = svdesc - > next ;
}
2020-09-29 19:44:12 -04:00
if ( no < bestSharedCt | | bestLevel > interrupt_controller_hal_get_level ( x ) ) {
2016-11-25 04:33:51 -05:00
//Seems like this shared vector is both okay and has the least amount of ISRs already attached to it.
best = x ;
bestSharedCt = no ;
2020-09-29 19:44:12 -04:00
bestLevel = interrupt_controller_hal_get_level ( x ) ;
2017-08-23 23:46:19 -04:00
ALCHLOG ( " ...int %d more usable as a shared int: has %d existing vectors " , x , no ) ;
2016-11-25 04:33:51 -05:00
} else {
2017-08-23 23:46:19 -04:00
ALCHLOG ( " ...worse than int %d " , best ) ;
2016-11-25 04:33:51 -05:00
}
} else {
if ( best = = - 1 ) {
2017-03-21 23:07:37 -04:00
//We haven't found a feasible shared interrupt yet. This one is still free and usable, even if
2016-11-25 04:33:51 -05:00
//not marked as shared.
//Remember it in case we don't find any other shared interrupt that qualifies.
2020-09-29 19:44:12 -04:00
if ( bestLevel > interrupt_controller_hal_get_level ( x ) ) {
2016-11-25 04:33:51 -05:00
best = x ;
2020-09-29 19:44:12 -04:00
bestLevel = interrupt_controller_hal_get_level ( x ) ;
2017-08-23 23:46:19 -04:00
ALCHLOG ( " ...int %d usable as a new shared int " , x ) ;
2016-11-25 04:33:51 -05:00
}
} else {
2017-08-23 23:46:19 -04:00
ALCHLOG ( " ...already have a shared int " ) ;
2016-11-25 04:33:51 -05:00
}
}
} else {
//Seems this interrupt is feasible. Select it and break out of the loop; no need to search further.
2020-09-29 19:44:12 -04:00
if ( bestLevel > interrupt_controller_hal_get_level ( x ) ) {
2016-11-25 04:33:51 -05:00
best = x ;
2020-09-29 19:44:12 -04:00
bestLevel = interrupt_controller_hal_get_level ( x ) ;
2016-11-25 04:33:51 -05:00
} else {
2017-08-23 23:46:19 -04:00
ALCHLOG ( " ...worse than int %d " , best ) ;
2016-11-25 04:33:51 -05:00
}
}
}
2017-08-23 23:46:19 -04:00
ALCHLOG ( " get_available_int: using int %d " , best ) ;
2016-11-25 04:33:51 -05:00
//Okay, by now we have looked at all potential interrupts and hopefully have selected the best one in best.
return best ;
}
//Common shared isr handler. Chain-call all ISRs.
2017-03-21 23:07:37 -04:00
static void IRAM_ATTR shared_intr_isr ( void * arg )
2016-11-25 04:33:51 -05:00
{
vector_desc_t * vd = ( vector_desc_t * ) arg ;
shared_vector_desc_t * sh_vec = vd - > shared_vec_info ;
2019-03-25 06:39:55 -04:00
portENTER_CRITICAL_ISR ( & spinlock ) ;
2016-11-25 04:33:51 -05:00
while ( sh_vec ) {
2016-12-07 08:30:21 -05:00
if ( ! sh_vec - > disabled ) {
if ( ( sh_vec - > statusreg = = NULL ) | | ( * sh_vec - > statusreg & sh_vec - > statusmask ) ) {
2017-03-21 23:07:37 -04:00
# if CONFIG_SYSVIEW_ENABLE
traceISR_ENTER ( sh_vec - > source + ETS_INTERNAL_INTR_SOURCE_OFF ) ;
# endif
2016-12-07 08:30:21 -05:00
sh_vec - > isr ( sh_vec - > arg ) ;
2017-03-21 23:07:37 -04:00
# if CONFIG_SYSVIEW_ENABLE
// check if we will return to scheduler or to interrupted task after ISR
2020-09-29 19:44:12 -04:00
if ( ! port_switch_flag [ cpu_hal_get_core_id ( ) ] ) {
2017-03-21 23:07:37 -04:00
traceISR_EXIT ( ) ;
}
# endif
2016-12-07 08:30:21 -05:00
}
2016-11-25 04:33:51 -05:00
}
2016-12-07 08:30:21 -05:00
sh_vec = sh_vec - > next ;
2016-11-25 04:33:51 -05:00
}
2019-03-25 06:39:55 -04:00
portEXIT_CRITICAL_ISR ( & spinlock ) ;
2016-11-25 04:33:51 -05:00
}
2017-03-21 23:07:37 -04:00
# if CONFIG_SYSVIEW_ENABLE
//Common non-shared isr handler wrapper.
static void IRAM_ATTR non_shared_intr_isr ( void * arg )
{
non_shared_isr_arg_t * ns_isr_arg = ( non_shared_isr_arg_t * ) arg ;
2019-03-25 06:39:55 -04:00
portENTER_CRITICAL_ISR ( & spinlock ) ;
2017-03-21 23:07:37 -04:00
traceISR_ENTER ( ns_isr_arg - > source + ETS_INTERNAL_INTR_SOURCE_OFF ) ;
// FIXME: can we call ISR and check port_switch_flag after releasing spinlock?
// when CONFIG_SYSVIEW_ENABLE = 0 ISRs for non-shared IRQs are called without spinlock
ns_isr_arg - > isr ( ns_isr_arg - > isr_arg ) ;
// check if we will return to scheduler or to interrupted task after ISR
2020-09-29 19:44:12 -04:00
if ( ! port_switch_flag [ cpu_hal_get_core_id ( ) ] ) {
2017-03-21 23:07:37 -04:00
traceISR_EXIT ( ) ;
}
2019-03-25 06:39:55 -04:00
portEXIT_CRITICAL_ISR ( & spinlock ) ;
2017-03-21 23:07:37 -04:00
}
# endif
2016-11-25 04:33:51 -05:00
//We use ESP_EARLY_LOG* here because this can be called before the scheduler is running.
2017-03-21 23:07:37 -04:00
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 )
2016-11-25 04:33:51 -05:00
{
2016-12-07 08:30:21 -05:00
intr_handle_data_t * ret = NULL ;
2016-11-25 04:33:51 -05:00
int force = - 1 ;
2021-02-23 23:07:11 -05:00
ESP_EARLY_LOGV ( TAG , " esp_intr_alloc_intrstatus (cpu %u): checking args " , cpu_hal_get_core_id ( ) ) ;
2016-11-25 04:33:51 -05:00
//Shared interrupts should be level-triggered.
if ( ( flags & ESP_INTR_FLAG_SHARED ) & & ( flags & ESP_INTR_FLAG_EDGE ) ) return ESP_ERR_INVALID_ARG ;
//You can't set an handler / arg for a non-C-callable interrupt.
if ( ( flags & ESP_INTR_FLAG_HIGH ) & & ( handler ) ) return ESP_ERR_INVALID_ARG ;
2016-12-07 08:30:21 -05:00
//Shared ints should have handler and non-processor-local source
if ( ( flags & ESP_INTR_FLAG_SHARED ) & & ( ! handler | | source < 0 ) ) return ESP_ERR_INVALID_ARG ;
2016-11-25 04:33:51 -05:00
//Statusreg should have a mask
if ( intrstatusreg & & ! intrstatusmask ) return ESP_ERR_INVALID_ARG ;
2017-01-10 12:14:18 -05:00
//If the ISR is marked to be IRAM-resident, the handler must not be in the cached region
2019-04-08 06:02:05 -04:00
//ToDo: if we are to allow placing interrupt handlers into the 0x400c0000—0x400c2000 region,
//we need to make sure the interrupt is connected to the CPU0.
//CPU1 does not have access to the RTC fast memory through this region.
2021-02-01 08:14:59 -05:00
if ( ( flags & ESP_INTR_FLAG_IRAM ) & & handler & & ! esp_ptr_in_iram ( handler ) & & ! esp_ptr_in_rtc_iram_fast ( handler ) ) {
2017-01-10 12:14:18 -05:00
return ESP_ERR_INVALID_ARG ;
}
2016-11-25 04:33:51 -05:00
//Default to prio 1 for shared interrupts. Default to prio 1, 2 or 3 for non-shared interrupts.
if ( ( flags & ESP_INTR_FLAG_LEVELMASK ) = = 0 ) {
if ( flags & ESP_INTR_FLAG_SHARED ) {
flags | = ESP_INTR_FLAG_LEVEL1 ;
} else {
flags | = ESP_INTR_FLAG_LOWMED ;
}
}
2021-02-23 23:07:11 -05:00
ESP_EARLY_LOGV ( TAG , " esp_intr_alloc_intrstatus (cpu %u): Args okay. Resulting flags 0x%X " , cpu_hal_get_core_id ( ) , flags ) ;
2017-03-21 23:07:37 -04:00
2016-11-25 04:33:51 -05:00
//Check 'special' interrupt sources. These are tied to one specific interrupt, so we
//have to force get_free_int to only look at that.
if ( source = = ETS_INTERNAL_TIMER0_INTR_SOURCE ) force = ETS_INTERNAL_TIMER0_INTR_NO ;
if ( source = = ETS_INTERNAL_TIMER1_INTR_SOURCE ) force = ETS_INTERNAL_TIMER1_INTR_NO ;
if ( source = = ETS_INTERNAL_TIMER2_INTR_SOURCE ) force = ETS_INTERNAL_TIMER2_INTR_NO ;
if ( source = = ETS_INTERNAL_SW0_INTR_SOURCE ) force = ETS_INTERNAL_SW0_INTR_NO ;
if ( source = = ETS_INTERNAL_SW1_INTR_SOURCE ) force = ETS_INTERNAL_SW1_INTR_NO ;
if ( source = = ETS_INTERNAL_PROFILING_INTR_SOURCE ) force = ETS_INTERNAL_PROFILING_INTR_NO ;
2016-12-07 08:30:21 -05:00
//Allocate a return handle. If we end up not needing it, we'll free it later on.
2017-09-22 04:02:39 -04:00
ret = heap_caps_malloc ( sizeof ( intr_handle_data_t ) , MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT ) ;
2016-12-07 08:30:21 -05:00
if ( ret = = NULL ) return ESP_ERR_NO_MEM ;
2016-12-06 01:20:12 -05:00
2016-11-25 04:33:51 -05:00
portENTER_CRITICAL ( & spinlock ) ;
2021-02-23 23:07:11 -05:00
uint32_t cpu = cpu_hal_get_core_id ( ) ;
2016-11-25 04:33:51 -05:00
//See if we can find an interrupt that matches the flags.
2017-08-18 03:15:47 -04:00
int intr = get_available_int ( flags , cpu , force , source ) ;
2016-11-25 04:33:51 -05:00
if ( intr = = - 1 ) {
//None found. Bail out.
portEXIT_CRITICAL ( & spinlock ) ;
2016-12-06 01:20:12 -05:00
free ( ret ) ;
2016-11-25 04:33:51 -05:00
return ESP_ERR_NOT_FOUND ;
}
//Get an int vector desc for int.
vector_desc_t * vd = get_desc_for_int ( intr , cpu ) ;
2016-12-06 01:20:12 -05:00
if ( vd = = NULL ) {
portEXIT_CRITICAL ( & spinlock ) ;
free ( ret ) ;
return ESP_ERR_NO_MEM ;
}
2016-11-25 04:33:51 -05:00
//Allocate that int!
if ( flags & ESP_INTR_FLAG_SHARED ) {
//Populate vector entry and add to linked list.
shared_vector_desc_t * sh_vec = malloc ( sizeof ( shared_vector_desc_t ) ) ;
2016-12-06 01:20:12 -05:00
if ( sh_vec = = NULL ) {
portEXIT_CRITICAL ( & spinlock ) ;
free ( ret ) ;
return ESP_ERR_NO_MEM ;
}
2016-11-25 04:33:51 -05:00
memset ( sh_vec , 0 , sizeof ( shared_vector_desc_t ) ) ;
sh_vec - > statusreg = ( uint32_t * ) intrstatusreg ;
sh_vec - > statusmask = intrstatusmask ;
sh_vec - > isr = handler ;
sh_vec - > arg = arg ;
sh_vec - > next = vd - > shared_vec_info ;
2016-12-07 08:30:21 -05:00
sh_vec - > source = source ;
sh_vec - > disabled = 0 ;
2016-11-25 04:33:51 -05:00
vd - > shared_vec_info = sh_vec ;
vd - > flags | = VECDESC_FL_SHARED ;
//(Re-)set shared isr handler to new value.
2020-11-05 23:00:07 -05:00
interrupt_controller_hal_set_int_handler ( intr , shared_intr_isr , vd ) ;
2016-11-25 04:33:51 -05:00
} else {
//Mark as unusable for other interrupt sources. This is ours now!
vd - > flags = VECDESC_FL_NONSHARED ;
if ( handler ) {
2017-03-21 23:07:37 -04:00
# if CONFIG_SYSVIEW_ENABLE
non_shared_isr_arg_t * ns_isr_arg = malloc ( sizeof ( non_shared_isr_arg_t ) ) ;
if ( ! ns_isr_arg ) {
portEXIT_CRITICAL ( & spinlock ) ;
free ( ret ) ;
return ESP_ERR_NO_MEM ;
}
ns_isr_arg - > isr = handler ;
ns_isr_arg - > isr_arg = arg ;
ns_isr_arg - > source = source ;
2020-09-29 19:44:12 -04:00
interrupt_controller_hal_set_int_handler ( intr , non_shared_intr_isr , ns_isr_arg ) ;
2017-03-21 23:07:37 -04:00
# else
2020-09-29 19:44:12 -04:00
interrupt_controller_hal_set_int_handler ( intr , handler , arg ) ;
2017-03-21 23:07:37 -04:00
# endif
2016-11-25 04:33:51 -05:00
}
2020-11-11 11:21:49 -05:00
2020-12-29 00:20:24 -05:00
if ( flags & ESP_INTR_FLAG_EDGE ) {
2020-11-11 11:21:49 -05:00
interrupt_controller_hal_edge_int_acknowledge ( intr ) ;
2020-12-28 23:31:54 -05:00
}
2020-11-11 11:21:49 -05:00
2016-12-07 08:30:21 -05:00
vd - > source = source ;
2016-11-25 04:33:51 -05:00
}
if ( flags & ESP_INTR_FLAG_IRAM ) {
vd - > flags | = VECDESC_FL_INIRAM ;
non_iram_int_mask [ cpu ] & = ~ ( 1 < < intr ) ;
} else {
vd - > flags & = ~ VECDESC_FL_INIRAM ;
non_iram_int_mask [ cpu ] | = ( 1 < < intr ) ;
}
if ( source > = 0 ) {
intr_matrix_set ( cpu , source , intr ) ;
}
2016-12-07 08:30:21 -05:00
//Fill return handle data.
ret - > vector_desc = vd ;
ret - > shared_vector_desc = vd - > shared_vec_info ;
//Enable int at CPU-level;
ESP_INTR_ENABLE ( intr ) ;
//If interrupt has to be started disabled, do that now; ints won't be enabled for real until the end
//of the critical section.
if ( flags & ESP_INTR_FLAG_INTRDISABLED ) {
esp_intr_disable ( ret ) ;
}
2020-12-16 12:20:38 -05:00
# ifdef SOC_CPU_HAS_FLEXIBLE_INTC
2020-11-19 13:14:54 -05:00
//Extract the level from the interrupt passed flags
2020-12-28 23:31:54 -05:00
int level = esp_intr_flags_to_level ( flags ) ;
interrupt_controller_hal_set_int_level ( intr , level ) ;
2020-11-11 11:21:49 -05:00
2020-11-19 13:14:54 -05:00
if ( flags & ESP_INTR_FLAG_EDGE ) {
2020-12-28 23:31:54 -05:00
interrupt_controller_hal_set_int_type ( intr , INTTP_EDGE ) ;
2020-11-19 13:14:54 -05:00
} else {
2020-12-28 23:31:54 -05:00
interrupt_controller_hal_set_int_type ( intr , INTTP_LEVEL ) ;
2020-11-19 13:14:54 -05:00
}
2020-12-16 12:20:38 -05:00
# endif
2020-12-30 02:33:03 -05:00
2016-12-07 08:30:21 -05:00
portEXIT_CRITICAL ( & spinlock ) ;
//Fill return handle if needed, otherwise free handle.
2016-11-25 04:33:51 -05:00
if ( ret_handle ! = NULL ) {
* ret_handle = ret ;
2016-12-07 08:30:21 -05:00
} else {
free ( ret ) ;
2016-11-25 04:33:51 -05:00
}
ESP_EARLY_LOGD ( TAG , " Connected src %d to int %d (cpu %d) " , source , intr , cpu ) ;
return ESP_OK ;
}
2017-03-21 23:07:37 -04:00
esp_err_t esp_intr_alloc ( int source , int flags , intr_handler_t handler , void * arg , intr_handle_t * ret_handle )
2016-11-25 04:33:51 -05:00
{
/*
As an optimization , we can create a table with the possible interrupt status registers and masks for every single
2017-03-21 23:07:37 -04:00
source there is . We can then add code here to look up an applicable value and pass that to the
2016-11-25 04:33:51 -05:00
esp_intr_alloc_intrstatus function .
*/
return esp_intr_alloc_intrstatus ( source , flags , 0 , 0 , handler , arg , ret_handle ) ;
}
2017-11-09 06:21:39 -05:00
esp_err_t IRAM_ATTR esp_intr_set_in_iram ( intr_handle_t handle , bool is_in_iram )
{
if ( ! handle ) return ESP_ERR_INVALID_ARG ;
vector_desc_t * vd = handle - > vector_desc ;
if ( vd - > flags & VECDESC_FL_SHARED ) {
return ESP_ERR_INVALID_ARG ;
}
portENTER_CRITICAL ( & spinlock ) ;
uint32_t mask = ( 1 < < vd - > intno ) ;
if ( is_in_iram ) {
vd - > flags | = VECDESC_FL_INIRAM ;
non_iram_int_mask [ vd - > cpu ] & = ~ mask ;
} else {
vd - > flags & = ~ VECDESC_FL_INIRAM ;
non_iram_int_mask [ vd - > cpu ] | = mask ;
}
portEXIT_CRITICAL ( & spinlock ) ;
return ESP_OK ;
}
2016-11-25 04:33:51 -05:00
2019-08-15 03:05:59 -04:00
# if !CONFIG_FREERTOS_UNICORE
2018-10-13 02:38:48 -04:00
static void esp_intr_free_cb ( void * arg )
{
( void ) esp_intr_free ( ( intr_handle_t ) arg ) ;
}
2019-08-15 03:05:59 -04:00
# endif /* !CONFIG_FREERTOS_UNICORE */
2018-10-13 02:38:48 -04:00
2017-03-21 23:07:37 -04:00
esp_err_t esp_intr_free ( intr_handle_t handle )
2016-11-25 04:33:51 -05:00
{
bool free_shared_vector = false ;
if ( ! handle ) return ESP_ERR_INVALID_ARG ;
2019-08-15 03:05:59 -04:00
# if !CONFIG_FREERTOS_UNICORE
2018-09-20 00:13:43 -04:00
//Assign this routine to the core where this interrupt is allocated on.
2020-09-29 19:44:12 -04:00
if ( handle - > vector_desc - > cpu ! = cpu_hal_get_core_id ( ) ) {
2018-10-13 02:38:48 -04:00
esp_err_t ret = esp_ipc_call_blocking ( handle - > vector_desc - > cpu , & esp_intr_free_cb , ( void * ) handle ) ;
2018-09-20 00:13:43 -04:00
return ret = = ESP_OK ? ESP_OK : ESP_FAIL ;
}
2019-08-15 03:05:59 -04:00
# endif /* !CONFIG_FREERTOS_UNICORE */
2016-11-25 04:33:51 -05:00
portENTER_CRITICAL ( & spinlock ) ;
2016-12-07 23:04:26 -05:00
esp_intr_disable ( handle ) ;
2016-11-25 04:33:51 -05:00
if ( handle - > vector_desc - > flags & VECDESC_FL_SHARED ) {
2017-03-21 23:07:37 -04:00
//Find and kill the shared int
2016-11-25 04:33:51 -05:00
shared_vector_desc_t * svd = handle - > vector_desc - > shared_vec_info ;
shared_vector_desc_t * prevsvd = NULL ;
assert ( svd ) ; //should be something in there for a shared int
while ( svd ! = NULL ) {
if ( svd = = handle - > shared_vector_desc ) {
//Found it. Now kill it.
if ( prevsvd ) {
prevsvd - > next = svd - > next ;
} else {
handle - > vector_desc - > shared_vec_info = svd - > next ;
}
free ( svd ) ;
break ;
}
prevsvd = svd ;
svd = svd - > next ;
}
//If nothing left, disable interrupt.
if ( handle - > vector_desc - > shared_vec_info = = NULL ) free_shared_vector = true ;
2019-12-18 04:11:24 -05:00
ESP_EARLY_LOGV ( TAG , " esp_intr_free: Deleting shared int: %s. Shared int is %s " , svd ? " not found or last one " : " deleted " , free_shared_vector ? " empty now. " : " still in use " ) ;
2016-11-25 04:33:51 -05:00
}
if ( ( handle - > vector_desc - > flags & VECDESC_FL_NONSHARED ) | | free_shared_vector ) {
2019-12-18 04:11:24 -05:00
ESP_EARLY_LOGV ( TAG , " esp_intr_free: Disabling int, killing handler " ) ;
2017-03-21 23:07:37 -04:00
# if CONFIG_SYSVIEW_ENABLE
if ( ! free_shared_vector ) {
2020-09-29 19:44:12 -04:00
void * isr_arg = interrupt_controller_hal_get_int_handler_arg ( handle - > vector_desc - > intno ) ;
2017-03-21 23:07:37 -04:00
if ( isr_arg ) {
free ( isr_arg ) ;
}
}
# endif
2020-09-29 19:44:12 -04:00
//Reset to normal handler:
interrupt_controller_hal_set_int_handler ( handle - > vector_desc - > intno , NULL , ( void * ) ( ( int ) handle - > vector_desc - > intno ) ) ;
2016-11-25 04:33:51 -05:00
//Theoretically, we could free the vector_desc... not sure if that's worth the few bytes of memory
2017-03-21 23:07:37 -04:00
//we save.(We can also not use the same exit path for empty shared ints anymore if we delete
//the desc.) For now, just mark it as free.
2016-11-25 04:33:51 -05:00
handle - > vector_desc - > flags & = ! ( VECDESC_FL_NONSHARED | VECDESC_FL_RESERVED ) ;
//Also kill non_iram mask bit.
2016-12-07 08:30:21 -05:00
non_iram_int_mask [ handle - > vector_desc - > cpu ] & = ~ ( 1 < < ( handle - > vector_desc - > intno ) ) ;
2016-11-25 04:33:51 -05:00
}
portEXIT_CRITICAL ( & spinlock ) ;
free ( handle ) ;
return ESP_OK ;
}
2016-12-07 08:30:21 -05:00
int esp_intr_get_intno ( intr_handle_t handle )
2016-11-25 04:33:51 -05:00
{
2016-12-07 08:30:21 -05:00
return handle - > vector_desc - > intno ;
2016-11-25 04:33:51 -05:00
}
2016-12-07 08:30:21 -05:00
int esp_intr_get_cpu ( intr_handle_t handle )
2016-11-25 04:33:51 -05:00
{
2016-12-07 08:30:21 -05:00
return handle - > vector_desc - > cpu ;
2016-11-25 04:33:51 -05:00
}
2016-12-07 08:30:21 -05:00
/*
Interrupt disabling strategy :
If the source is > = 0 ( meaning a muxed interrupt ) , we disable it by muxing the interrupt to a non - connected
interrupt . If the source is < 0 ( meaning an internal , per - cpu interrupt ) , we disable it using ESP_INTR_DISABLE .
This allows us to , for the muxed CPUs , disable an int from the other core . It also allows disabling shared
interrupts .
*/
//Muxing an interrupt source to interrupt 6, 7, 11, 15, 16 or 29 cause the interrupt to effectively be disabled.
# define INT_MUX_DISABLED_INTNO 6
2016-12-19 01:28:28 -05:00
esp_err_t IRAM_ATTR esp_intr_enable ( intr_handle_t handle )
2016-11-25 04:33:51 -05:00
{
if ( ! handle ) return ESP_ERR_INVALID_ARG ;
2019-03-25 06:39:55 -04:00
portENTER_CRITICAL_SAFE ( & spinlock ) ;
2016-12-07 08:30:21 -05:00
int source ;
if ( handle - > shared_vector_desc ) {
handle - > shared_vector_desc - > disabled = 0 ;
source = handle - > shared_vector_desc - > source ;
} else {
source = handle - > vector_desc - > source ;
}
if ( source > = 0 ) {
//Disabled using int matrix; re-connect to enable
intr_matrix_set ( handle - > vector_desc - > cpu , source , handle - > vector_desc - > intno ) ;
} else {
//Re-enable using cpu int ena reg
2020-09-29 19:44:12 -04:00
if ( handle - > vector_desc - > cpu ! = cpu_hal_get_core_id ( ) ) return ESP_ERR_INVALID_ARG ; //Can only enable these ints on this cpu
2016-12-07 08:30:21 -05:00
ESP_INTR_ENABLE ( handle - > vector_desc - > intno ) ;
}
2019-03-25 06:39:55 -04:00
portEXIT_CRITICAL_SAFE ( & spinlock ) ;
2016-11-25 04:33:51 -05:00
return ESP_OK ;
}
2016-12-19 01:28:28 -05:00
esp_err_t IRAM_ATTR esp_intr_disable ( intr_handle_t handle )
2016-11-25 04:33:51 -05:00
{
if ( ! handle ) return ESP_ERR_INVALID_ARG ;
2019-03-25 06:39:55 -04:00
portENTER_CRITICAL_SAFE ( & spinlock ) ;
2016-12-07 08:30:21 -05:00
int source ;
2017-08-18 03:15:47 -04:00
bool disabled = 1 ;
2016-12-07 08:30:21 -05:00
if ( handle - > shared_vector_desc ) {
handle - > shared_vector_desc - > disabled = 1 ;
source = handle - > shared_vector_desc - > source ;
2017-08-18 03:15:47 -04:00
shared_vector_desc_t * svd = handle - > vector_desc - > shared_vec_info ;
assert ( svd ! = NULL ) ;
while ( svd ) {
if ( svd - > source = = source & & svd - > disabled = = 0 ) {
disabled = 0 ;
break ;
}
svd = svd - > next ;
}
2016-12-07 08:30:21 -05:00
} else {
source = handle - > vector_desc - > source ;
}
2017-08-18 03:15:47 -04:00
2016-12-07 08:30:21 -05:00
if ( source > = 0 ) {
2017-08-18 03:15:47 -04:00
if ( disabled ) {
//Disable using int matrix
intr_matrix_set ( handle - > vector_desc - > cpu , source , INT_MUX_DISABLED_INTNO ) ;
}
2016-12-07 08:30:21 -05:00
} else {
//Disable using per-cpu regs
2020-09-29 19:44:12 -04:00
if ( handle - > vector_desc - > cpu ! = cpu_hal_get_core_id ( ) ) {
2019-10-20 01:23:47 -04:00
portEXIT_CRITICAL_SAFE ( & spinlock ) ;
2016-12-07 08:30:21 -05:00
return ESP_ERR_INVALID_ARG ; //Can only enable these ints on this cpu
}
ESP_INTR_DISABLE ( handle - > vector_desc - > intno ) ;
}
2019-03-25 06:39:55 -04:00
portEXIT_CRITICAL_SAFE ( & spinlock ) ;
2016-11-25 04:33:51 -05:00
return ESP_OK ;
}
2019-07-16 05:33:30 -04:00
void IRAM_ATTR esp_intr_noniram_disable ( void )
2016-11-25 04:33:51 -05:00
{
2021-02-23 23:07:11 -05:00
portENTER_CRITICAL_SAFE ( & spinlock ) ;
2020-09-29 19:44:12 -04:00
uint32_t oldint ;
2021-02-23 23:07:11 -05:00
uint32_t cpu = cpu_hal_get_core_id ( ) ;
uint32_t non_iram_ints = non_iram_int_mask [ cpu ] ;
if ( non_iram_int_disabled_flag [ cpu ] ) {
abort ( ) ;
}
non_iram_int_disabled_flag [ cpu ] = true ;
oldint = interrupt_controller_hal_read_interrupt_mask ( ) ;
interrupt_controller_hal_disable_interrupts ( non_iram_ints ) ;
// Save disabled ints
non_iram_int_disabled [ cpu ] = oldint & non_iram_ints ;
portEXIT_CRITICAL_SAFE ( & spinlock ) ;
2016-11-25 04:33:51 -05:00
}
2019-07-16 05:33:30 -04:00
void IRAM_ATTR esp_intr_noniram_enable ( void )
2016-11-25 04:33:51 -05:00
{
2021-02-23 23:07:11 -05:00
portENTER_CRITICAL_SAFE ( & spinlock ) ;
uint32_t cpu = cpu_hal_get_core_id ( ) ;
int non_iram_ints = non_iram_int_disabled [ cpu ] ;
if ( ! non_iram_int_disabled_flag [ cpu ] ) {
abort ( ) ;
}
non_iram_int_disabled_flag [ cpu ] = false ;
interrupt_controller_hal_enable_interrupts ( non_iram_ints ) ;
portEXIT_CRITICAL_SAFE ( & spinlock ) ;
2016-11-25 04:33:51 -05:00
}
2016-12-12 07:05:58 -05:00
//These functions are provided in ROM, but the ROM-based functions use non-multicore-capable
//virtualized interrupt levels. Thus, we disable them in the ld file and provide working
//equivalents here.
2016-11-25 04:33:51 -05:00
2020-11-05 23:00:07 -05:00
void IRAM_ATTR ets_isr_unmask ( uint32_t mask ) {
2020-09-29 19:44:12 -04:00
interrupt_controller_hal_enable_interrupts ( mask ) ;
2016-12-12 07:05:58 -05:00
}
2020-11-05 23:00:07 -05:00
void IRAM_ATTR ets_isr_mask ( uint32_t mask ) {
2020-09-29 19:44:12 -04:00
interrupt_controller_hal_disable_interrupts ( mask ) ;
2016-12-12 07:05:58 -05:00
}
2020-11-10 02:40:01 -05:00
void esp_intr_enable_source ( int inum )
2020-09-29 19:44:12 -04:00
{
interrupt_controller_hal_enable_interrupts ( 1 < < inum ) ;
}
2016-11-25 04:33:51 -05:00
2020-09-29 19:44:12 -04:00
void esp_intr_disable_source ( int inum )
{
interrupt_controller_hal_disable_interrupts ( 1 < < inum ) ;
2020-11-10 02:40:01 -05:00
}