From 810be86f21677d0d1b5c7913ade8efc90fbfdaca Mon Sep 17 00:00:00 2001 From: Felipe Neves Date: Wed, 4 Nov 2020 18:34:47 -0300 Subject: [PATCH 01/10] freertos/riscv: move freertos aware interrupt code from vectors to the freertos riscv port. The riscv vectors.S in riscv component contains the trap vector, which is responsible to defer interrupts and examine if a task context switch is needed, this change cleans up this code by hiding all freertos details behind on two functions rtos_it_enter/exit and their implementations are placed in freertos riscv port files. --- components/freertos/port/riscv/port.c | 11 +++-- components/freertos/port/riscv/portasm.S | 38 ++++++++++++---- components/riscv/vectors.S | 58 ++++++------------------ 3 files changed, 50 insertions(+), 57 deletions(-) diff --git a/components/freertos/port/riscv/port.c b/components/freertos/port/riscv/port.c index 6c25ad11ad..6895604c60 100644 --- a/components/freertos/port/riscv/port.c +++ b/components/freertos/port/riscv/port.c @@ -102,6 +102,7 @@ static UBaseType_t uxCriticalNesting = 0; static UBaseType_t uxSavedInterruptState = 0; BaseType_t uxSchedulerRunning = 0; UBaseType_t uxInterruptNesting = 0; +BaseType_t xPortSwitchFlag = 0; __attribute__((aligned(16))) static StackType_t xIsrStack[configISR_STACK_SIZE]; StackType_t *xIsrStackTop = &xIsrStack[0] + (configISR_STACK_SIZE & (~((portPOINTER_SIZE_TYPE)portBYTE_ALIGNMENT_MASK))); @@ -243,7 +244,7 @@ void vPortSysTickHandler(void) } if (xTaskIncrementTick() != pdFALSE) { - vTaskSwitchContext(); + vPortYieldFromISR(); } } @@ -251,6 +252,7 @@ BaseType_t xPortStartScheduler(void) { vPortSetupTimer(); vPortSetupSoftwareInterrupt(); + uxInterruptNesting = 0; uxCriticalNesting = 0; uxSchedulerRunning = 0; /* this means first yield */ esprv_intc_int_set_threshold(1); /* set global INTC masking level */ @@ -270,7 +272,6 @@ void vPortEndScheduler(void) void vPortSoftwareInterrupt(void) { uxSchedulerRunning = 1; - vTaskSwitchContext(); REG_WRITE(SYSTEM_CPU_INTR_FROM_CPU_0_REG, 0); } @@ -285,6 +286,7 @@ void vPortYield(void) if (uxInterruptNesting) { vPortYieldFromISR(); } else { + xPortSwitchFlag = 1; REG_WRITE(SYSTEM_CPU_INTR_FROM_CPU_0_REG, 1); /* There are 3-4 instructions of latency between triggering the software @@ -299,11 +301,12 @@ void vPortYield(void) */ while(uxSchedulerRunning && uxCriticalNesting == 0 && REG_READ(SYSTEM_CPU_INTR_FROM_CPU_0_REG) != 0) { } } + } -void vPortYieldFromISR(void) +void vPortYieldFromISR( void ) { - vTaskSwitchContext(); + xPortSwitchFlag = 1; } void vPortSetStackWatchpoint(void *pxStackStart) diff --git a/components/freertos/port/riscv/portasm.S b/components/freertos/port/riscv/portasm.S index e4e05e3d68..8d19ba3467 100644 --- a/components/freertos/port/riscv/portasm.S +++ b/components/freertos/port/riscv/portasm.S @@ -36,15 +36,24 @@ rtos_int_enter: mv t2, a0 /* scheduler not enabled, jump directly to ISR handler */ - lw t0, uxSchedulerRunning - beq t0,zero, not_rtos_enter + lw t0, uxSchedulerRunning + beq t0,zero, rtos_enter_end - /* Sabe current TCB and load the ISR stack */ + /* increments the ISR nesting count */ + la t3, uxInterruptNesting + lw t4, 0x0(t3) + addi t5,t4,1 + sw t5, 0x0(t3) + + /* If reached here from another low-prio ISR, skip stack pushing to TCB */ + bne t4,zero, rtos_enter_end + + /* Save current TCB and load the ISR stack */ lw t0, pxCurrentTCB sw t2, 0x0(t0) lw sp, xIsrStackTop -not_rtos_enter: +rtos_enter_end: mv ra, t1 ret @@ -56,10 +65,23 @@ not_rtos_enter: .global rtos_int_exit .type rtos_int_exit, @function rtos_int_exit: - /* may skip RTOS aware interrupt since scheduler was not started */ - lw t0, uxSchedulerRunning - beq t0,zero, not_rtos_exit + lw t0, uxSchedulerRunning + beq t0,zero, rtos_exit_end + + /* update nesting interrupts counter */ + la t2, uxInterruptNesting + lw t3, 0x0(t2) + + /* Already zero, protect againts underflow */ + beq t3, zero, isr_skip_decrement + addi t3,t3, -1 + sw t3, 0x0(t2) + +isr_skip_decrement: + + /* may still have interrupts pending, skip section below and exit */ + bne t3,zero,rtos_exit_end /* Schedule the next task if a yield is pending */ la t0, xPortSwitchFlag @@ -83,5 +105,5 @@ no_switch: lw a0, pxCurrentTCB lw a0, 0x0(a0) -not_rtos_exit: +rtos_exit_end: ret diff --git a/components/riscv/vectors.S b/components/riscv/vectors.S index d273f3ab17..b55f4c12fe 100644 --- a/components/riscv/vectors.S +++ b/components/riscv/vectors.S @@ -97,11 +97,9 @@ csrw mepc, t0 .endm - .global vPortYieldFromISR - .global uxInterruptNesting - .global uxSchedulerRunning - .global xIsrStackTop - .global pxCurrentTCB + .global rtos_int_enter + .global rtos_int_exit + .global uxInterruptNesting .global _global_interrupt_handler .section .exception_vectors.text @@ -218,26 +216,12 @@ _interrupt_handler: /* entry */ save_regs save_mepc + + /* Before doing anythig preserve the stack pointer */ + /* It will be saved in current TCB, if needed */ + mv a0, sp + call rtos_int_enter - /* scheduler not enabled, jump directly to ISR handler */ - lw t0, uxSchedulerRunning - beq t0, zero, already_on_handler - - /* increments the ISR nesting count */ - la t0, uxInterruptNesting - lw t1, 0x0(t0) - addi t2,t1,1 - sw t2, 0x0(t0) - - /* If reached here from another low priority ISR, skip stack pushing to TCB */ - bne t1,zero, already_on_handler - - /* Otherwise, save current sp, and use the isr stack from here */ - lw t0, pxCurrentTCB - sw sp, 0x0(t0) - lw sp, xIsrStackTop - -already_on_handler: /* Before dispatch c handler, restore interrupt to enable nested intr */ csrr s1, mcause csrr s2, mstatus @@ -278,29 +262,13 @@ already_on_handler: sw s3, 0(t0) fence - /* may skip RTOS aware interrupt since scheduler was not started */ - lw t1, uxSchedulerRunning - beq t1,zero, isr_exit + /* Yield to the next task is needed: */ + mv a0, sp + call rtos_int_exit - /* update nesting interrupts counter */ - la t0, uxInterruptNesting - lw t1, 0x0(t0) + /* The next (or current) stack pointer is returned in a0 */ + mv sp, a0 - /* Already zero, protect against underflow */ - beq t1, zero, isr_skip_decrement - addi t1,t1, -1 - sw t1, 0x0(t0) - -isr_skip_decrement: - /* may still have interrupts pending, skip section below and exit */ - bne t1,zero,isr_exit - - /* handled all the ISRs and scheduled the next task, take its stack */ - /* load on sp, then exit. */ - lw sp, pxCurrentTCB - lw sp, 0x0(sp) - -isr_exit: /* restore the rest of the registers */ csrw mcause, s1 csrw mstatus, s2 From 09bc1580be963e0a89dc22550dbe95929ce8e6e5 Mon Sep 17 00:00:00 2001 From: Felipe Neves Date: Wed, 11 Nov 2020 13:21:49 -0300 Subject: [PATCH 02/10] intr_allocator: add abstractions for priority, type and edge-ack interrupt controller functions --- components/esp_system/intr_alloc.c | 23 +++++------ .../include/hal/interrupt_controller_ll.h | 40 ++++++++++++++++++ .../include/hal/interrupt_controller_ll.h | 37 +++++++++++------ .../include/hal/interrupt_controller_ll.h | 41 +++++++++++++++++++ .../include/hal/interrupt_controller_ll.h | 40 ++++++++++++++++++ .../include/hal/interrupt_controller_hal.h | 32 +++++++++++++++ 6 files changed, 188 insertions(+), 25 deletions(-) diff --git a/components/esp_system/intr_alloc.c b/components/esp_system/intr_alloc.c index 22650cfc25..67f3b6c697 100644 --- a/components/esp_system/intr_alloc.c +++ b/components/esp_system/intr_alloc.c @@ -551,14 +551,11 @@ esp_err_t esp_intr_alloc_intrstatus(int source, int flags, uint32_t intrstatusre interrupt_controller_hal_set_int_handler(intr, handler, arg); #endif } -#ifdef __XTENSA__ // TODO ESP32-C3 IDF-2126 - if (flags&ESP_INTR_FLAG_EDGE) xthal_set_intclear(1 << intr); -#else + if (flags & ESP_INTR_FLAG_EDGE) { - ESP_INTR_DISABLE(intr); - esprv_intc_int_set_priority(intr, 0); - } -#endif + interrupt_controller_hal_edge_int_acknowledge(intr); + } + vd->source=source; } if (flags&ESP_INTR_FLAG_IRAM) { @@ -585,12 +582,12 @@ esp_err_t esp_intr_alloc_intrstatus(int source, int flags, uint32_t intrstatusre esp_intr_disable(ret); } -#if CONFIG_IDF_TARGET_ESP32C3 - // TODO ESP32-C3 IDF-2126, these need to be set or the new interrupt won't fire, but are currently hard-coded - // for priority and level... - esprv_intc_int_set_priority(intr, 1); - esprv_intc_int_set_type(BIT(intr), INTR_TYPE_LEVEL); -#endif + //Set the level and type at controller level if needed: + interrupt_controller_hal_set_int_level(intr, + interrupt_controller_hal_desc_level(intr)); + + interrupt_controller_hal_set_int_type(intr, + interrupt_controller_hal_desc_type(intr)); portEXIT_CRITICAL(&spinlock); diff --git a/components/hal/esp32/include/hal/interrupt_controller_ll.h b/components/hal/esp32/include/hal/interrupt_controller_ll.h index b61fa47dbc..d59fcc4d29 100644 --- a/components/hal/esp32/include/hal/interrupt_controller_ll.h +++ b/components/hal/esp32/include/hal/interrupt_controller_ll.h @@ -100,6 +100,46 @@ static inline void intr_cntrl_ll_enable_int_mask(uint32_t newmask) xt_int_enable_mask(newmask); } +/** + * @brief Acknowledge an edge-trigger interrupt by clearing its pending flag + * + * @param intr interrupt number ranged from 0 to 31 + */ +static inline void intr_cntrl_ll_edge_int_acknowledge (int intr) +{ + xthal_set_intclear(1 << intr); +} + +/** + * @brief Sets the interrupt level int the interrupt controller. + * + * @param interrupt_number Interrupt number 0 to 31 + * @param level priority between 1 (lowest) to 7 (highest) + */ +static inline void intr_cntrl_ll_set_int_level(int intr, int level) +{ + /* Not needed currently for xtensa platforms since the level is already set + * in interrupt table + */ + (void)intr; + (void)level; +} + +/** + * @brief Set the type of an interrupt in the controller. + * + * @param interrupt_number Interrupt number 0 to 31 + * @param type interrupt type as edge or level triggered + */ +static inline void intr_cntrl_ll_set_int_type(int intr, int_type_t type) +{ + /* Not needed currently for xtensa platforms since the type is already set + * in interrupt table + */ + (void)intr; + (void)type; +} + #ifdef __cplusplus } #endif diff --git a/components/hal/esp32c3/include/hal/interrupt_controller_ll.h b/components/hal/esp32c3/include/hal/interrupt_controller_ll.h index 96277e9922..8d0b8cb6d4 100644 --- a/components/hal/esp32c3/include/hal/interrupt_controller_ll.h +++ b/components/hal/esp32c3/include/hal/interrupt_controller_ll.h @@ -116,27 +116,40 @@ static inline void intr_cntrl_ll_enable_int_mask(uint32_t newmask) } /** - * @brief Set the interrupt type given an interrupt number. - * - * @param interrupt_number number of the interrupt - * @param type new type for this interrupt + * @brief Acknowledge an edge-trigger interrupt by clearing its pending flag + * + * @param intr interrupt number ranged from 0 to 31 */ -static inline void intr_cntrl_ll_set_type(int interrupt_number, int_type_t type) +static inline void intr_cntrl_ll_edge_int_acknowledge (int intr) { - esprv_intc_int_set_type(BIT(interrupt_number), type); + intr_cntrl_ll_disable_interrupts(1 << intr); + esprv_intc_int_set_priority(intr, 0); } /** - * @brief Set the interrupt level (priority) given an interrupt number. - * - * @param interrupt_number number of the interrupt - * @param level new level for this interrupt + * @brief Sets the interrupt level int the interrupt controller. + * + * @param interrupt_number Interrupt number 0 to 31 + * @param level priority between 1 (lowest) to 7 (highest) */ -static inline void intr_cntrl_ll_set_level(int interrupt_number, int level) +static inline void intr_cntrl_ll_set_int_level(int intr, int level) { - esprv_intc_int_set_priority(interrupt_number, level); + esprv_intc_int_set_priority(intr, level); } +/** + * @brief Set the type of an interrupt in the controller. + * + * @param interrupt_number Interrupt number 0 to 31 + * @param type interrupt type as edge or level triggered + */ +static inline void intr_cntrl_ll_set_int_type(int intr, int_type_t type) +{ + /* Not needed currently for xtensa platforms since the type is already set + * in interrupt table + */ + esprv_intc_int_set_type(BIT(intr), type); +} #ifdef __cplusplus } diff --git a/components/hal/esp32s2/include/hal/interrupt_controller_ll.h b/components/hal/esp32s2/include/hal/interrupt_controller_ll.h index b61fa47dbc..2e07c0ff00 100644 --- a/components/hal/esp32s2/include/hal/interrupt_controller_ll.h +++ b/components/hal/esp32s2/include/hal/interrupt_controller_ll.h @@ -100,6 +100,47 @@ static inline void intr_cntrl_ll_enable_int_mask(uint32_t newmask) xt_int_enable_mask(newmask); } +/** + * @brief Acknowledge an edge-trigger interrupt by clearing its pending flag + * + * @param intr interrupt number ranged from 0 to 31 + */ +static inline void intr_cntrl_ll_edge_int_acknowledge (int intr) +{ + xthal_set_intclear(1 << intr); +} + +/** + * @brief Sets the interrupt level int the interrupt controller. + * + * @param interrupt_number Interrupt number 0 to 31 + * @param level priority between 1 (lowest) to 7 (highest) + */ +static inline void intr_cntrl_ll_set_int_level(int intr, int level) +{ + /* Not needed currently for xtensa platforms since the level is already set + * in interrupt table + */ + (void)intr; + (void)level; +} + +/** + * @brief Set the type of an interrupt in the controller. + * + * @param interrupt_number Interrupt number 0 to 31 + * @param type interrupt type as edge or level triggered + */ +static inline void intr_cntrl_ll_set_int_type(int intr, int_type_t type) +{ + /* Not needed currently for xtensa platforms since the type is already set + * in interrupt table + */ + (void)intr; + (void)type; +} + + #ifdef __cplusplus } #endif diff --git a/components/hal/esp32s3/include/hal/interrupt_controller_ll.h b/components/hal/esp32s3/include/hal/interrupt_controller_ll.h index b61fa47dbc..d59fcc4d29 100644 --- a/components/hal/esp32s3/include/hal/interrupt_controller_ll.h +++ b/components/hal/esp32s3/include/hal/interrupt_controller_ll.h @@ -100,6 +100,46 @@ static inline void intr_cntrl_ll_enable_int_mask(uint32_t newmask) xt_int_enable_mask(newmask); } +/** + * @brief Acknowledge an edge-trigger interrupt by clearing its pending flag + * + * @param intr interrupt number ranged from 0 to 31 + */ +static inline void intr_cntrl_ll_edge_int_acknowledge (int intr) +{ + xthal_set_intclear(1 << intr); +} + +/** + * @brief Sets the interrupt level int the interrupt controller. + * + * @param interrupt_number Interrupt number 0 to 31 + * @param level priority between 1 (lowest) to 7 (highest) + */ +static inline void intr_cntrl_ll_set_int_level(int intr, int level) +{ + /* Not needed currently for xtensa platforms since the level is already set + * in interrupt table + */ + (void)intr; + (void)level; +} + +/** + * @brief Set the type of an interrupt in the controller. + * + * @param interrupt_number Interrupt number 0 to 31 + * @param type interrupt type as edge or level triggered + */ +static inline void intr_cntrl_ll_set_int_type(int intr, int_type_t type) +{ + /* Not needed currently for xtensa platforms since the type is already set + * in interrupt table + */ + (void)intr; + (void)type; +} + #ifdef __cplusplus } #endif diff --git a/components/hal/include/hal/interrupt_controller_hal.h b/components/hal/include/hal/interrupt_controller_hal.h index c0a6d61822..dd0f615a1f 100644 --- a/components/hal/include/hal/interrupt_controller_hal.h +++ b/components/hal/include/hal/interrupt_controller_hal.h @@ -84,6 +84,17 @@ static inline int_type_t interrupt_controller_hal_get_type(int interrupt_number) return interrupt_controller_hal_desc_type(interrupt_number); } +/** + * @brief Set the type of an interrupt in the controller. + * + * @param interrupt_number Interrupt number 0 to 31 + * @param type interrupt type as edge or level triggered + */ +static inline void interrupt_controller_hal_set_int_type(int intr, int_type_t type) +{ + intr_cntrl_ll_set_int_type(intr, type); +} + /** * @brief Gets the interrupt level given an interrupt number. * @@ -95,6 +106,17 @@ static inline int interrupt_controller_hal_get_level(int interrupt_number) return interrupt_controller_hal_desc_level(interrupt_number); } +/** + * @brief Sets the interrupt level int the interrupt controller. + * + * @param interrupt_number Interrupt number 0 to 31 + * @param level priority between 1 (lowest) to 7 (highest) + */ +static inline void interrupt_controller_hal_set_int_level(int intr, int level) +{ + intr_cntrl_ll_set_int_level(intr, level); +} + /** * @brief Gets the cpu flags given the interrupt number and target cpu. * @@ -184,6 +206,16 @@ static inline void interrupt_controller_hal_enable_int_mask(uint32_t newmask) intr_cntrl_ll_enable_int_mask(newmask); } +/** + * @brief Acknowledge an edge-trigger interrupt by clearing its pending flag + * + * @param intr interrupt number ranged from 0 to 31 + */ +static inline void interrupt_controller_hal_edge_int_acknowledge(int intr) +{ + intr_cntrl_ll_edge_int_acknowledge(intr); +} + #ifdef __cplusplus } #endif From f4781d3b1d76d797e77bdb5415e9f5335e491b98 Mon Sep 17 00:00:00 2001 From: Felipe Neves Date: Fri, 13 Nov 2020 16:03:50 -0300 Subject: [PATCH 03/10] freertos: riscv port now uses interrupt allocator and crosscore interrupt --- components/freertos/port/riscv/port.c | 103 +++++++----------- components/freertos/port/riscv/portasm.S | 16 +-- .../hal/esp32c3/interrupt_descriptor_table.c | 3 - components/riscv/vectors.S | 1 - 4 files changed, 46 insertions(+), 77 deletions(-) diff --git a/components/freertos/port/riscv/port.c b/components/freertos/port/riscv/port.c index 6895604c60..4e29cb6494 100644 --- a/components/freertos/port/riscv/port.c +++ b/components/freertos/port/riscv/port.c @@ -77,19 +77,23 @@ #include #include "FreeRTOS.h" #include "task.h" -#include "sdkconfig.h" #include "portmacro.h" -#include "riscv/interrupt.h" -#include "riscv/rvruntime-frames.h" + +#include "sdkconfig.h" + #include "soc/periph_defs.h" #include "soc/system_reg.h" -#include "soc/interrupt_reg.h" #include "hal/systimer_hal.h" #include "hal/systimer_ll.h" + +#include "riscv/rvruntime-frames.h" #include "riscv/riscv_interrupts.h" #include "riscv/interrupt.h" + #include "esp_system.h" #include "esp_intr_alloc.h" +#include "esp_private/crosscore_int.h" +#include "esp_attr.h" #include "esp_log.h" /** @@ -98,7 +102,7 @@ * to ensure interrupts don't inadvertently become unmasked before the scheduler starts. * As it is stored as part of the task context it will automatically be set to 0 when the first task is started. */ -static UBaseType_t uxCriticalNesting = 0; +static UBaseType_t uxCriticalNesting = 0; static UBaseType_t uxSavedInterruptState = 0; BaseType_t uxSchedulerRunning = 0; UBaseType_t uxInterruptNesting = 0; @@ -108,10 +112,8 @@ StackType_t *xIsrStackTop = &xIsrStack[0] + (configISR_STACK_SIZE & (~((portPOIN static const char *TAG = "cpu_start"; // [refactor-todo]: might be appropriate to change in the future, but -static void vPortSysTickHandler(void); +static void vPortSysTickHandler(void *arg); static void vPortSetupTimer(void); -static void vPortSetupSoftwareInterrupt(void); -static void vPortSoftwareInterrupt(void); static void prvTaskExitError(void); extern void esprv_intc_int_set_threshold(int); // FIXME, this function is in ROM only @@ -144,16 +146,9 @@ void vPortExitCritical(void) */ void vPortSetupTimer(void) { - /* register the interrupt handler */ - intr_handler_set(ETS_SYSTICK_INUM, (intr_handler_t)&vPortSysTickHandler, NULL); - - /* pass the timer interrupt through the interrupt matrix */ - intr_matrix_route(ETS_SYSTIMER_TARGET0_EDGE_INTR_SOURCE, ETS_SYSTICK_INUM); - - /* enable the interrupt in the INTC */ - esprv_intc_int_enable(BIT(ETS_SYSTICK_INUM)); - esprv_intc_int_set_type(BIT(ETS_SYSTICK_INUM), INTR_TYPE_LEVEL); - esprv_intc_int_set_priority(ETS_SYSTICK_INUM, 1); + /* set system timer interrupt vector */ + esp_err_t err = esp_intr_alloc(ETS_SYSTIMER_TARGET0_EDGE_INTR_SOURCE, ESP_INTR_FLAG_IRAM, vPortSysTickHandler, NULL, NULL); + assert(err == ESP_OK); /* configure the timer */ systimer_hal_init(); @@ -164,24 +159,6 @@ void vPortSetupTimer(void) systimer_hal_connect_alarm_counter(SYSTIMER_ALARM_0, SYSTIMER_COUNTER_1); } -/* setup software interrupt */ -void vPortSetupSoftwareInterrupt(void) -{ - /* register the interrupt handler, see interrupt.h */ - intr_handler_set(ETS_CPU_INTR0_INUM, (intr_handler_t)&vPortSoftwareInterrupt, NULL); - - /* pass the "FROM_CPU_0", a.k.a. cross-core interrupt, through the interrupt matrix */ - intr_matrix_route(ETS_FROM_CPU_INTR0_SOURCE, ETS_CPU_INTR0_INUM); - - /* enable the interrupt in the INTC */ - esprv_intc_int_enable(BIT(ETS_CPU_INTR0_INUM)); - esprv_intc_int_set_type(BIT(ETS_CPU_INTR0_INUM), INTR_TYPE_LEVEL); - esprv_intc_int_set_priority(ETS_CPU_INTR0_INUM, 1); - - // TODO ESP32-C3 IDF-2126, maybe can use interrupt allocation API for all of the above? unsure... - esp_intr_reserve(ETS_CPU_INTR0_INUM, xPortGetCoreID()); -} - void prvTaskExitError(void) { /* A function that implements a task must not exit or attempt to return to @@ -213,9 +190,6 @@ int vPortSetInterruptMask(void) return ret; } -/* - * See header file for description. - */ StackType_t *pxPortInitialiseStack(StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters) { extern uint32_t __global_pointer$; @@ -232,11 +206,15 @@ StackType_t *pxPortInitialiseStack(StackType_t *pxTopOfStack, TaskFunction_t pxC frame->a1 = 0x11111111; frame->a2 = 0x22222222; frame->a3 = 0x33333333; + + //TODO: IDF-2393 return (StackType_t *)frame; } -void vPortSysTickHandler(void) +IRAM_ATTR void vPortSysTickHandler(void *arg) { + (void)arg; + systimer_ll_clear_alarm_int(SYSTIMER_ALARM_0); if (!uxSchedulerRunning) { @@ -249,15 +227,18 @@ void vPortSysTickHandler(void) } BaseType_t xPortStartScheduler(void) -{ - vPortSetupTimer(); - vPortSetupSoftwareInterrupt(); +{ uxInterruptNesting = 0; uxCriticalNesting = 0; - uxSchedulerRunning = 0; /* this means first yield */ + uxSchedulerRunning = 0; + + vPortSetupTimer(); + esprv_intc_int_set_threshold(1); /* set global INTC masking level */ riscv_global_interrupts_enable(); + vPortYield(); + /*Should not get here*/ return pdFALSE; } @@ -265,20 +246,18 @@ BaseType_t xPortStartScheduler(void) void vPortEndScheduler(void) { /* very unlikely this function will be called, so just trap here */ - while (1) - ; -} - -void vPortSoftwareInterrupt(void) -{ - uxSchedulerRunning = 1; - REG_WRITE(SYSTEM_CPU_INTR_FROM_CPU_0_REG, 0); + abort(); } void vPortYieldOtherCore(BaseType_t coreid) { - (void)coreid; - vPortYield(); + esp_crosscore_int_send_yield(coreid); +} + +void vPortYieldFromISR( void ) +{ + uxSchedulerRunning = 1; + xPortSwitchFlag = 1; } void vPortYield(void) @@ -286,9 +265,8 @@ void vPortYield(void) if (uxInterruptNesting) { vPortYieldFromISR(); } else { - xPortSwitchFlag = 1; - REG_WRITE(SYSTEM_CPU_INTR_FROM_CPU_0_REG, 1); + esp_crosscore_int_send_yield(0); /* There are 3-4 instructions of latency between triggering the software interrupt and the CPU interrupt happening. Make sure it happened before we return, otherwise vTaskDelay() may return and execute 1-2 @@ -304,11 +282,6 @@ void vPortYield(void) } -void vPortYieldFromISR( void ) -{ - xPortSwitchFlag = 1; -} - void vPortSetStackWatchpoint(void *pxStackStart) { (void)pxStackStart; // TODO ESP32-C3 IDF-2207 @@ -328,24 +301,24 @@ BaseType_t IRAM_ATTR xPortInterruptedFromISRContext(void) void vPortCPUInitializeMutex(portMUX_TYPE *mux) { - (void)mux; + (void)mux; //TODO: IDF-2393 } void vPortCPUAcquireMutex(portMUX_TYPE *mux) { - (void)mux; + (void)mux; //TODO: IDF-2393 } bool vPortCPUAcquireMutexTimeout(portMUX_TYPE *mux, int timeout_cycles) { - (void)mux; + (void)mux; //TODO: IDF-2393 (void)timeout_cycles; return true; } void vPortCPUReleaseMutex(portMUX_TYPE *mux) { - (void)mux; + (void)mux; //TODO: IDF-2393 } void __attribute__((weak)) vApplicationStackOverflowHook(TaskHandle_t xTask, char *pcTaskName) diff --git a/components/freertos/port/riscv/portasm.S b/components/freertos/port/riscv/portasm.S index 8d19ba3467..04a5399a94 100644 --- a/components/freertos/port/riscv/portasm.S +++ b/components/freertos/port/riscv/portasm.S @@ -70,18 +70,18 @@ rtos_int_exit: beq t0,zero, rtos_exit_end /* update nesting interrupts counter */ - la t2, uxInterruptNesting - lw t3, 0x0(t2) + la t2, uxInterruptNesting + lw t3, 0x0(t2) - /* Already zero, protect againts underflow */ - beq t3, zero, isr_skip_decrement - addi t3,t3, -1 - sw t3, 0x0(t2) + /* Already zero, protect againts underflow */ + beq t3, zero, isr_skip_decrement + addi t3,t3, -1 + sw t3, 0x0(t2) isr_skip_decrement: - /* may still have interrupts pending, skip section below and exit */ - bne t3,zero,rtos_exit_end + /* may still have interrupts pending, skip section below and exit */ + bne t3,zero,rtos_exit_end /* Schedule the next task if a yield is pending */ la t0, xPortSwitchFlag diff --git a/components/hal/esp32c3/interrupt_descriptor_table.c b/components/hal/esp32c3/interrupt_descriptor_table.c index b4c8637b91..8c0837e195 100644 --- a/components/hal/esp32c3/interrupt_descriptor_table.c +++ b/components/hal/esp32c3/interrupt_descriptor_table.c @@ -16,9 +16,6 @@ #include "soc/soc_caps.h" #include "soc/soc.h" -// TODO ESP32-C3 IDF-2126 check this table is correct, some interrupts may be unnecessarily reserved or not reserved -// or marked as the wrong type - //This is basically a software-readable version of the interrupt usage table in include/soc/soc.h const int_desc_t interrupt_descriptor_table[32] = { { 1, INTTP_LEVEL, {INTDESC_RESVD } }, //0 diff --git a/components/riscv/vectors.S b/components/riscv/vectors.S index b55f4c12fe..081fb951d4 100644 --- a/components/riscv/vectors.S +++ b/components/riscv/vectors.S @@ -99,7 +99,6 @@ .global rtos_int_enter .global rtos_int_exit - .global uxInterruptNesting .global _global_interrupt_handler .section .exception_vectors.text From ec5acf91ee88db44ce04f38d9c6ef4537015e872 Mon Sep 17 00:00:00 2001 From: Felipe Neves Date: Tue, 17 Nov 2020 16:37:28 -0300 Subject: [PATCH 04/10] esp_shared_stack: enable shared stack function for riscv and reenable the unit test --- .../port/riscv/include/freertos/xtensa_api.h | 2 + components/riscv/CMakeLists.txt | 2 + .../riscv/expression_with_stack_riscv.c | 79 +++++++++++++++++++ .../riscv/expression_with_stack_riscv_asm.S | 43 ++++++++++ 4 files changed, 126 insertions(+) create mode 100644 components/freertos/port/riscv/include/freertos/xtensa_api.h create mode 100644 components/riscv/expression_with_stack_riscv.c create mode 100644 components/riscv/expression_with_stack_riscv_asm.S diff --git a/components/freertos/port/riscv/include/freertos/xtensa_api.h b/components/freertos/port/riscv/include/freertos/xtensa_api.h new file mode 100644 index 0000000000..245b6246c0 --- /dev/null +++ b/components/freertos/port/riscv/include/freertos/xtensa_api.h @@ -0,0 +1,2 @@ +/* Just a placeholder since this file is exposed in some top-level apps */ +#pragma once diff --git a/components/riscv/CMakeLists.txt b/components/riscv/CMakeLists.txt index 6d3744d6a7..c42b51db9d 100644 --- a/components/riscv/CMakeLists.txt +++ b/components/riscv/CMakeLists.txt @@ -9,6 +9,8 @@ else() set(srcs "interrupt.c" "stdatomic.c" + "expression_with_stack_riscv.c" + "expression_with_stack_riscv_asm.S" "vectors.S") endif() diff --git a/components/riscv/expression_with_stack_riscv.c b/components/riscv/expression_with_stack_riscv.c new file mode 100644 index 0000000000..28e492ce00 --- /dev/null +++ b/components/riscv/expression_with_stack_riscv.c @@ -0,0 +1,79 @@ +// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD +// +// 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 +// +// 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 +#include +#include + +static portMUX_TYPE shared_stack_spinlock = portMUX_INITIALIZER_UNLOCKED; +static void *current_task_stack = NULL; + +extern void esp_shared_stack_invoke_function(shared_stack_function function, void *stack); + +static StackType_t *esp_switch_stack_setup(StackType_t *stack, size_t stack_size) +{ +#if CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK + // TODO ESP32-C3 IDF-2207 + // esp_clear_watchpoint(1); + // uint32_t watchpoint_place = ((uint32_t)stack + 32) & ~0x1f ; +#endif + //We need also to tweak current task stackpointer to avoid erroneous + //stack overflow indication, so fills the stack with freertos known pattern: + memset(stack, 0xa5U, stack_size * sizeof(StackType_t)); + + StaticTask_t *current = (StaticTask_t *)xTaskGetCurrentTaskHandle(); + //Then put the fake stack inside of TCB: + current_task_stack = current->pxDummy6; + current->pxDummy6 = (void *)stack; + + StackType_t *top_of_stack = stack + stack_size; + + //Align stack to a 16byte boundary, as required by CPU specific: + top_of_stack = (StackType_t *)(((UBaseType_t)(top_of_stack - 16) & ~0xf)); + RvExcFrame *adjusted_top_of_stack = (RvExcFrame *) top_of_stack; + adjusted_top_of_stack--; + +#if CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK + // TODO ESP32-C3 IDF-2207 + //esp_set_watchpoint(1, (uint8_t *)watchpoint_place, 32, ESP_WATCHPOINT_STORE); +#endif + + return ((StackType_t *)adjusted_top_of_stack); +} + + +void esp_execute_shared_stack_function(SemaphoreHandle_t lock, void *stack, size_t stack_size, shared_stack_function function) +{ + assert(lock); + assert(stack); + assert(stack_size > 0 && stack_size >= CONFIG_ESP_MINIMAL_SHARED_STACK_SIZE); + assert(function); + + xSemaphoreTake(lock, portMAX_DELAY); + portENTER_CRITICAL(&shared_stack_spinlock); + stack = esp_switch_stack_setup(stack, stack_size); + portEXIT_CRITICAL(&shared_stack_spinlock); + + esp_shared_stack_invoke_function(function, stack); + + portENTER_CRITICAL(&shared_stack_spinlock); + StaticTask_t *current = (StaticTask_t *)xTaskGetCurrentTaskHandle(); + + //Restore current task stack: + current->pxDummy6 = (StackType_t *)current_task_stack; + vPortSetStackWatchpoint(current->pxDummy6); + portEXIT_CRITICAL(&shared_stack_spinlock); + + xSemaphoreGive(lock); +} diff --git a/components/riscv/expression_with_stack_riscv_asm.S b/components/riscv/expression_with_stack_riscv_asm.S new file mode 100644 index 0000000000..99b0ec5840 --- /dev/null +++ b/components/riscv/expression_with_stack_riscv_asm.S @@ -0,0 +1,43 @@ +// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD +// +// 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 + +// 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. + + .section .text + + .global esp_shared_stack_invoke_function + .type esp_shared_stack_invoke_function, @function +esp_shared_stack_invoke_function: + /* save current stack and return address */ + mv t0, sp + mv t1, ra + + /* Set shared stack as new stack pointer */ + mv sp, a1 + + /* store the ra and previous stack pointer in a safe place */ + addi sp,sp,-4 + sw t0, 0(sp) + sw t1, 4(sp) + + /* call the subroutine */ + jalr a0, 0 + + /* gets the ra and stack pointer saved previously */ + lw t0, 0(sp) + lw t1, 4(sp) + addi sp, sp, 4 + + /* restore both ra and real stack pointer of current task */ + mv ra, t1 + mv sp, t0 + ret From 544a3f7df5693bc32a7264e0a5bfec486620f9dd Mon Sep 17 00:00:00 2001 From: Felipe Neves Date: Thu, 19 Nov 2020 15:14:54 -0300 Subject: [PATCH 05/10] interrupt-allocator: reject vector allocation if its marked as not-implemented. and search to next available --- components/esp_system/intr_alloc.c | 25 +++++--- .../port/riscv/include/freertos/xtensa_api.h | 2 - components/freertos/port/riscv/portasm.S | 2 +- .../include/hal/interrupt_controller_ll.h | 6 +- .../hal/esp32c3/interrupt_descriptor_table.c | 64 +++++++++---------- .../include/hal/interrupt_controller_types.h | 4 +- components/riscv/include/riscv/interrupt.h | 7 ++ components/riscv/interrupt.c | 6 ++ 8 files changed, 64 insertions(+), 52 deletions(-) delete mode 100644 components/freertos/port/riscv/include/freertos/xtensa_api.h diff --git a/components/esp_system/intr_alloc.c b/components/esp_system/intr_alloc.c index 67f3b6c697..b00fdacae3 100644 --- a/components/esp_system/intr_alloc.c +++ b/components/esp_system/intr_alloc.c @@ -48,7 +48,7 @@ Define this to debug the choices made when allocating the interrupt. This leads 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. */ -//define DEBUG_INT_ALLOC_DECISIONS +//#define DEBUG_INT_ALLOC_DECISIONS #ifdef DEBUG_INT_ALLOC_DECISIONS # define ALCHLOG(...) ESP_EARLY_LOGD(TAG, __VA_ARGS__) #else @@ -238,13 +238,14 @@ static bool is_vect_desc_usable(vector_desc_t *vd, int flags, int cpu, int force return false; } //Check if the interrupt level is acceptable - if (!(flags&(1<> 1) & ESP_INTR_FLAG_LEVELMASK)) + 1; - interrupt_controller_hal_set_int_type(intr, - interrupt_controller_hal_desc_type(intr)); + interrupt_controller_hal_set_int_level(intr,level); + + if (flags & ESP_INTR_FLAG_EDGE) { + interrupt_controller_hal_set_int_type(intr,INTTP_EDGE); + } else { + interrupt_controller_hal_set_int_type(intr,INTTP_LEVEL); + } portEXIT_CRITICAL(&spinlock); diff --git a/components/freertos/port/riscv/include/freertos/xtensa_api.h b/components/freertos/port/riscv/include/freertos/xtensa_api.h deleted file mode 100644 index 245b6246c0..0000000000 --- a/components/freertos/port/riscv/include/freertos/xtensa_api.h +++ /dev/null @@ -1,2 +0,0 @@ -/* Just a placeholder since this file is exposed in some top-level apps */ -#pragma once diff --git a/components/freertos/port/riscv/portasm.S b/components/freertos/port/riscv/portasm.S index 04a5399a94..3f4740299b 100644 --- a/components/freertos/port/riscv/portasm.S +++ b/components/freertos/port/riscv/portasm.S @@ -73,7 +73,7 @@ rtos_int_exit: la t2, uxInterruptNesting lw t3, 0x0(t2) - /* Already zero, protect againts underflow */ + /* Already zero, protect against underflow */ beq t3, zero, isr_skip_decrement addi t3,t3, -1 sw t3, 0x0(t2) diff --git a/components/hal/esp32c3/include/hal/interrupt_controller_ll.h b/components/hal/esp32c3/include/hal/interrupt_controller_ll.h index 8d0b8cb6d4..ca47c3a16f 100644 --- a/components/hal/esp32c3/include/hal/interrupt_controller_ll.h +++ b/components/hal/esp32c3/include/hal/interrupt_controller_ll.h @@ -122,8 +122,7 @@ static inline void intr_cntrl_ll_enable_int_mask(uint32_t newmask) */ static inline void intr_cntrl_ll_edge_int_acknowledge (int intr) { - intr_cntrl_ll_disable_interrupts(1 << intr); - esprv_intc_int_set_priority(intr, 0); + esprv_intc_set_interrupt_clear(intr); } /** @@ -145,9 +144,6 @@ static inline void intr_cntrl_ll_set_int_level(int intr, int level) */ static inline void intr_cntrl_ll_set_int_type(int intr, int_type_t type) { - /* Not needed currently for xtensa platforms since the type is already set - * in interrupt table - */ esprv_intc_int_set_type(BIT(intr), type); } diff --git a/components/hal/esp32c3/interrupt_descriptor_table.c b/components/hal/esp32c3/interrupt_descriptor_table.c index 8c0837e195..7e0e5709c4 100644 --- a/components/hal/esp32c3/interrupt_descriptor_table.c +++ b/components/hal/esp32c3/interrupt_descriptor_table.c @@ -18,38 +18,38 @@ //This is basically a software-readable version of the interrupt usage table in include/soc/soc.h const int_desc_t interrupt_descriptor_table[32] = { - { 1, INTTP_LEVEL, {INTDESC_RESVD } }, //0 - { 1, INTTP_LEVEL, {INTDESC_SPECIAL } }, //1 - { 1, INTTP_LEVEL, {INTDESC_NORMAL } }, //2 - { 1, INTTP_LEVEL, {INTDESC_NORMAL } }, //3 - { 1, INTTP_LEVEL, {INTDESC_NORMAL } }, //4 - { 1, INTTP_LEVEL, {INTDESC_SPECIAL } }, //5 - { 1, INTTP_NA, {INTDESC_NORMAL } }, //6 - { 1, INTTP_NA, {INTDESC_NORMAL } }, //7 - { 1, INTTP_LEVEL, {INTDESC_SPECIAL } }, //8 - { 1, INTTP_LEVEL, {INTDESC_SPECIAL } }, //9 - { 1, INTTP_EDGE, {INTDESC_NORMAL } }, //10 - { 3, INTTP_NA, {INTDESC_NORMAL } }, //11 - { 1, INTTP_LEVEL, {INTDESC_SPECIAL } }, //12 - { 1, INTTP_LEVEL, {INTDESC_NORMAL } }, //13 - { 7, INTTP_LEVEL, {INTDESC_NORMAL } }, //14 - { 3, INTTP_NA, {INTDESC_NORMAL } }, //15 - { 5, INTTP_NA, {INTDESC_NORMAL } }, //16 - { 1, INTTP_LEVEL, {INTDESC_NORMAL } }, //17 - { 1, INTTP_LEVEL, {INTDESC_NORMAL } }, //18 - { 2, INTTP_LEVEL, {INTDESC_NORMAL } }, //19 - { 2, INTTP_LEVEL, {INTDESC_NORMAL } }, //20 - { 2, INTTP_LEVEL, {INTDESC_NORMAL } }, //21 - { 3, INTTP_EDGE, {INTDESC_NORMAL } }, //22 - { 3, INTTP_LEVEL, {INTDESC_NORMAL } }, //23 - { 4, INTTP_LEVEL, {INTDESC_RESVD } }, //24 - { 4, INTTP_LEVEL, {INTDESC_RESVD } }, //25 - { 5, INTTP_LEVEL, {INTDESC_NORMAL } }, //26 - { 3, INTTP_LEVEL, {INTDESC_NORMAL } }, //27 - { 4, INTTP_EDGE, {INTDESC_NORMAL } }, //28 - { 3, INTTP_NA, {INTDESC_NORMAL } }, //29 - { 4, INTTP_EDGE, {INTDESC_NORMAL } }, //30 - { 5, INTTP_LEVEL, {INTDESC_NORMAL } }, //31 + { 1, INTTP_ANY, {INTDESC_RESVD } }, //0 + { 1, INTTP_ANY, {INTDESC_SPECIAL } }, //1 + { 1, INTTP_ANY, {INTDESC_NORMAL } }, //2 + { 1, INTTP_ANY, {INTDESC_NORMAL } }, //3 + { 1, INTTP_ANY, {INTDESC_NORMAL } }, //4 + { 1, INTTP_ANY, {INTDESC_SPECIAL } }, //5 + { 1, INTTP_ANY, {INTDESC_NORMAL } }, //6 + { 1, INTTP_ANY, {INTDESC_NORMAL } }, //7 + { 1, INTTP_ANY, {INTDESC_SPECIAL } }, //8 + { 1, INTTP_ANY, {INTDESC_SPECIAL } }, //9 + { 1, INTTP_ANY, {INTDESC_NORMAL } }, //10 + { 1, INTTP_ANY, {INTDESC_NORMAL } }, //11 + { 1, INTTP_ANY, {INTDESC_SPECIAL } }, //12 + { 1, INTTP_ANY, {INTDESC_NORMAL } }, //13 + { 1, INTTP_ANY, {INTDESC_NORMAL } }, //14 + { 1, INTTP_ANY, {INTDESC_NORMAL } }, //15 + { 1, INTTP_ANY, {INTDESC_NORMAL } }, //16 + { 1, INTTP_ANY, {INTDESC_NORMAL } }, //17 + { 1, INTTP_ANY, {INTDESC_NORMAL } }, //18 + { 1, INTTP_ANY, {INTDESC_NORMAL } }, //19 + { 1, INTTP_ANY, {INTDESC_NORMAL } }, //20 + { 1, INTTP_ANY, {INTDESC_NORMAL } }, //21 + { 1, INTTP_ANY, {INTDESC_NORMAL } }, //22 + { 1, INTTP_ANY, {INTDESC_NORMAL } }, //23 + { 1, INTTP_ANY, {INTDESC_NORMAL } }, //24 + { 1, INTTP_ANY, {INTDESC_NORMAL } }, //25 + { 1, INTTP_ANY, {INTDESC_NORMAL } }, //26 + { 1, INTTP_ANY, {INTDESC_NORMAL } }, //27 + { 1, INTTP_ANY, {INTDESC_NORMAL } }, //28 + { 1, INTTP_ANY, {INTDESC_NORMAL } }, //29 + { 1, INTTP_ANY, {INTDESC_NORMAL } }, //30 + { 1, INTTP_ANY, {INTDESC_NORMAL } }, //31 }; const int_desc_t *interrupt_controller_hal_desc_table(void) diff --git a/components/hal/include/hal/interrupt_controller_types.h b/components/hal/include/hal/interrupt_controller_types.h index bf9be1fd1f..9e36dc7361 100644 --- a/components/hal/include/hal/interrupt_controller_types.h +++ b/components/hal/include/hal/interrupt_controller_types.h @@ -24,13 +24,13 @@ extern "C" { typedef enum { INTDESC_NORMAL=0, INTDESC_RESVD, - INTDESC_SPECIAL + INTDESC_SPECIAL, } int_desc_flag_t; typedef enum { INTTP_LEVEL=0, INTTP_EDGE, - INTTP_NA + INTTP_ANY, } int_type_t; typedef struct { diff --git a/components/riscv/include/riscv/interrupt.h b/components/riscv/include/riscv/interrupt.h index 6498d57f2f..ed87384c17 100644 --- a/components/riscv/include/riscv/interrupt.h +++ b/components/riscv/include/riscv/interrupt.h @@ -110,6 +110,13 @@ void esprv_intc_set_threshold(int priority_threshold); */ uint32_t esprv_intc_get_interrupt_unmask(void); +/** + * @brief Set a bit in int clear register + * @param intr bit to set from 0 to 31 + * @return none + */ +void esprv_intc_set_interrupt_clear(int intr); + #ifdef __cplusplus } #endif diff --git a/components/riscv/interrupt.c b/components/riscv/interrupt.c index 1b48bfdf89..3be259be89 100644 --- a/components/riscv/interrupt.c +++ b/components/riscv/interrupt.c @@ -89,6 +89,12 @@ uint32_t esprv_intc_get_interrupt_unmask(void) return REG_READ(INTERRUPT_CORE0_CPU_INT_ENABLE_REG); } +void esprv_intc_set_interrupt_clear(int intr) +{ + REG_SET_BIT(INTERRUPT_CORE0_CPU_INT_CLEAR_REG, intr); +} + + /*************************** Exception names. Used in .gdbinit file. ***************************/ const char *riscv_excp_names[16] __attribute__((used)) = { From 5d316ac14200753bd64b0f0e504342ec61406b9b Mon Sep 17 00:00:00 2001 From: Felipe Neves Date: Wed, 16 Dec 2020 14:20:38 -0300 Subject: [PATCH 06/10] interrupt: added INTC FLEXIBLE capabillity to esp32c3 CPU caps --- components/esp_system/intr_alloc.c | 20 +++--- .../include/hal/interrupt_controller_ll.h | 30 --------- .../hal/esp32c3/interrupt_descriptor_table.c | 64 +++++++++---------- .../include/hal/interrupt_controller_ll.h | 32 ---------- .../include/hal/interrupt_controller_ll.h | 31 --------- .../include/hal/interrupt_controller_hal.h | 24 +++---- .../include/hal/interrupt_controller_types.h | 2 +- components/soc/esp32c3/include/soc/cpu_caps.h | 1 + 8 files changed, 59 insertions(+), 145 deletions(-) diff --git a/components/esp_system/intr_alloc.c b/components/esp_system/intr_alloc.c index b00fdacae3..4e88cc8698 100644 --- a/components/esp_system/intr_alloc.c +++ b/components/esp_system/intr_alloc.c @@ -237,18 +237,20 @@ static bool is_vect_desc_usable(vector_desc_t *vd, int flags, int cpu, int force ALCHLOG("....Unusable: special-purpose int"); return false; } + +#ifndef SOC_CPU_HAS_FLEXIBLE_INTC //Check if the interrupt level is acceptable - if (!(flags&(1<flags&VECDESC_FL_RESERVED) { ALCHLOG("....Unusable: reserved at runtime."); @@ -583,6 +585,7 @@ esp_err_t esp_intr_alloc_intrstatus(int source, int flags, uint32_t intrstatusre esp_intr_disable(ret); } +#ifdef SOC_CPU_HAS_FLEXIBLE_INTC //Extract the level from the interrupt passed flags int level = (__builtin_ffs((flags >> 1) & ESP_INTR_FLAG_LEVELMASK)) + 1; @@ -593,6 +596,7 @@ esp_err_t esp_intr_alloc_intrstatus(int source, int flags, uint32_t intrstatusre } else { interrupt_controller_hal_set_int_type(intr,INTTP_LEVEL); } +#endif portEXIT_CRITICAL(&spinlock); diff --git a/components/hal/esp32/include/hal/interrupt_controller_ll.h b/components/hal/esp32/include/hal/interrupt_controller_ll.h index d59fcc4d29..f450f2c6c1 100644 --- a/components/hal/esp32/include/hal/interrupt_controller_ll.h +++ b/components/hal/esp32/include/hal/interrupt_controller_ll.h @@ -110,36 +110,6 @@ static inline void intr_cntrl_ll_edge_int_acknowledge (int intr) xthal_set_intclear(1 << intr); } -/** - * @brief Sets the interrupt level int the interrupt controller. - * - * @param interrupt_number Interrupt number 0 to 31 - * @param level priority between 1 (lowest) to 7 (highest) - */ -static inline void intr_cntrl_ll_set_int_level(int intr, int level) -{ - /* Not needed currently for xtensa platforms since the level is already set - * in interrupt table - */ - (void)intr; - (void)level; -} - -/** - * @brief Set the type of an interrupt in the controller. - * - * @param interrupt_number Interrupt number 0 to 31 - * @param type interrupt type as edge or level triggered - */ -static inline void intr_cntrl_ll_set_int_type(int intr, int_type_t type) -{ - /* Not needed currently for xtensa platforms since the type is already set - * in interrupt table - */ - (void)intr; - (void)type; -} - #ifdef __cplusplus } #endif diff --git a/components/hal/esp32c3/interrupt_descriptor_table.c b/components/hal/esp32c3/interrupt_descriptor_table.c index 7e0e5709c4..ca2ea05641 100644 --- a/components/hal/esp32c3/interrupt_descriptor_table.c +++ b/components/hal/esp32c3/interrupt_descriptor_table.c @@ -18,38 +18,38 @@ //This is basically a software-readable version of the interrupt usage table in include/soc/soc.h const int_desc_t interrupt_descriptor_table[32] = { - { 1, INTTP_ANY, {INTDESC_RESVD } }, //0 - { 1, INTTP_ANY, {INTDESC_SPECIAL } }, //1 - { 1, INTTP_ANY, {INTDESC_NORMAL } }, //2 - { 1, INTTP_ANY, {INTDESC_NORMAL } }, //3 - { 1, INTTP_ANY, {INTDESC_NORMAL } }, //4 - { 1, INTTP_ANY, {INTDESC_SPECIAL } }, //5 - { 1, INTTP_ANY, {INTDESC_NORMAL } }, //6 - { 1, INTTP_ANY, {INTDESC_NORMAL } }, //7 - { 1, INTTP_ANY, {INTDESC_SPECIAL } }, //8 - { 1, INTTP_ANY, {INTDESC_SPECIAL } }, //9 - { 1, INTTP_ANY, {INTDESC_NORMAL } }, //10 - { 1, INTTP_ANY, {INTDESC_NORMAL } }, //11 - { 1, INTTP_ANY, {INTDESC_SPECIAL } }, //12 - { 1, INTTP_ANY, {INTDESC_NORMAL } }, //13 - { 1, INTTP_ANY, {INTDESC_NORMAL } }, //14 - { 1, INTTP_ANY, {INTDESC_NORMAL } }, //15 - { 1, INTTP_ANY, {INTDESC_NORMAL } }, //16 - { 1, INTTP_ANY, {INTDESC_NORMAL } }, //17 - { 1, INTTP_ANY, {INTDESC_NORMAL } }, //18 - { 1, INTTP_ANY, {INTDESC_NORMAL } }, //19 - { 1, INTTP_ANY, {INTDESC_NORMAL } }, //20 - { 1, INTTP_ANY, {INTDESC_NORMAL } }, //21 - { 1, INTTP_ANY, {INTDESC_NORMAL } }, //22 - { 1, INTTP_ANY, {INTDESC_NORMAL } }, //23 - { 1, INTTP_ANY, {INTDESC_NORMAL } }, //24 - { 1, INTTP_ANY, {INTDESC_NORMAL } }, //25 - { 1, INTTP_ANY, {INTDESC_NORMAL } }, //26 - { 1, INTTP_ANY, {INTDESC_NORMAL } }, //27 - { 1, INTTP_ANY, {INTDESC_NORMAL } }, //28 - { 1, INTTP_ANY, {INTDESC_NORMAL } }, //29 - { 1, INTTP_ANY, {INTDESC_NORMAL } }, //30 - { 1, INTTP_ANY, {INTDESC_NORMAL } }, //31 + { 1, INTTP_NA, {INTDESC_RESVD } }, //0 + { 1, INTTP_NA, {INTDESC_SPECIAL } }, //1 + { 1, INTTP_NA, {INTDESC_NORMAL } }, //2 + { 1, INTTP_NA, {INTDESC_NORMAL } }, //3 + { 1, INTTP_NA, {INTDESC_NORMAL } }, //4 + { 1, INTTP_NA, {INTDESC_SPECIAL } }, //5 + { 1, INTTP_NA, {INTDESC_NORMAL } }, //6 + { 1, INTTP_NA, {INTDESC_NORMAL } }, //7 + { 1, INTTP_NA, {INTDESC_SPECIAL } }, //8 + { 1, INTTP_NA, {INTDESC_SPECIAL } }, //9 + { 1, INTTP_NA, {INTDESC_NORMAL } }, //10 + { 1, INTTP_NA, {INTDESC_NORMAL } }, //11 + { 1, INTTP_NA, {INTDESC_SPECIAL } }, //12 + { 1, INTTP_NA, {INTDESC_NORMAL } }, //13 + { 1, INTTP_NA, {INTDESC_NORMAL } }, //14 + { 1, INTTP_NA, {INTDESC_NORMAL } }, //15 + { 1, INTTP_NA, {INTDESC_NORMAL } }, //16 + { 1, INTTP_NA, {INTDESC_NORMAL } }, //17 + { 1, INTTP_NA, {INTDESC_NORMAL } }, //18 + { 1, INTTP_NA, {INTDESC_NORMAL } }, //19 + { 1, INTTP_NA, {INTDESC_NORMAL } }, //20 + { 1, INTTP_NA, {INTDESC_NORMAL } }, //21 + { 1, INTTP_NA, {INTDESC_NORMAL } }, //22 + { 1, INTTP_NA, {INTDESC_NORMAL } }, //23 + { 1, INTTP_NA, {INTDESC_NORMAL } }, //24 + { 1, INTTP_NA, {INTDESC_NORMAL } }, //25 + { 1, INTTP_NA, {INTDESC_NORMAL } }, //26 + { 1, INTTP_NA, {INTDESC_NORMAL } }, //27 + { 1, INTTP_NA, {INTDESC_NORMAL } }, //28 + { 1, INTTP_NA, {INTDESC_NORMAL } }, //29 + { 1, INTTP_NA, {INTDESC_NORMAL } }, //30 + { 1, INTTP_NA, {INTDESC_NORMAL } }, //31 }; const int_desc_t *interrupt_controller_hal_desc_table(void) diff --git a/components/hal/esp32s2/include/hal/interrupt_controller_ll.h b/components/hal/esp32s2/include/hal/interrupt_controller_ll.h index 2e07c0ff00..2303f5e808 100644 --- a/components/hal/esp32s2/include/hal/interrupt_controller_ll.h +++ b/components/hal/esp32s2/include/hal/interrupt_controller_ll.h @@ -109,38 +109,6 @@ static inline void intr_cntrl_ll_edge_int_acknowledge (int intr) { xthal_set_intclear(1 << intr); } - -/** - * @brief Sets the interrupt level int the interrupt controller. - * - * @param interrupt_number Interrupt number 0 to 31 - * @param level priority between 1 (lowest) to 7 (highest) - */ -static inline void intr_cntrl_ll_set_int_level(int intr, int level) -{ - /* Not needed currently for xtensa platforms since the level is already set - * in interrupt table - */ - (void)intr; - (void)level; -} - -/** - * @brief Set the type of an interrupt in the controller. - * - * @param interrupt_number Interrupt number 0 to 31 - * @param type interrupt type as edge or level triggered - */ -static inline void intr_cntrl_ll_set_int_type(int intr, int_type_t type) -{ - /* Not needed currently for xtensa platforms since the type is already set - * in interrupt table - */ - (void)intr; - (void)type; -} - - #ifdef __cplusplus } #endif diff --git a/components/hal/esp32s3/include/hal/interrupt_controller_ll.h b/components/hal/esp32s3/include/hal/interrupt_controller_ll.h index d59fcc4d29..2303f5e808 100644 --- a/components/hal/esp32s3/include/hal/interrupt_controller_ll.h +++ b/components/hal/esp32s3/include/hal/interrupt_controller_ll.h @@ -109,37 +109,6 @@ static inline void intr_cntrl_ll_edge_int_acknowledge (int intr) { xthal_set_intclear(1 << intr); } - -/** - * @brief Sets the interrupt level int the interrupt controller. - * - * @param interrupt_number Interrupt number 0 to 31 - * @param level priority between 1 (lowest) to 7 (highest) - */ -static inline void intr_cntrl_ll_set_int_level(int intr, int level) -{ - /* Not needed currently for xtensa platforms since the level is already set - * in interrupt table - */ - (void)intr; - (void)level; -} - -/** - * @brief Set the type of an interrupt in the controller. - * - * @param interrupt_number Interrupt number 0 to 31 - * @param type interrupt type as edge or level triggered - */ -static inline void intr_cntrl_ll_set_int_type(int intr, int_type_t type) -{ - /* Not needed currently for xtensa platforms since the type is already set - * in interrupt table - */ - (void)intr; - (void)type; -} - #ifdef __cplusplus } #endif diff --git a/components/hal/include/hal/interrupt_controller_hal.h b/components/hal/include/hal/interrupt_controller_hal.h index dd0f615a1f..9c275a15b4 100644 --- a/components/hal/include/hal/interrupt_controller_hal.h +++ b/components/hal/include/hal/interrupt_controller_hal.h @@ -84,17 +84,6 @@ static inline int_type_t interrupt_controller_hal_get_type(int interrupt_number) return interrupt_controller_hal_desc_type(interrupt_number); } -/** - * @brief Set the type of an interrupt in the controller. - * - * @param interrupt_number Interrupt number 0 to 31 - * @param type interrupt type as edge or level triggered - */ -static inline void interrupt_controller_hal_set_int_type(int intr, int_type_t type) -{ - intr_cntrl_ll_set_int_type(intr, type); -} - /** * @brief Gets the interrupt level given an interrupt number. * @@ -106,6 +95,18 @@ static inline int interrupt_controller_hal_get_level(int interrupt_number) return interrupt_controller_hal_desc_level(interrupt_number); } +#ifdef SOC_CPU_HAS_FLEXIBLE_INTC +/** + * @brief Set the type of an interrupt in the controller. + * + * @param interrupt_number Interrupt number 0 to 31 + * @param type interrupt type as edge or level triggered + */ +static inline void interrupt_controller_hal_set_int_type(int intr, int_type_t type) +{ + intr_cntrl_ll_set_int_type(intr, type); +} + /** * @brief Sets the interrupt level int the interrupt controller. * @@ -116,6 +117,7 @@ static inline void interrupt_controller_hal_set_int_level(int intr, int level) { intr_cntrl_ll_set_int_level(intr, level); } +#endif /** * @brief Gets the cpu flags given the interrupt number and target cpu. diff --git a/components/hal/include/hal/interrupt_controller_types.h b/components/hal/include/hal/interrupt_controller_types.h index 9e36dc7361..528b0eb35d 100644 --- a/components/hal/include/hal/interrupt_controller_types.h +++ b/components/hal/include/hal/interrupt_controller_types.h @@ -30,7 +30,7 @@ typedef enum { typedef enum { INTTP_LEVEL=0, INTTP_EDGE, - INTTP_ANY, + INTTP_NA, } int_type_t; typedef struct { diff --git a/components/soc/esp32c3/include/soc/cpu_caps.h b/components/soc/esp32c3/include/soc/cpu_caps.h index e8692efc29..2d8a80bcfc 100644 --- a/components/soc/esp32c3/include/soc/cpu_caps.h +++ b/components/soc/esp32c3/include/soc/cpu_caps.h @@ -16,5 +16,6 @@ #define SOC_CPU_BREAKPOINTS_NUM 8 #define SOC_CPU_WATCHPOINTS_NUM 8 +#define SOC_CPU_HAS_FLEXIBLE_INTC 1 #define SOC_CPU_WATCHPOINT_SIZE 0x80000000 // bytes From 72e4655d4e2a56d7cf7a29c4c59df4ea68cad78e Mon Sep 17 00:00:00 2001 From: Felipe Neves Date: Fri, 25 Dec 2020 10:44:22 -0300 Subject: [PATCH 07/10] interrupt: removed descriptor table from esp32c3 interrupt hal. --- components/esp_common/src/int_wdt.c | 4 +- components/hal/CMakeLists.txt | 6 +- .../include/hal/interrupt_controller_ll.h | 8 +-- .../hal/esp32c3/interrupt_descriptor_table.c | 58 ------------------- .../include/hal/interrupt_controller_hal.h | 28 ++------- components/hal/interrupt_controller_hal.c | 26 ++++----- components/riscv/include/riscv/interrupt.h | 7 --- components/riscv/interrupt.c | 6 -- 8 files changed, 27 insertions(+), 116 deletions(-) delete mode 100644 components/hal/esp32c3/interrupt_descriptor_table.c diff --git a/components/esp_common/src/int_wdt.c b/components/esp_common/src/int_wdt.c index a2de13404d..f560437c40 100644 --- a/components/esp_common/src/int_wdt.c +++ b/components/esp_common/src/int_wdt.c @@ -126,11 +126,11 @@ void esp_int_wdt_cpu_init(void) /* Set the type and priority to cache error interrupts, if supported. */ #if SOC_INTERRUPT_TYPE_CAN_SET - interrupt_controller_hal_set_type(WDT_INT_NUM, INTR_TYPE_LEVEL); + interrupt_controller_hal_set_int_type(WDT_INT_NUM, INTR_TYPE_LEVEL); #endif #if SOC_INTERRUPT_LEVEL_CAN_SET - interrupt_controller_hal_set_level(WDT_INT_NUM, SOC_INTERRUPT_LEVEL_MEDIUM); + interrupt_controller_hal_set_int_level(WDT_INT_NUM, SOC_INTERRUPT_LEVEL_MEDIUM); #endif #if CONFIG_ESP32_ECO3_CACHE_LOCK_FIX diff --git a/components/hal/CMakeLists.txt b/components/hal/CMakeLists.txt index e43a4c44f8..57f07b3063 100644 --- a/components/hal/CMakeLists.txt +++ b/components/hal/CMakeLists.txt @@ -28,8 +28,7 @@ if(NOT BOOTLOADER_BUILD) "soc_hal.c" "interrupt_controller_hal.c" "sha_hal.c" - "aes_hal.c" - "${target}/interrupt_descriptor_table.c") + "aes_hal.c") if(${target} STREQUAL "esp32") list(APPEND srcs @@ -43,6 +42,7 @@ if(NOT BOOTLOADER_BUILD) "twai_hal_iram.c" "esp32/adc_hal.c" "esp32/brownout_hal.c" + "esp32/interrupt_descriptor_table.c" "esp32/touch_sensor_hal.c") if(NOT BOOTLOADER_BUILD AND CONFIG_ETH_USE_ESP32_EMAC) list(APPEND srcs "esp32/emac_hal.c") @@ -65,6 +65,7 @@ if(NOT BOOTLOADER_BUILD) "esp32s2/systimer_hal.c" "esp32s2/touch_sensor_hal.c" "esp32s2/dac_hal.c" + "esp32s2/interrupt_descriptor_table.c" "esp32s2/usb_hal.c") endif() @@ -79,6 +80,7 @@ if(NOT BOOTLOADER_BUILD) "twai_hal.c" "twai_hal_iram.c" "esp32s3/brownout_hal.c" + "esp32s3/interrupt_descriptor_table.c" "esp32s3/systimer_hal.c" "esp32s3/touch_sensor_hal.c") endif() diff --git a/components/hal/esp32c3/include/hal/interrupt_controller_ll.h b/components/hal/esp32c3/include/hal/interrupt_controller_ll.h index ca47c3a16f..42a6385f61 100644 --- a/components/hal/esp32c3/include/hal/interrupt_controller_ll.h +++ b/components/hal/esp32c3/include/hal/interrupt_controller_ll.h @@ -117,17 +117,17 @@ static inline void intr_cntrl_ll_enable_int_mask(uint32_t newmask) /** * @brief Acknowledge an edge-trigger interrupt by clearing its pending flag - * + * * @param intr interrupt number ranged from 0 to 31 */ static inline void intr_cntrl_ll_edge_int_acknowledge (int intr) { - esprv_intc_set_interrupt_clear(intr); + REG_SET_BIT(INTERRUPT_CORE0_CPU_INT_CLEAR_REG, intr); } /** * @brief Sets the interrupt level int the interrupt controller. - * + * * @param interrupt_number Interrupt number 0 to 31 * @param level priority between 1 (lowest) to 7 (highest) */ @@ -138,7 +138,7 @@ static inline void intr_cntrl_ll_set_int_level(int intr, int level) /** * @brief Set the type of an interrupt in the controller. - * + * * @param interrupt_number Interrupt number 0 to 31 * @param type interrupt type as edge or level triggered */ diff --git a/components/hal/esp32c3/interrupt_descriptor_table.c b/components/hal/esp32c3/interrupt_descriptor_table.c deleted file mode 100644 index ca2ea05641..0000000000 --- a/components/hal/esp32c3/interrupt_descriptor_table.c +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright 2020 Espressif Systems (Shanghai) PTE LTD -// -// 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 - -// 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 "sdkconfig.h" -#include "hal/interrupt_controller_hal.h" -#include "soc/soc_caps.h" -#include "soc/soc.h" - -//This is basically a software-readable version of the interrupt usage table in include/soc/soc.h -const int_desc_t interrupt_descriptor_table[32] = { - { 1, INTTP_NA, {INTDESC_RESVD } }, //0 - { 1, INTTP_NA, {INTDESC_SPECIAL } }, //1 - { 1, INTTP_NA, {INTDESC_NORMAL } }, //2 - { 1, INTTP_NA, {INTDESC_NORMAL } }, //3 - { 1, INTTP_NA, {INTDESC_NORMAL } }, //4 - { 1, INTTP_NA, {INTDESC_SPECIAL } }, //5 - { 1, INTTP_NA, {INTDESC_NORMAL } }, //6 - { 1, INTTP_NA, {INTDESC_NORMAL } }, //7 - { 1, INTTP_NA, {INTDESC_SPECIAL } }, //8 - { 1, INTTP_NA, {INTDESC_SPECIAL } }, //9 - { 1, INTTP_NA, {INTDESC_NORMAL } }, //10 - { 1, INTTP_NA, {INTDESC_NORMAL } }, //11 - { 1, INTTP_NA, {INTDESC_SPECIAL } }, //12 - { 1, INTTP_NA, {INTDESC_NORMAL } }, //13 - { 1, INTTP_NA, {INTDESC_NORMAL } }, //14 - { 1, INTTP_NA, {INTDESC_NORMAL } }, //15 - { 1, INTTP_NA, {INTDESC_NORMAL } }, //16 - { 1, INTTP_NA, {INTDESC_NORMAL } }, //17 - { 1, INTTP_NA, {INTDESC_NORMAL } }, //18 - { 1, INTTP_NA, {INTDESC_NORMAL } }, //19 - { 1, INTTP_NA, {INTDESC_NORMAL } }, //20 - { 1, INTTP_NA, {INTDESC_NORMAL } }, //21 - { 1, INTTP_NA, {INTDESC_NORMAL } }, //22 - { 1, INTTP_NA, {INTDESC_NORMAL } }, //23 - { 1, INTTP_NA, {INTDESC_NORMAL } }, //24 - { 1, INTTP_NA, {INTDESC_NORMAL } }, //25 - { 1, INTTP_NA, {INTDESC_NORMAL } }, //26 - { 1, INTTP_NA, {INTDESC_NORMAL } }, //27 - { 1, INTTP_NA, {INTDESC_NORMAL } }, //28 - { 1, INTTP_NA, {INTDESC_NORMAL } }, //29 - { 1, INTTP_NA, {INTDESC_NORMAL } }, //30 - { 1, INTTP_NA, {INTDESC_NORMAL } }, //31 -}; - -const int_desc_t *interrupt_controller_hal_desc_table(void) -{ - return interrupt_descriptor_table; -} diff --git a/components/hal/include/hal/interrupt_controller_hal.h b/components/hal/include/hal/interrupt_controller_hal.h index 9c275a15b4..a7c47e6a5c 100644 --- a/components/hal/include/hal/interrupt_controller_hal.h +++ b/components/hal/include/hal/interrupt_controller_hal.h @@ -23,12 +23,14 @@ extern "C" { #endif +#ifndef SOC_CPU_HAS_FLEXIBLE_INTC /** * @brief Gets target platform interrupt descriptor table * * @return Address of interrupt descriptor table */ __attribute__((pure)) const int_desc_t *interrupt_controller_hal_desc_table(void); +#endif /** * @brief Gets the interrupt type given an interrupt number. @@ -55,24 +57,6 @@ __attribute__((pure)) int interrupt_controller_hal_desc_level(int interrupt_num */ __attribute__((pure)) int_desc_flag_t interrupt_controller_hal_desc_flags(int interrupt_number, int cpu_number); -#if SOC_INTERRUPT_LEVEL_CAN_SET -/** - * @brief Set the interrupt level given an interrupt number. - * - * @param interrupt_number number of the interrupt - * @param level new level for this interrupt - */ -void interrupt_controller_hal_set_level(int interrupt_number, int level); - -/** - * @brief Set the interrupt type given an interrupt number. - * - * @param interrupt_number number of the interrupt - * @param type new type for this interrupt - */ -void interrupt_controller_hal_set_type(int interrupt_number, int_type_t type); -#endif - /** * @brief Gets the interrupt type given an interrupt number. * @@ -98,7 +82,7 @@ static inline int interrupt_controller_hal_get_level(int interrupt_number) #ifdef SOC_CPU_HAS_FLEXIBLE_INTC /** * @brief Set the type of an interrupt in the controller. - * + * * @param interrupt_number Interrupt number 0 to 31 * @param type interrupt type as edge or level triggered */ @@ -109,7 +93,7 @@ static inline void interrupt_controller_hal_set_int_type(int intr, int_type_t ty /** * @brief Sets the interrupt level int the interrupt controller. - * + * * @param interrupt_number Interrupt number 0 to 31 * @param level priority between 1 (lowest) to 7 (highest) */ @@ -210,10 +194,10 @@ static inline void interrupt_controller_hal_enable_int_mask(uint32_t newmask) /** * @brief Acknowledge an edge-trigger interrupt by clearing its pending flag - * + * * @param intr interrupt number ranged from 0 to 31 */ -static inline void interrupt_controller_hal_edge_int_acknowledge(int intr) +static inline void interrupt_controller_hal_edge_int_acknowledge(int intr) { intr_cntrl_ll_edge_int_acknowledge(intr); } diff --git a/components/hal/interrupt_controller_hal.c b/components/hal/interrupt_controller_hal.c index 0c2d2dae97..f3c5728301 100644 --- a/components/hal/interrupt_controller_hal.c +++ b/components/hal/interrupt_controller_hal.c @@ -16,34 +16,30 @@ int_type_t interrupt_controller_hal_desc_type(int interrupt_number) { +#ifndef SOC_CPU_HAS_FLEXIBLE_INTC const int_desc_t *int_desc = interrupt_controller_hal_desc_table(); return(int_desc[interrupt_number].type); +#else + return (INTTP_NA); +#endif } int interrupt_controller_hal_desc_level(int interrupt_number) { +#ifndef SOC_CPU_HAS_FLEXIBLE_INTC const int_desc_t *int_desc = interrupt_controller_hal_desc_table(); return(int_desc[interrupt_number].level); +#else + return 1; +#endif } int_desc_flag_t interrupt_controller_hal_desc_flags(int interrupt_number, int cpu_number) { +#ifndef SOC_CPU_HAS_FLEXIBLE_INTC const int_desc_t *int_desc = interrupt_controller_hal_desc_table(); return(int_desc[interrupt_number].cpuflags[cpu_number]); -} - -#if SOC_INTERRUPT_LEVEL_CAN_SET - -void interrupt_controller_hal_set_level(int interrupt_number, int level) { - intr_cntrl_ll_set_level(interrupt_number, level); -} - +#else + return INTDESC_NORMAL; #endif - -#if SOC_INTERRUPT_TYPE_CAN_SET - -void interrupt_controller_hal_set_type(int interrupt_number, int_type_t type) { - intr_cntrl_ll_set_type(interrupt_number, type); } - -#endif diff --git a/components/riscv/include/riscv/interrupt.h b/components/riscv/include/riscv/interrupt.h index ed87384c17..6498d57f2f 100644 --- a/components/riscv/include/riscv/interrupt.h +++ b/components/riscv/include/riscv/interrupt.h @@ -110,13 +110,6 @@ void esprv_intc_set_threshold(int priority_threshold); */ uint32_t esprv_intc_get_interrupt_unmask(void); -/** - * @brief Set a bit in int clear register - * @param intr bit to set from 0 to 31 - * @return none - */ -void esprv_intc_set_interrupt_clear(int intr); - #ifdef __cplusplus } #endif diff --git a/components/riscv/interrupt.c b/components/riscv/interrupt.c index 3be259be89..1b48bfdf89 100644 --- a/components/riscv/interrupt.c +++ b/components/riscv/interrupt.c @@ -89,12 +89,6 @@ uint32_t esprv_intc_get_interrupt_unmask(void) return REG_READ(INTERRUPT_CORE0_CPU_INT_ENABLE_REG); } -void esprv_intc_set_interrupt_clear(int intr) -{ - REG_SET_BIT(INTERRUPT_CORE0_CPU_INT_CLEAR_REG, intr); -} - - /*************************** Exception names. Used in .gdbinit file. ***************************/ const char *riscv_excp_names[16] __attribute__((used)) = { From 9e7d2c0065872f6be2cceedf3ec8d62072fe83a6 Mon Sep 17 00:00:00 2001 From: morris Date: Tue, 29 Dec 2020 12:31:54 +0800 Subject: [PATCH 08/10] esp32c3: format and clean up interrupt and os port code --- components/esp_common/src/int_wdt.c | 62 +++++++++--------- .../esp_system/include/esp_intr_alloc.h | 64 ++++++++++--------- components/esp_system/intr_alloc.c | 25 ++++---- components/freertos/port/riscv/port.c | 21 +++--- components/freertos/port/riscv/portasm.S | 10 +-- .../include/hal/interrupt_controller_ll.h | 8 +-- .../include/hal/interrupt_controller_ll.h | 8 +-- .../include/hal/interrupt_controller_ll.h | 6 +- .../include/hal/interrupt_controller_ll.h | 6 +- .../riscv/expression_with_stack_riscv_asm.S | 8 +-- components/riscv/vectors.S | 2 +- components/soc/esp32c3/include/soc/soc_caps.h | 1 - 12 files changed, 111 insertions(+), 110 deletions(-) diff --git a/components/esp_common/src/int_wdt.c b/components/esp_common/src/int_wdt.c index f560437c40..da2f880cc1 100644 --- a/components/esp_common/src/int_wdt.c +++ b/components/esp_common/src/int_wdt.c @@ -1,9 +1,9 @@ -// Copyright 2015-2018 Espressif Systems (Shanghai) PTE LTD +// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD // // 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 - +// // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software @@ -12,14 +12,14 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "sdkconfig.h" #include #include #include #include +#include "sdkconfig.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" -#include +#include "esp_types.h" #include "esp_err.h" #include "esp_intr_alloc.h" #include "esp_attr.h" @@ -29,6 +29,7 @@ #include "driver/periph_ctrl.h" #include "esp_int_wdt.h" #include "esp_private/system_internal.h" +#include "hal/cpu_hal.h" #include "hal/timer_types.h" #include "hal/wdt_hal.h" #include "hal/interrupt_controller_hal.h" @@ -45,7 +46,7 @@ static wdt_hal_context_t iwdt_context; #if CONFIG_ESP32_ECO3_CACHE_LOCK_FIX /* - * This parameter is indicates the response time of Interrupt watchdog to + * This parameter is used to indicate the response time of Interrupt watchdog to * identify the live lock. */ #define IWDT_LIVELOCK_TIMEOUT_MS (20) @@ -58,8 +59,9 @@ extern uint32_t _l4_intr_livelock_counter, _l4_intr_livelock_max; //Not static; the ISR assembly checks this. bool int_wdt_app_cpu_ticked = false; -static void IRAM_ATTR tick_hook(void) { - if (xPortGetCoreID()!=0) { +static void IRAM_ATTR tick_hook(void) +{ + if (cpu_hal_get_core_id() != 0) { int_wdt_app_cpu_ticked = true; } else { //Only feed wdt if app cpu also ticked. @@ -70,11 +72,11 @@ static void IRAM_ATTR tick_hook(void) { #if CONFIG_ESP32_ECO3_CACHE_LOCK_FIX _l4_intr_livelock_counter = 0; wdt_hal_config_stage(&iwdt_context, WDT_STAGE0, - CONFIG_ESP_INT_WDT_TIMEOUT_MS*1000/IWDT_TICKS_PER_US/(_l4_intr_livelock_max+1), WDT_STAGE_ACTION_INT); //Set timeout before interrupt + CONFIG_ESP_INT_WDT_TIMEOUT_MS * 1000 / IWDT_TICKS_PER_US / (_l4_intr_livelock_max + 1), WDT_STAGE_ACTION_INT); //Set timeout before interrupt #else - wdt_hal_config_stage(&iwdt_context, WDT_STAGE0, CONFIG_ESP_INT_WDT_TIMEOUT_MS*1000/IWDT_TICKS_PER_US, WDT_STAGE_ACTION_INT); //Set timeout before interrupt + wdt_hal_config_stage(&iwdt_context, WDT_STAGE0, CONFIG_ESP_INT_WDT_TIMEOUT_MS * 1000 / IWDT_TICKS_PER_US, WDT_STAGE_ACTION_INT); //Set timeout before interrupt #endif - wdt_hal_config_stage(&iwdt_context, WDT_STAGE1, 2*CONFIG_ESP_INT_WDT_TIMEOUT_MS*1000/IWDT_TICKS_PER_US, WDT_STAGE_ACTION_RESET_SYSTEM); //Set timeout before reset + wdt_hal_config_stage(&iwdt_context, WDT_STAGE1, 2 * CONFIG_ESP_INT_WDT_TIMEOUT_MS * 1000 / IWDT_TICKS_PER_US, WDT_STAGE_ACTION_RESET_SYSTEM); //Set timeout before reset wdt_hal_feed(&iwdt_context); wdt_hal_write_protect_enable(&iwdt_context); int_wdt_app_cpu_ticked = false; @@ -82,32 +84,31 @@ static void IRAM_ATTR tick_hook(void) { } } #else -static void IRAM_ATTR tick_hook(void) { +static void IRAM_ATTR tick_hook(void) +{ #if !CONFIG_FREERTOS_UNICORE - if (xPortGetCoreID()!=0) { + if (cpu_hal_get_core_id() != 0) { return; } #endif //Todo: Check if there's a way to avoid reconfiguring the stages on each feed. wdt_hal_write_protect_disable(&iwdt_context); //Reconfigure stage timeouts - wdt_hal_config_stage(&iwdt_context, WDT_STAGE0, CONFIG_ESP_INT_WDT_TIMEOUT_MS*1000/IWDT_TICKS_PER_US, WDT_STAGE_ACTION_INT); //Set timeout before interrupt - wdt_hal_config_stage(&iwdt_context, WDT_STAGE1, 2*CONFIG_ESP_INT_WDT_TIMEOUT_MS*1000/IWDT_TICKS_PER_US, WDT_STAGE_ACTION_RESET_SYSTEM); //Set timeout before reset + wdt_hal_config_stage(&iwdt_context, WDT_STAGE0, CONFIG_ESP_INT_WDT_TIMEOUT_MS * 1000 / IWDT_TICKS_PER_US, WDT_STAGE_ACTION_INT); //Set timeout before interrupt + wdt_hal_config_stage(&iwdt_context, WDT_STAGE1, 2 * CONFIG_ESP_INT_WDT_TIMEOUT_MS * 1000 / IWDT_TICKS_PER_US, WDT_STAGE_ACTION_RESET_SYSTEM); //Set timeout before reset wdt_hal_feed(&iwdt_context); wdt_hal_write_protect_enable(&iwdt_context); } #endif -void esp_int_wdt_init(void) { +void esp_int_wdt_init(void) +{ periph_module_enable(PERIPH_TIMG1_MODULE); //The timer configs initially are set to 5 seconds, to make sure the CPU can start up. The tick hook sets //it to their actual value. wdt_hal_init(&iwdt_context, IWDT_INSTANCE, IWDT_PRESCALER, true); wdt_hal_write_protect_disable(&iwdt_context); - //The timer configs initially are set to 5 seconds, to make sure the CPU can start up. The tick hook sets - //it to their actual value. - //1st stage timeout: interrupt wdt_hal_config_stage(&iwdt_context, WDT_STAGE0, IWDT_INITIAL_TIMEOUT_S * 1000000 / IWDT_TICKS_PER_US, WDT_STAGE_ACTION_INT); //2nd stage timeout: reset system @@ -119,17 +120,14 @@ void esp_int_wdt_init(void) { void esp_int_wdt_cpu_init(void) { - assert((CONFIG_ESP_INT_WDT_TIMEOUT_MS >= (portTICK_PERIOD_MS<<1)) && "Interrupt watchdog timeout needs to meet twice the RTOS tick period!"); - esp_register_freertos_tick_hook_for_cpu(tick_hook, xPortGetCoreID()); + assert((CONFIG_ESP_INT_WDT_TIMEOUT_MS >= (portTICK_PERIOD_MS << 1)) && "Interrupt watchdog timeout needs to meet twice the RTOS tick period!"); + esp_register_freertos_tick_hook_for_cpu(tick_hook, cpu_hal_get_core_id()); ESP_INTR_DISABLE(WDT_INT_NUM); - intr_matrix_set(xPortGetCoreID(), ETS_TG1_WDT_LEVEL_INTR_SOURCE, WDT_INT_NUM); + intr_matrix_set(cpu_hal_get_core_id(), ETS_TG1_WDT_LEVEL_INTR_SOURCE, WDT_INT_NUM); - /* Set the type and priority to cache error interrupts, if supported. */ -#if SOC_INTERRUPT_TYPE_CAN_SET + /* Set the type and priority to watch dog interrupts */ +#if SOC_CPU_HAS_FLEXIBLE_INTC interrupt_controller_hal_set_int_type(WDT_INT_NUM, INTR_TYPE_LEVEL); -#endif - -#if SOC_INTERRUPT_LEVEL_CAN_SET interrupt_controller_hal_set_int_level(WDT_INT_NUM, SOC_INTERRUPT_LEVEL_MEDIUM); #endif @@ -140,15 +138,15 @@ void esp_int_wdt_cpu_init(void) */ _l4_intr_livelock_counter = 0; if (soc_has_cache_lock_bug()) { - assert((portTICK_PERIOD_MS<<1) <= IWDT_LIVELOCK_TIMEOUT_MS); - assert(CONFIG_ESP_INT_WDT_TIMEOUT_MS >= (IWDT_LIVELOCK_TIMEOUT_MS*3)); - _l4_intr_livelock_max = CONFIG_ESP_INT_WDT_TIMEOUT_MS/IWDT_LIVELOCK_TIMEOUT_MS - 1; + assert((portTICK_PERIOD_MS << 1) <= IWDT_LIVELOCK_TIMEOUT_MS); + assert(CONFIG_ESP_INT_WDT_TIMEOUT_MS >= (IWDT_LIVELOCK_TIMEOUT_MS * 3)); + _l4_intr_livelock_max = CONFIG_ESP_INT_WDT_TIMEOUT_MS / IWDT_LIVELOCK_TIMEOUT_MS - 1; } #endif - //We do not register a handler for the interrupt because it is interrupt level 4 which - //is not servicable from C. Instead, xtensa_vectors.S has a call to the panic handler for - //this interrupt. + // We do not register a handler for the watchdog interrupt because: + // 1. Interrupt level 4 on Xtensa architecture is not servicable from C + // 2. Instead, we set the entry of watchdog interrupt to the panic handler, see riscv/vector.S and xtensa_vectors.S ESP_INTR_ENABLE(WDT_INT_NUM); } diff --git a/components/esp_system/include/esp_intr_alloc.h b/components/esp_system/include/esp_intr_alloc.h index 6c9963c176..33f70b9597 100644 --- a/components/esp_system/include/esp_intr_alloc.h +++ b/components/esp_system/include/esp_intr_alloc.h @@ -1,4 +1,4 @@ -// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,8 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#ifndef __ESP_INTR_ALLOC_H__ -#define __ESP_INTR_ALLOC_H__ +#pragma once #include #include @@ -37,24 +36,24 @@ extern "C" { */ //Keep the LEVELx values as they are here; they match up with (1<> 1) + 1; +} + /**@}*/ #ifdef __cplusplus } #endif - -#endif diff --git a/components/esp_system/intr_alloc.c b/components/esp_system/intr_alloc.c index 4e88cc8698..9327b0ff8c 100644 --- a/components/esp_system/intr_alloc.c +++ b/components/esp_system/intr_alloc.c @@ -1,9 +1,9 @@ -// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD // // 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 - +// // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software @@ -12,7 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "sdkconfig.h" #include #include #include @@ -21,6 +20,7 @@ #include #include #include +#include "sdkconfig.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "esp_err.h" @@ -48,7 +48,8 @@ Define this to debug the choices made when allocating the interrupt. This leads 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. */ -//#define DEBUG_INT_ALLOC_DECISIONS +// #define DEBUG_INT_ALLOC_DECISIONS + #ifdef DEBUG_INT_ALLOC_DECISIONS # define ALCHLOG(...) ESP_EARLY_LOGD(TAG, __VA_ARGS__) #else @@ -240,13 +241,14 @@ static bool is_vect_desc_usable(vector_desc_t *vd, int flags, int cpu, int force #ifndef SOC_CPU_HAS_FLEXIBLE_INTC //Check if the interrupt level is acceptable - if (!(flags&(1<source=source; } @@ -587,14 +589,13 @@ esp_err_t esp_intr_alloc_intrstatus(int source, int flags, uint32_t intrstatusre #ifdef SOC_CPU_HAS_FLEXIBLE_INTC //Extract the level from the interrupt passed flags - int level = (__builtin_ffs((flags >> 1) & ESP_INTR_FLAG_LEVELMASK)) + 1; - - interrupt_controller_hal_set_int_level(intr,level); + int level = esp_intr_flags_to_level(flags); + interrupt_controller_hal_set_int_level(intr, level); if (flags & ESP_INTR_FLAG_EDGE) { - interrupt_controller_hal_set_int_type(intr,INTTP_EDGE); + interrupt_controller_hal_set_int_type(intr, INTTP_EDGE); } else { - interrupt_controller_hal_set_int_type(intr,INTTP_LEVEL); + interrupt_controller_hal_set_int_type(intr, INTTP_LEVEL); } #endif diff --git a/components/freertos/port/riscv/port.c b/components/freertos/port/riscv/port.c index 4e29cb6494..a2256b9add 100644 --- a/components/freertos/port/riscv/port.c +++ b/components/freertos/port/riscv/port.c @@ -102,7 +102,7 @@ * to ensure interrupts don't inadvertently become unmasked before the scheduler starts. * As it is stored as part of the task context it will automatically be set to 0 when the first task is started. */ -static UBaseType_t uxCriticalNesting = 0; +static UBaseType_t uxCriticalNesting = 0; static UBaseType_t uxSavedInterruptState = 0; BaseType_t uxSchedulerRunning = 0; UBaseType_t uxInterruptNesting = 0; @@ -124,7 +124,6 @@ void vPortEnterCritical(void) uxCriticalNesting++; if (uxCriticalNesting == 1) { - //portDISABLE_INTERRUPTS(); uxSavedInterruptState = state; } } @@ -135,7 +134,6 @@ void vPortExitCritical(void) uxCriticalNesting--; if (uxCriticalNesting == 0) { portEXIT_CRITICAL_NESTED(uxSavedInterruptState); - //portENABLE_INTERRUPTS(); } } } @@ -169,8 +167,7 @@ void prvTaskExitError(void) defined, then stop here so application writers can catch the error. */ configASSERT(uxCriticalNesting == ~0UL); portDISABLE_INTERRUPTS(); - for (;;) - ; + abort(); } /* Clear current interrupt mask and set given mask */ @@ -227,16 +224,16 @@ IRAM_ATTR void vPortSysTickHandler(void *arg) } BaseType_t xPortStartScheduler(void) -{ +{ uxInterruptNesting = 0; uxCriticalNesting = 0; - uxSchedulerRunning = 0; + uxSchedulerRunning = 0; vPortSetupTimer(); esprv_intc_int_set_threshold(1); /* set global INTC masking level */ riscv_global_interrupts_enable(); - + vPortYield(); /*Should not get here*/ @@ -251,7 +248,7 @@ void vPortEndScheduler(void) void vPortYieldOtherCore(BaseType_t coreid) { - esp_crosscore_int_send_yield(coreid); + esp_crosscore_int_send_yield(coreid); } void vPortYieldFromISR( void ) @@ -266,7 +263,7 @@ void vPortYield(void) vPortYieldFromISR(); } else { - esp_crosscore_int_send_yield(0); + esp_crosscore_int_send_yield(0); /* There are 3-4 instructions of latency between triggering the software interrupt and the CPU interrupt happening. Make sure it happened before we return, otherwise vTaskDelay() may return and execute 1-2 @@ -277,7 +274,7 @@ void vPortYield(void) for an instant yield, and if that happens then the WFI would be waiting for the next interrupt to occur...) */ - while(uxSchedulerRunning && uxCriticalNesting == 0 && REG_READ(SYSTEM_CPU_INTR_FROM_CPU_0_REG) != 0) { } + while (uxSchedulerRunning && uxCriticalNesting == 0 && REG_READ(SYSTEM_CPU_INTR_FROM_CPU_0_REG) != 0) {} } } @@ -295,7 +292,7 @@ BaseType_t xPortInIsrContext(void) BaseType_t IRAM_ATTR xPortInterruptedFromISRContext(void) { /* For single core, this can be the same as xPortInIsrContext() because reading it is atomic */ - return uxInterruptNesting; + return uxInterruptNesting; } diff --git a/components/freertos/port/riscv/portasm.S b/components/freertos/port/riscv/portasm.S index 3f4740299b..d32103f5f8 100644 --- a/components/freertos/port/riscv/portasm.S +++ b/components/freertos/port/riscv/portasm.S @@ -36,7 +36,7 @@ rtos_int_enter: mv t2, a0 /* scheduler not enabled, jump directly to ISR handler */ - lw t0, uxSchedulerRunning + lw t0, uxSchedulerRunning beq t0,zero, rtos_enter_end /* increments the ISR nesting count */ @@ -44,7 +44,7 @@ rtos_int_enter: lw t4, 0x0(t3) addi t5,t4,1 sw t5, 0x0(t3) - + /* If reached here from another low-prio ISR, skip stack pushing to TCB */ bne t4,zero, rtos_enter_end @@ -66,8 +66,8 @@ rtos_enter_end: .type rtos_int_exit, @function rtos_int_exit: /* may skip RTOS aware interrupt since scheduler was not started */ - lw t0, uxSchedulerRunning - beq t0,zero, rtos_exit_end + lw t0, uxSchedulerRunning + beq t0,zero, rtos_exit_end /* update nesting interrupts counter */ la t2, uxInterruptNesting @@ -81,7 +81,7 @@ rtos_int_exit: isr_skip_decrement: /* may still have interrupts pending, skip section below and exit */ - bne t3,zero,rtos_exit_end + bne t3,zero,rtos_exit_end /* Schedule the next task if a yield is pending */ la t0, xPortSwitchFlag diff --git a/components/hal/esp32/include/hal/interrupt_controller_ll.h b/components/hal/esp32/include/hal/interrupt_controller_ll.h index f450f2c6c1..6634b003c4 100644 --- a/components/hal/esp32/include/hal/interrupt_controller_ll.h +++ b/components/hal/esp32/include/hal/interrupt_controller_ll.h @@ -62,7 +62,7 @@ static inline bool intr_cntrl_ll_has_handler(uint8_t intr, uint8_t cpu) * @param handler handler invoked when an interrupt occurs * @param arg optional argument to pass to the handler */ -static inline void intr_cntrl_ll_set_int_handler(uint8_t intr, interrupt_handler_t handler, void * arg) +static inline void intr_cntrl_ll_set_int_handler(uint8_t intr, interrupt_handler_t handler, void *arg) { xt_set_interrupt_handler(intr, (xt_handler)handler, arg); } @@ -74,7 +74,7 @@ static inline void intr_cntrl_ll_set_int_handler(uint8_t intr, interrupt_handler * * @return argument used by handler of passed interrupt number */ -static inline void * intr_cntrl_ll_get_int_handler_arg(uint8_t intr) +static inline void *intr_cntrl_ll_get_int_handler_arg(uint8_t intr) { return xt_get_interrupt_handler_arg(intr); } @@ -102,10 +102,10 @@ static inline void intr_cntrl_ll_enable_int_mask(uint32_t newmask) /** * @brief Acknowledge an edge-trigger interrupt by clearing its pending flag - * + * * @param intr interrupt number ranged from 0 to 31 */ -static inline void intr_cntrl_ll_edge_int_acknowledge (int intr) +static inline void intr_cntrl_ll_edge_int_acknowledge(int intr) { xthal_set_intclear(1 << intr); } diff --git a/components/hal/esp32c3/include/hal/interrupt_controller_ll.h b/components/hal/esp32c3/include/hal/interrupt_controller_ll.h index 42a6385f61..1957e0384b 100644 --- a/components/hal/esp32c3/include/hal/interrupt_controller_ll.h +++ b/components/hal/esp32c3/include/hal/interrupt_controller_ll.h @@ -68,7 +68,7 @@ static inline bool intr_cntrl_ll_has_handler(uint8_t intr, uint8_t cpu) * @param handler handler invoked when an interrupt occurs * @param arg optional argument to pass to the handler */ -static inline void intr_cntrl_ll_set_int_handler(uint8_t intr, interrupt_handler_t handler, void * arg) +static inline void intr_cntrl_ll_set_int_handler(uint8_t intr, interrupt_handler_t handler, void *arg) { intr_handler_set(intr, (void *)handler, arg); } @@ -80,7 +80,7 @@ static inline void intr_cntrl_ll_set_int_handler(uint8_t intr, interrupt_handler * * @return argument used by handler of passed interrupt number */ -static inline void * intr_cntrl_ll_get_int_handler_arg(uint8_t intr) +static inline void *intr_cntrl_ll_get_int_handler_arg(uint8_t intr) { return intr_handler_get_arg(intr); } @@ -120,9 +120,9 @@ static inline void intr_cntrl_ll_enable_int_mask(uint32_t newmask) * * @param intr interrupt number ranged from 0 to 31 */ -static inline void intr_cntrl_ll_edge_int_acknowledge (int intr) +static inline void intr_cntrl_ll_edge_int_acknowledge(int intr) { - REG_SET_BIT(INTERRUPT_CORE0_CPU_INT_CLEAR_REG, intr); + REG_SET_BIT(INTERRUPT_CORE0_CPU_INT_CLEAR_REG, intr); } /** diff --git a/components/hal/esp32s2/include/hal/interrupt_controller_ll.h b/components/hal/esp32s2/include/hal/interrupt_controller_ll.h index 2303f5e808..5c270ec66e 100644 --- a/components/hal/esp32s2/include/hal/interrupt_controller_ll.h +++ b/components/hal/esp32s2/include/hal/interrupt_controller_ll.h @@ -62,7 +62,7 @@ static inline bool intr_cntrl_ll_has_handler(uint8_t intr, uint8_t cpu) * @param handler handler invoked when an interrupt occurs * @param arg optional argument to pass to the handler */ -static inline void intr_cntrl_ll_set_int_handler(uint8_t intr, interrupt_handler_t handler, void * arg) +static inline void intr_cntrl_ll_set_int_handler(uint8_t intr, interrupt_handler_t handler, void *arg) { xt_set_interrupt_handler(intr, (xt_handler)handler, arg); } @@ -74,7 +74,7 @@ static inline void intr_cntrl_ll_set_int_handler(uint8_t intr, interrupt_handler * * @return argument used by handler of passed interrupt number */ -static inline void * intr_cntrl_ll_get_int_handler_arg(uint8_t intr) +static inline void *intr_cntrl_ll_get_int_handler_arg(uint8_t intr) { return xt_get_interrupt_handler_arg(intr); } @@ -102,7 +102,7 @@ static inline void intr_cntrl_ll_enable_int_mask(uint32_t newmask) /** * @brief Acknowledge an edge-trigger interrupt by clearing its pending flag - * + * * @param intr interrupt number ranged from 0 to 31 */ static inline void intr_cntrl_ll_edge_int_acknowledge (int intr) diff --git a/components/hal/esp32s3/include/hal/interrupt_controller_ll.h b/components/hal/esp32s3/include/hal/interrupt_controller_ll.h index 2303f5e808..5c270ec66e 100644 --- a/components/hal/esp32s3/include/hal/interrupt_controller_ll.h +++ b/components/hal/esp32s3/include/hal/interrupt_controller_ll.h @@ -62,7 +62,7 @@ static inline bool intr_cntrl_ll_has_handler(uint8_t intr, uint8_t cpu) * @param handler handler invoked when an interrupt occurs * @param arg optional argument to pass to the handler */ -static inline void intr_cntrl_ll_set_int_handler(uint8_t intr, interrupt_handler_t handler, void * arg) +static inline void intr_cntrl_ll_set_int_handler(uint8_t intr, interrupt_handler_t handler, void *arg) { xt_set_interrupt_handler(intr, (xt_handler)handler, arg); } @@ -74,7 +74,7 @@ static inline void intr_cntrl_ll_set_int_handler(uint8_t intr, interrupt_handler * * @return argument used by handler of passed interrupt number */ -static inline void * intr_cntrl_ll_get_int_handler_arg(uint8_t intr) +static inline void *intr_cntrl_ll_get_int_handler_arg(uint8_t intr) { return xt_get_interrupt_handler_arg(intr); } @@ -102,7 +102,7 @@ static inline void intr_cntrl_ll_enable_int_mask(uint32_t newmask) /** * @brief Acknowledge an edge-trigger interrupt by clearing its pending flag - * + * * @param intr interrupt number ranged from 0 to 31 */ static inline void intr_cntrl_ll_edge_int_acknowledge (int intr) diff --git a/components/riscv/expression_with_stack_riscv_asm.S b/components/riscv/expression_with_stack_riscv_asm.S index 99b0ec5840..44ca865315 100644 --- a/components/riscv/expression_with_stack_riscv_asm.S +++ b/components/riscv/expression_with_stack_riscv_asm.S @@ -23,7 +23,7 @@ esp_shared_stack_invoke_function: /* Set shared stack as new stack pointer */ mv sp, a1 - + /* store the ra and previous stack pointer in a safe place */ addi sp,sp,-4 sw t0, 0(sp) @@ -33,11 +33,11 @@ esp_shared_stack_invoke_function: jalr a0, 0 /* gets the ra and stack pointer saved previously */ - lw t0, 0(sp) + lw t0, 0(sp) lw t1, 4(sp) addi sp, sp, 4 - + /* restore both ra and real stack pointer of current task */ - mv ra, t1 + mv ra, t1 mv sp, t0 ret diff --git a/components/riscv/vectors.S b/components/riscv/vectors.S index 081fb951d4..6580517fa8 100644 --- a/components/riscv/vectors.S +++ b/components/riscv/vectors.S @@ -215,7 +215,7 @@ _interrupt_handler: /* entry */ save_regs save_mepc - + /* Before doing anythig preserve the stack pointer */ /* It will be saved in current TCB, if needed */ mv a0, sp diff --git a/components/soc/esp32c3/include/soc/soc_caps.h b/components/soc/esp32c3/include/soc/soc_caps.h index 51d2d1a8d6..2d112540f4 100644 --- a/components/soc/esp32c3/include/soc/soc_caps.h +++ b/components/soc/esp32c3/include/soc/soc_caps.h @@ -43,7 +43,6 @@ #include "rmt_caps.h" #include "spi_caps.h" #include "uart_caps.h" -#include "int_caps.h" /*-------------------------- TOUCH SENSOR CAPS -------------------------------*/ #define SOC_TOUCH_SENSOR_NUM (0) /*! No touch sensors on ESP32-C3 */ From 1f9629da9ff26b91c8893f3566c9776d44b011c3 Mon Sep 17 00:00:00 2001 From: morris Date: Tue, 5 Jan 2021 15:11:43 +0800 Subject: [PATCH 09/10] hal: put cpu_ll_get_core_id to IRAM --- components/hal/esp32c3/include/hal/cpu_ll.h | 2 +- components/hal/esp32s3/include/hal/cpu_ll.h | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/components/hal/esp32c3/include/hal/cpu_ll.h b/components/hal/esp32c3/include/hal/cpu_ll.h index e819fff803..ce8062c561 100644 --- a/components/hal/esp32c3/include/hal/cpu_ll.h +++ b/components/hal/esp32c3/include/hal/cpu_ll.h @@ -30,7 +30,7 @@ extern "C" { #endif -static inline int cpu_ll_get_core_id(void) +static inline int IRAM_ATTR cpu_ll_get_core_id(void) { #if SOC_CPU_CORES_NUM == 1 return 0; // No need to check core ID on single core hardware diff --git a/components/hal/esp32s3/include/hal/cpu_ll.h b/components/hal/esp32s3/include/hal/cpu_ll.h index f43c65ef34..a7fb19625c 100644 --- a/components/hal/esp32s3/include/hal/cpu_ll.h +++ b/components/hal/esp32s3/include/hal/cpu_ll.h @@ -21,13 +21,14 @@ #include "xtensa/config/specreg.h" #include "xtensa/config/extreg.h" #include "esp_bit_defs.h" +#include "esp_attr.h" #include "xtensa/config/core.h" #ifdef __cplusplus extern "C" { #endif -static inline int cpu_ll_get_core_id(void) +static inline int IRAM_ATTR cpu_ll_get_core_id(void) { uint32_t id; asm volatile ( From 7a71cedf873e71ab0b802717d63f64ab17cc9c70 Mon Sep 17 00:00:00 2001 From: morris Date: Wed, 30 Dec 2020 13:27:00 +0800 Subject: [PATCH 10/10] interrupt: filter out reserved int number by decoding risc-v JAL instruction --- components/hal/interrupt_controller_hal.c | 26 +++++++++++-- components/riscv/CMakeLists.txt | 5 ++- .../include/riscv/instruction_decode.h} | 14 +++++-- components/riscv/instruction_decode.c | 38 +++++++++++++++++++ 4 files changed, 75 insertions(+), 8 deletions(-) rename components/{soc/esp32c3/include/soc/int_caps.h => riscv/include/riscv/instruction_decode.h} (68%) create mode 100644 components/riscv/instruction_decode.c diff --git a/components/hal/interrupt_controller_hal.c b/components/hal/interrupt_controller_hal.c index f3c5728301..93bce347c9 100644 --- a/components/hal/interrupt_controller_hal.c +++ b/components/hal/interrupt_controller_hal.c @@ -14,11 +14,27 @@ #include "hal/interrupt_controller_hal.h" +#if __riscv +#include "riscv/instruction_decode.h" + +static bool is_interrupt_number_reserved(int interrupt_number) +{ + extern int _vector_table; + extern int _interrupt_handler; + const intptr_t pc = (intptr_t)(&_vector_table + interrupt_number); + + /* JAL instructions are relative to the PC there are executed from. */ + const intptr_t destination = pc + riscv_decode_offset_from_jal_instruction(pc); + + return destination != (intptr_t)&_interrupt_handler; +} +#endif + int_type_t interrupt_controller_hal_desc_type(int interrupt_number) { #ifndef SOC_CPU_HAS_FLEXIBLE_INTC const int_desc_t *int_desc = interrupt_controller_hal_desc_table(); - return(int_desc[interrupt_number].type); + return (int_desc[interrupt_number].type); #else return (INTTP_NA); #endif @@ -28,7 +44,7 @@ int interrupt_controller_hal_desc_level(int interrupt_number) { #ifndef SOC_CPU_HAS_FLEXIBLE_INTC const int_desc_t *int_desc = interrupt_controller_hal_desc_table(); - return(int_desc[interrupt_number].level); + return (int_desc[interrupt_number].level); #else return 1; #endif @@ -38,8 +54,12 @@ int_desc_flag_t interrupt_controller_hal_desc_flags(int interrupt_number, int cp { #ifndef SOC_CPU_HAS_FLEXIBLE_INTC const int_desc_t *int_desc = interrupt_controller_hal_desc_table(); - return(int_desc[interrupt_number].cpuflags[cpu_number]); + return (int_desc[interrupt_number].cpuflags[cpu_number]); +#else +#if __riscv + return is_interrupt_number_reserved(interrupt_number) ? INTDESC_RESVD : INTDESC_NORMAL; #else return INTDESC_NORMAL; #endif +#endif } diff --git a/components/riscv/CMakeLists.txt b/components/riscv/CMakeLists.txt index c42b51db9d..0290ca9937 100644 --- a/components/riscv/CMakeLists.txt +++ b/components/riscv/CMakeLists.txt @@ -7,10 +7,11 @@ if(BOOTLOADER_BUILD) else() set(priv_requires soc freertos) set(srcs - "interrupt.c" - "stdatomic.c" "expression_with_stack_riscv.c" "expression_with_stack_riscv_asm.S" + "instruction_decode.c" + "interrupt.c" + "stdatomic.c" "vectors.S") endif() diff --git a/components/soc/esp32c3/include/soc/int_caps.h b/components/riscv/include/riscv/instruction_decode.h similarity index 68% rename from components/soc/esp32c3/include/soc/int_caps.h rename to components/riscv/include/riscv/instruction_decode.h index c84aa3a564..5625680f82 100644 --- a/components/soc/esp32c3/include/soc/int_caps.h +++ b/components/riscv/include/riscv/instruction_decode.h @@ -3,7 +3,7 @@ // 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 - +// // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software @@ -14,12 +14,20 @@ #pragma once +#include + #ifdef __cplusplus extern "C" { #endif -#define SOC_INTERRUPT_LEVEL_CAN_SET (1) -#define SOC_INTERRUPT_TYPE_CAN_SET (1) +/** + * @brief Decode the offset value from a RISC-V JAL instruction + * @note This API will abort if the instruction is not JAL formatted. + * + * @param inst_addr Address of JAL instruction + * @return int offset value + */ +int riscv_decode_offset_from_jal_instruction(const intptr_t inst_addr); #ifdef __cplusplus } diff --git a/components/riscv/instruction_decode.c b/components/riscv/instruction_decode.c new file mode 100644 index 0000000000..89abccbbbb --- /dev/null +++ b/components/riscv/instruction_decode.c @@ -0,0 +1,38 @@ +// Copyright 2020 Espressif Systems (Shanghai) PTE LTD +// +// 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 +// +// 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 +#include "riscv/instruction_decode.h" + +typedef union { + struct { + unsigned int opcode: 7; + unsigned int rd: 5; + int imm_19_12: 8; + int imm_11: 1; + int imm_10_1: 10; + int imm20: 1; + }; + unsigned int inst; +} riscv_jal_intruction_t; + +int riscv_decode_offset_from_jal_instruction(const intptr_t inst_addr) +{ + riscv_jal_intruction_t *jal_inst = (riscv_jal_intruction_t *)inst_addr; + // check if it's a valid JAL instruction + if (jal_inst->opcode != 0x6f && jal_inst->rd != 0) { + abort(); + } + return (jal_inst->imm_10_1 | jal_inst->imm_11 << 10 | jal_inst->imm_19_12 << 11 | jal_inst->imm20 << 19) << 1; +}