]> granicus.if.org Git - esp-idf/commitdiff
Per-CPU interrupt handlers and args
authorJeroen Domburg <git@j0h.nl>
Thu, 10 Nov 2016 09:59:46 +0000 (17:59 +0800)
committerJeroen Domburg <git@j0h.nl>
Thu, 10 Nov 2016 09:59:46 +0000 (17:59 +0800)
components/esp32/crosscore_int.c
components/freertos/include/freertos/FreeRTOSConfig.h
components/freertos/readme_smp.txt
components/freertos/xtensa_intr.c
components/freertos/xtensa_intr_asm.S
components/freertos/xtensa_vectors.S

index 60a45da402c9a8a980520fa57901542cd573092e..60f972a2a21db5c0b068e289bdf39abd98b66047 100644 (file)
@@ -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);
index 224857c86ca98a42a3cdbf070fe727ca40ab88ab..47566ab3b37fdffbedaf8bc2aff21a60b2e258c5 100644 (file)
 #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
index 38f332416ab53fd099fbd0c4f8d21b743cce89e5..fdd9b146b17067f262947e65054ac663c0badd83 100644 (file)
@@ -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 
index f5ca7d151fdbe17b5df9ca8756586601292f7156..e9c0b79b963f545be90cd5f65cc4122a7f3800a9 100644 (file)
@@ -30,7 +30,9 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 #include <xtensa/config/core.h>
 
+#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;
 
index 5f9890dfe4f22a5f80ed3cb89eb70c569b07ff0d..8c7ae63fdb6823c1cae21a4d316c4e30f3edb0ed 100644 (file)
@@ -30,6 +30,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include <xtensa/config/core.h>
 
 #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
 
index 7cf70f0032d01bfc4b9d9b5790fbb7e268449e45..2a373810fd03c69624a8c8839b00519839717a24 100644 (file)
@@ -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__