diff --git a/arch/xtensa/include/esp32/irq.h b/arch/xtensa/include/esp32/irq.h index 4221f30b20d..46b20fb552d 100644 --- a/arch/xtensa/include/esp32/irq.h +++ b/arch/xtensa/include/esp32/irq.h @@ -297,11 +297,17 @@ * 26 can be mapped to peripheral interrupts: * * Level triggered peripherals (21 total): - * 0-5, 8-9, 12-13, 17-21, 23-27, 31 + * 0-5, 8-9, 12-13, 17-18 - Priority 1 + * 19-21 - Priority 2 + * 23, 27 - Priority 3 + * 24-25 - Priority 4 + * 26, 31 - Priority 5 * Edge triggered peripherals (4 total): - * 10, 22, 28, 30 + * 10 - Priority 1 + * 22 - Priority 3 + * 28, 30 - Priority 4 * NMI (1 total): - * 14 + * 14 - NMI * * CPU peripheral interrupts can be a assigned to a CPU interrupt using the * PRO_*_MAP_REG or APP_*_MAP_REG. There are a pair of these registers for @@ -310,11 +316,12 @@ * * The remaining, five, internal CPU interrupts are: * - * 6 Timer0 - * 7 Software - * 15 Timer1 - * 16 Timer2 - * 29 Software + * 6 Timer0 - Priority 1 + * 7 Software - Priority 1 + * 11 Profiling - Priority 3 + * 15 Timer1 - Priority 3 + * 16 Timer2 - Priority 5 + * 29 Software - Priority 3 * * A peripheral interrupt can be disabled */ @@ -359,6 +366,21 @@ #define EPS32_CPUINT_PERIPHSET 0xdffe7f3f #define EPS32_CPUINT_INTERNALSET 0x200180c0 +/* Priority 1: 0-10, 12-13, 17-18 (15) + * Priority 2: 19-21 (3) + * Priority 3: 11, 15, 22-23, 27, 29 (6) + * Priority 4: 24-25, 28, 30 (4) + * Priority 5: 16, 26, 31 (3) + * Priority NMI: 14 (1) + */ + +#define ESP32_INTPRI1_MASK 0x000637ff +#define ESP32_INTPRI2_MASK 0x00380000 +#define ESP32_INTPRI3_MASK 0x28c08800 +#define ESP32_INTPRI4_MASK 0x53000000 +#define ESP32_INTPRI5_MASK 0x84010000 +#define ESP32_INTNMI_MASK 0x00004000 + /**************************************************************************** * Public Types ****************************************************************************/ diff --git a/arch/xtensa/src/esp32/esp32_cpuint.c b/arch/xtensa/src/esp32/esp32_cpuint.c index 9f09a3b72cf..6a6aec7fe5a 100644 --- a/arch/xtensa/src/esp32/esp32_cpuint.c +++ b/arch/xtensa/src/esp32/esp32_cpuint.c @@ -143,6 +143,12 @@ #define NO_CPUINT ESP32_CPUINT_TIMER0 +/* Priority range is 1-5 */ + +#define ESP32_MIN_PRIORITY 1 +#define ESP32_MAX_PRIORITY 5 +#define ESP32_PRIO_INDEX(p) ((p) - ESP32_MIN_PRIORITY) + /**************************************************************************** * Private Data ****************************************************************************/ @@ -166,6 +172,17 @@ static uint32_t g_intenable[1]; static uint32_t g_level_ints = ESP32_LEVEL_SET; static uint32_t g_edge_ints = ESP32_EDGE_SET; +/* Bitsets for each interrupt priority 1-5 */ + +static uint32_t g_priority[5] = +{ + ESP32_INTPRI1_MASK, + ESP32_INTPRI2_MASK, + ESP32_INTPRI3_MASK, + ESP32_INTPRI4_MASK, + ESP32_INTPRI5_MASK +}; + /**************************************************************************** * Private Functions ****************************************************************************/ @@ -229,7 +246,7 @@ void up_enable_irq(int cpuint) * Allocate a level CPU interrupt * * Input Parameters: - * None + * priority - Priority of the CPU interrupt (1-5) * * Returned Value: * On success, the allocated level-sensitive, CPU interrupt numbr is @@ -239,28 +256,39 @@ void up_enable_irq(int cpuint) * ****************************************************************************/ -int esp32_alloc_levelint(void) +int esp32_alloc_levelint(int priority) { irqstate_t flags; uint32_t mask; + uint32_t intset; int cpuint; int ret = -ENOMEM; + DEBUGASSERT(priority >= ESP32_MIN_PRIORITY && priority <= ESP32_MAX_PRIORITY) + /* Check if there are any level CPU interrupts available */ flags = enter_critical_section(); - if ((g_level_ints & ESP32_LEVEL_SET) != 0) - { - /* Search for an unallocated CPU interrupt number in g_level_ints. */ - for (cpuint = 0; cpuint < ESP32_CPUINT_NLEVELPERIPHS; cpuint++) + intset = g_level_ints & g_priority[ESP32_PRIO_INDEX(priority)] & ESP32_LEVEL_SET; + if (intset != 0) + { + /* Skip over initial zeroes as quickly in groups of 8 bits. */ + + for (cpuint = 0, mask = 0xff; + cpuint <= ESP32_CPUINT_MAX && (intset & mask) == 0; + cpuint += 8, mask <<= 8); + + /* Search for an unallocated CPU interrupt number in the remaining intset. */ + + for (; cpuint <= ESP32_CPUINT_MAX && intset != 0; cpuint++) { /* If the bit corresponding to the CPU interrupt is '1', then * that CPU interrupt is available. */ mask = (1ul << cpuint); - if ((g_level_ints & mask) != 0) + if ((intset & mask) != 0) { /* Got it! */ @@ -268,6 +296,10 @@ int esp32_alloc_levelint(void) ret = cpuint; break; } + + /* Clear the bit in intset so that we may exit the loop sooner */ + + intset &= ~mask; } } @@ -312,7 +344,7 @@ void esp32_free_levelint(int cpuint) * Allocate an edge CPU interrupt * * Input Parameters: - * None + * priority - Priority of the CPU interrupt (1-5) * * Returned Value: * On success, the allocated edge-sensitive, CPU interrupt numbr is @@ -322,28 +354,39 @@ void esp32_free_levelint(int cpuint) * ****************************************************************************/ -int esp32_alloc_edgeint(void) +int esp32_alloc_edgeint(int priority) { irqstate_t flags; uint32_t mask; + uint32_t intset; int cpuint; int ret = -ENOMEM; + DEBUGASSERT(priority >= ESP32_MIN_PRIORITY && priority <= ESP32_MAX_PRIORITY) + /* Check if there are any level CPU interrupts available */ flags = enter_critical_section(); - if ((g_edge_ints & ESP32_EDGE_SET) != 0) - { - /* Search for an unallocated CPU interrupt number in g_edge_ints. */ - for (cpuint = 0; cpuint < ESP32_CPUINT_NEDGEPERIPHS; cpuint++) + intset = g_edge_ints & g_priority[ESP32_PRIO_INDEX(priority)] & ESP32_EDGE_SET; + if (intset != 0) + { + /* Skip over initial zeroes as quickly in groups of 8 bits. */ + + for (cpuint = 0, mask = 0xff; + cpuint <= ESP32_CPUINT_MAX && (intset & mask) == 0; + cpuint += 8, mask <<= 8); + + /* Search for an unallocated CPU interrupt number in the remaining intset. */ + + for (; cpuint <= ESP32_CPUINT_MAX && intset != 0; cpuint++) { /* If the bit corresponding to the CPU interrupt is '1', then * that CPU interrupt is available. */ mask = (1ul << cpuint); - if ((g_edge_ints & mask) != 0) + if ((intset & mask) != 0) { /* Got it! */ @@ -351,6 +394,10 @@ int esp32_alloc_edgeint(void) ret = cpuint; break; } + + /* Clear the bit in intset so that we may exit the loop sooner */ + + intset &= ~mask; } } diff --git a/arch/xtensa/src/esp32/esp32_cpuint.h b/arch/xtensa/src/esp32/esp32_cpuint.h index 07af5ea8f39..746248456de 100644 --- a/arch/xtensa/src/esp32/esp32_cpuint.h +++ b/arch/xtensa/src/esp32/esp32_cpuint.h @@ -53,7 +53,7 @@ * Allocate a level CPU interrupt * * Input Parameters: - * None + * priority - Priority of the CPU interrupt (1-5) * * Returned Value: * On success, the allocated level-sensitive, CPU interrupt numbr is @@ -63,7 +63,7 @@ * ****************************************************************************/ -int esp32_alloc_levelint(void); +int esp32_alloc_levelint(int priority); /**************************************************************************** * Name: esp32_free_levelint @@ -72,7 +72,7 @@ int esp32_alloc_levelint(void); * Free a previoulsy allocated level CPU interrupt * * Input Parameters: - * The CPU interrupt number to be freed + * cpuint - The CPU interrupt number to be freed * * Returned Value: * None @@ -88,7 +88,7 @@ void esp32_free_levelint(int cpuint); * Allocate an edge CPU interrupt * * Input Parameters: - * None + * priority - Priority of the CPU interrupt (1-5) * * Returned Value: * On success, the allocated edge-sensitive, CPU interrupt numbr is @@ -98,7 +98,7 @@ void esp32_free_levelint(int cpuint); * ****************************************************************************/ -int esp32_alloc_edgeint(void); +int esp32_alloc_edgeint(int priority); /**************************************************************************** * Name: esp32_free_edgeint @@ -107,14 +107,14 @@ int esp32_alloc_edgeint(void); * Free a previoulsy allocated edge CPU interrupt * * Input Parameters: - * The CPU interrupt number to be freed + * cpuint - The CPU interrupt number to be freed * * Returned Value: * None * ****************************************************************************/ -void esp32_free_edgeint(int cpuint); +void esp32_free_edgeint(int cpuint, int priority); /**************************************************************************** * Name: esp32_attach_peripheral