From 86d8f63005d42bb9c46330c67b35ba8efc3a04ec Mon Sep 17 00:00:00 2001 From: Jeroen Domburg Date: Thu, 10 Nov 2016 17:59:46 +0800 Subject: [PATCH 1/3] Per-CPU interrupt handlers and args --- components/esp32/crosscore_int.c | 7 +---- .../include/freertos/FreeRTOSConfig.h | 6 ----- components/freertos/readme_smp.txt | 5 ---- components/freertos/xtensa_intr.c | 11 ++++++-- components/freertos/xtensa_intr_asm.S | 23 ++++++++++++++-- components/freertos/xtensa_vectors.S | 26 +++++++++++++++++++ 6 files changed, 57 insertions(+), 21 deletions(-) diff --git a/components/esp32/crosscore_int.c b/components/esp32/crosscore_int.c index 60a45da402..60f972a2a2 100644 --- a/components/esp32/crosscore_int.c +++ b/components/esp32/crosscore_int.c @@ -45,14 +45,9 @@ the ISR will cause it to switch _away_ from it. portYIELD_FROM_ISR will probably */ static void esp_crosscore_isr(void *arg) { uint32_t myReasonVal; -#if 0 //A pointer to the correct reason array item is passed to this ISR. volatile uint32_t *myReason=arg; -#else - //The previous line does not work yet, the interrupt code needs work to understand two separate interrupt and argument - //tables... this is a valid but slightly less optimal replacement. - volatile uint32_t *myReason=&reason[xPortGetCoreID()]; -#endif + //Clear the interrupt first. if (xPortGetCoreID()==0) { WRITE_PERI_REG(DPORT_CPU_INTR_FROM_CPU_0_REG, 0); diff --git a/components/freertos/include/freertos/FreeRTOSConfig.h b/components/freertos/include/freertos/FreeRTOSConfig.h index 224857c86c..47566ab3b3 100644 --- a/components/freertos/include/freertos/FreeRTOSConfig.h +++ b/components/freertos/include/freertos/FreeRTOSConfig.h @@ -265,12 +265,6 @@ #define INCLUDE_eTaskGetState 1 #define configUSE_QUEUE_SETS 1 -#if (!defined XT_INTEXC_HOOKS) -#define configXT_INTEXC_HOOKS 1 /* Exception hooks used by certain tests */ -#if configUSE_TRACE_FACILITY_2 -#define configASSERT_2 1 /* Specific to Xtensa port */ -#endif -#endif #define configXT_BOARD 1 /* Board mode */ #define configXT_SIMULATOR 0 diff --git a/components/freertos/readme_smp.txt b/components/freertos/readme_smp.txt index 38f332416a..fdd9b146b1 100644 --- a/components/freertos/readme_smp.txt +++ b/components/freertos/readme_smp.txt @@ -19,11 +19,6 @@ it would on a single-core system: the other core still will keep on executing all it's own. Use a mux, queue or semaphore to protect your structures instead. -- While each core has individual interrupts, the handlers are shared. This -means that when you set a handler for an interrupt, it will get triggered if -the interrupt is triggered on both CPU0 as well as on CPU1. This is something -we may change in future FreeRTOS-esp32 releases. - - This FreeRTOS version has the task local storage backported from the 8.2.x versions. It, however, has an addition: you can also set a callback when you set the pointer. This callback will be called by the idle task, with the diff --git a/components/freertos/xtensa_intr.c b/components/freertos/xtensa_intr.c index f5ca7d151f..e9c0b79b96 100644 --- a/components/freertos/xtensa_intr.c +++ b/components/freertos/xtensa_intr.c @@ -30,7 +30,9 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include +#include "freertos/FreeRTOS.h" #include "freertos/xtensa_api.h" +#include "freertos/portable.h" #include "rom/ets_sys.h" @@ -39,7 +41,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. /* Handler table is in xtensa_intr_asm.S */ // Todo: Make multicore - JD -extern xt_exc_handler _xt_exception_table[XCHAL_EXCCAUSE_NUM]; +extern xt_exc_handler _xt_exception_table[XCHAL_EXCCAUSE_NUM*portNUM_PROCESSORS]; /* @@ -66,6 +68,8 @@ xt_exc_handler xt_set_exception_handler(int n, xt_exc_handler f) if( n < 0 || n >= XCHAL_EXCCAUSE_NUM ) return 0; /* invalid exception number */ + /* Convert exception number to _xt_exception_table name */ + n = n * portNUM_PROCESSORS + xPortGetCoreID(); old = _xt_exception_table[n]; if (f) { @@ -89,7 +93,7 @@ typedef struct xt_handler_table_entry { void * arg; } xt_handler_table_entry; -extern xt_handler_table_entry _xt_interrupt_table[XCHAL_NUM_INTERRUPTS]; +extern xt_handler_table_entry _xt_interrupt_table[XCHAL_NUM_INTERRUPTS*portNUM_PROCESSORS]; /* @@ -118,6 +122,9 @@ xt_handler xt_set_interrupt_handler(int n, xt_handler f, void * arg) if( Xthal_intlevel[n] > XCHAL_EXCM_LEVEL ) return 0; /* priority level too high to safely handle in C */ + /* Convert exception number to _xt_exception_table name */ + n = n * portNUM_PROCESSORS + xPortGetCoreID(); + entry = _xt_interrupt_table + n; old = entry->handler; diff --git a/components/freertos/xtensa_intr_asm.S b/components/freertos/xtensa_intr_asm.S index 5f9890dfe4..8c7ae63fdb 100644 --- a/components/freertos/xtensa_intr_asm.S +++ b/components/freertos/xtensa_intr_asm.S @@ -30,6 +30,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include #include "xtensa_context.h" +#include "FreeRTOSConfig.h" #if XCHAL_HAVE_INTERRUPTS @@ -59,6 +60,15 @@ _xt_vpri_mask: .word 0xFFFFFFFF /* Virtual priority mask */ Table of C-callable interrupt handlers for each interrupt. Note that not all slots can be filled, because interrupts at level > EXCM_LEVEL will not be dispatched to a C handler by default. + + Stored as: + int 0 cpu 0 + int 0 cpu 1 + ... + int 0 cpu n + int 1 cpu 0 + int 1 cpu 1 + etc ------------------------------------------------------------------------------- */ @@ -69,7 +79,7 @@ _xt_vpri_mask: .word 0xFFFFFFFF /* Virtual priority mask */ _xt_interrupt_table: .set i, 0 - .rept XCHAL_NUM_INTERRUPTS + .rept XCHAL_NUM_INTERRUPTS*portNUM_PROCESSORS .word xt_unhandled_interrupt /* handler address */ .word i /* handler arg (default: intnum) */ .set i, i+1 @@ -85,6 +95,15 @@ _xt_interrupt_table: Table of C-callable exception handlers for each exception. Note that not all slots will be active, because some exceptions (e.g. coprocessor exceptions) are always handled by the OS and cannot be hooked by user handlers. + + Stored as: + exc 0 cpu 0 + exc 0 cpu 1 + ... + exc 0 cpu n + exc 1 cpu 0 + exc 1 cpu 1 + etc ------------------------------------------------------------------------------- */ @@ -93,7 +112,7 @@ _xt_interrupt_table: .align 4 _xt_exception_table: - .rept XCHAL_EXCCAUSE_NUM + .rept XCHAL_EXCCAUSE_NUM * portNUM_PROCESSORS .word xt_unhandled_exception /* handler address */ .endr diff --git a/components/freertos/xtensa_vectors.S b/components/freertos/xtensa_vectors.S index 7cf70f0032..2a373810fd 100644 --- a/components/freertos/xtensa_vectors.S +++ b/components/freertos/xtensa_vectors.S @@ -113,6 +113,27 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define XIE_ARG 4 #define XIE_SIZE 8 + +/* + Macro get_percpu_entry_for - convert a per-core ID into a multicore entry. + Basically does reg=reg*portNUM_PROCESSORS+current_core_id + Multiple versions here for multiple +*/ + .macro get_percpu_entry_for reg scratch +#if (portNUM_PROCESSORS == 1) + /* No need to do anything */ +#elif (portNUM_PROCESSORS == 2) + /* Optimized 2-core code. */ + getcoreid \scratch + addx2 \reg,\reg,\scratch +#else + /* Generalized n-core code. Untested! */ + movi \scratch,portNUM_PROCESSORS + mull \scratch,\reg,\scratch + getcoreid \reg + add \reg,\scratch,\reg +#endif + .endm /* -------------------------------------------------------------------------------- Macro extract_msb - return the input with only the highest bit set. @@ -229,6 +250,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. find_ms_setbit a3, a4, a3, 0 /* a3 = interrupt number */ + get_percpu_entry_for a3, a12 movi a4, _xt_interrupt_table addx8 a3, a3, a4 /* a3 = address of interrupt table entry */ l32i a4, a3, XIE_HANDLER /* a4 = handler address */ @@ -395,6 +417,9 @@ panic_print_hex_ok: with index 0 containing the entry for user exceptions. Initialized with all 0s, meaning no handler is installed at each level. See comment in xtensa_rtos.h for more details. + + *WARNING* This array is for all CPUs, that is, installing a hook for + one CPU will install it for all others as well! -------------------------------------------------------------------------------- */ @@ -688,6 +713,7 @@ _xt_user_exc: rsr a2, EXCCAUSE /* recover exc cause */ movi a3, _xt_exception_table + get_percpu_entry_for a3, a4 addx4 a4, a2, a3 /* a4 = address of exception table entry */ l32i a4, a4, 0 /* a4 = handler address */ #ifdef __XTENSA_CALL0_ABI__ From 07c30f22b58f4511912a2e809bba3474769632bd Mon Sep 17 00:00:00 2001 From: Jeroen Domburg Date: Thu, 10 Nov 2016 18:04:23 +0800 Subject: [PATCH 2/3] Add core info to xt interrupt api --- components/freertos/include/freertos/xtensa_api.h | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/components/freertos/include/freertos/xtensa_api.h b/components/freertos/include/freertos/xtensa_api.h index 04ad7d62d8..87922691dd 100644 --- a/components/freertos/include/freertos/xtensa_api.h +++ b/components/freertos/include/freertos/xtensa_api.h @@ -42,7 +42,8 @@ typedef void (*xt_exc_handler)(XtExcFrame *); /* ------------------------------------------------------------------------------- - Call this function to set a handler for the specified exception. + Call this function to set a handler for the specified exception. The handler + will be installed on the core that calls this function. n - Exception number (type) f - Handler function address, NULL to uninstall handler. @@ -61,7 +62,8 @@ extern xt_exc_handler xt_set_exception_handler(int n, xt_exc_handler f); /* ------------------------------------------------------------------------------- - Call this function to set a handler for the specified interrupt. + Call this function to set a handler for the specified interrupt. The handler + will be installed on the core that calls this function. n - Interrupt number. f - Handler function address, NULL to uninstall handler. @@ -73,7 +75,8 @@ extern xt_handler xt_set_interrupt_handler(int n, xt_handler f, void * arg); /* ------------------------------------------------------------------------------- - Call this function to enable the specified interrupts. + Call this function to enable the specified interrupts on the core that runs + this code. mask - Bit mask of interrupts to be enabled. ------------------------------------------------------------------------------- @@ -83,7 +86,8 @@ extern void xt_ints_on(unsigned int mask); /* ------------------------------------------------------------------------------- - Call this function to disable the specified interrupts. + Call this function to disable the specified interrupts on the core that runs + this code. mask - Bit mask of interrupts to be disabled. ------------------------------------------------------------------------------- From fdf3db19590cd722c8d0be11b3649cc2b1ff8c29 Mon Sep 17 00:00:00 2001 From: Jeroen Domburg Date: Fri, 11 Nov 2016 12:26:42 +0800 Subject: [PATCH 3/3] Comment fix --- components/freertos/xtensa_vectors.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/freertos/xtensa_vectors.S b/components/freertos/xtensa_vectors.S index 2a373810fd..f180705e70 100644 --- a/components/freertos/xtensa_vectors.S +++ b/components/freertos/xtensa_vectors.S @@ -117,7 +117,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. /* Macro get_percpu_entry_for - convert a per-core ID into a multicore entry. Basically does reg=reg*portNUM_PROCESSORS+current_core_id - Multiple versions here for multiple + Multiple versions here to optimize for specific portNUM_PROCESSORS values. */ .macro get_percpu_entry_for reg scratch #if (portNUM_PROCESSORS == 1)