mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
Per-CPU interrupt handlers and args
This commit is contained in:
parent
fcba7e278d
commit
86d8f63005
@ -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) {
|
static void esp_crosscore_isr(void *arg) {
|
||||||
uint32_t myReasonVal;
|
uint32_t myReasonVal;
|
||||||
#if 0
|
|
||||||
//A pointer to the correct reason array item is passed to this ISR.
|
//A pointer to the correct reason array item is passed to this ISR.
|
||||||
volatile uint32_t *myReason=arg;
|
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.
|
//Clear the interrupt first.
|
||||||
if (xPortGetCoreID()==0) {
|
if (xPortGetCoreID()==0) {
|
||||||
WRITE_PERI_REG(DPORT_CPU_INTR_FROM_CPU_0_REG, 0);
|
WRITE_PERI_REG(DPORT_CPU_INTR_FROM_CPU_0_REG, 0);
|
||||||
|
@ -265,12 +265,6 @@
|
|||||||
#define INCLUDE_eTaskGetState 1
|
#define INCLUDE_eTaskGetState 1
|
||||||
#define configUSE_QUEUE_SETS 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_BOARD 1 /* Board mode */
|
||||||
#define configXT_SIMULATOR 0
|
#define configXT_SIMULATOR 0
|
||||||
|
@ -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
|
executing all it's own. Use a mux, queue or semaphore to protect your
|
||||||
structures instead.
|
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
|
- 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
|
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
|
set the pointer. This callback will be called by the idle task, with the
|
||||||
|
@ -30,7 +30,9 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|||||||
|
|
||||||
#include <xtensa/config/core.h>
|
#include <xtensa/config/core.h>
|
||||||
|
|
||||||
|
#include "freertos/FreeRTOS.h"
|
||||||
#include "freertos/xtensa_api.h"
|
#include "freertos/xtensa_api.h"
|
||||||
|
#include "freertos/portable.h"
|
||||||
|
|
||||||
#include "rom/ets_sys.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 */
|
/* Handler table is in xtensa_intr_asm.S */
|
||||||
// Todo: Make multicore - JD
|
// 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 )
|
if( n < 0 || n >= XCHAL_EXCCAUSE_NUM )
|
||||||
return 0; /* invalid exception number */
|
return 0; /* invalid exception number */
|
||||||
|
|
||||||
|
/* Convert exception number to _xt_exception_table name */
|
||||||
|
n = n * portNUM_PROCESSORS + xPortGetCoreID();
|
||||||
old = _xt_exception_table[n];
|
old = _xt_exception_table[n];
|
||||||
|
|
||||||
if (f) {
|
if (f) {
|
||||||
@ -89,7 +93,7 @@ typedef struct xt_handler_table_entry {
|
|||||||
void * arg;
|
void * arg;
|
||||||
} xt_handler_table_entry;
|
} 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 )
|
if( Xthal_intlevel[n] > XCHAL_EXCM_LEVEL )
|
||||||
return 0; /* priority level too high to safely handle in C */
|
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;
|
entry = _xt_interrupt_table + n;
|
||||||
old = entry->handler;
|
old = entry->handler;
|
||||||
|
|
||||||
|
@ -30,6 +30,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|||||||
#include <xtensa/config/core.h>
|
#include <xtensa/config/core.h>
|
||||||
|
|
||||||
#include "xtensa_context.h"
|
#include "xtensa_context.h"
|
||||||
|
#include "FreeRTOSConfig.h"
|
||||||
|
|
||||||
#if XCHAL_HAVE_INTERRUPTS
|
#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
|
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
|
slots can be filled, because interrupts at level > EXCM_LEVEL will not be
|
||||||
dispatched to a C handler by default.
|
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:
|
_xt_interrupt_table:
|
||||||
|
|
||||||
.set i, 0
|
.set i, 0
|
||||||
.rept XCHAL_NUM_INTERRUPTS
|
.rept XCHAL_NUM_INTERRUPTS*portNUM_PROCESSORS
|
||||||
.word xt_unhandled_interrupt /* handler address */
|
.word xt_unhandled_interrupt /* handler address */
|
||||||
.word i /* handler arg (default: intnum) */
|
.word i /* handler arg (default: intnum) */
|
||||||
.set i, i+1
|
.set i, i+1
|
||||||
@ -85,6 +95,15 @@ _xt_interrupt_table:
|
|||||||
Table of C-callable exception handlers for each exception. Note that not all
|
Table of C-callable exception handlers for each exception. Note that not all
|
||||||
slots will be active, because some exceptions (e.g. coprocessor exceptions)
|
slots will be active, because some exceptions (e.g. coprocessor exceptions)
|
||||||
are always handled by the OS and cannot be hooked by user handlers.
|
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
|
.align 4
|
||||||
|
|
||||||
_xt_exception_table:
|
_xt_exception_table:
|
||||||
.rept XCHAL_EXCCAUSE_NUM
|
.rept XCHAL_EXCCAUSE_NUM * portNUM_PROCESSORS
|
||||||
.word xt_unhandled_exception /* handler address */
|
.word xt_unhandled_exception /* handler address */
|
||||||
.endr
|
.endr
|
||||||
|
|
||||||
|
@ -113,6 +113,27 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|||||||
#define XIE_ARG 4
|
#define XIE_ARG 4
|
||||||
#define XIE_SIZE 8
|
#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.
|
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 */
|
find_ms_setbit a3, a4, a3, 0 /* a3 = interrupt number */
|
||||||
|
|
||||||
|
get_percpu_entry_for a3, a12
|
||||||
movi a4, _xt_interrupt_table
|
movi a4, _xt_interrupt_table
|
||||||
addx8 a3, a3, a4 /* a3 = address of interrupt table entry */
|
addx8 a3, a3, a4 /* a3 = address of interrupt table entry */
|
||||||
l32i a4, a3, XIE_HANDLER /* a4 = handler address */
|
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.
|
with index 0 containing the entry for user exceptions.
|
||||||
Initialized with all 0s, meaning no handler is installed at each level.
|
Initialized with all 0s, meaning no handler is installed at each level.
|
||||||
See comment in xtensa_rtos.h for more details.
|
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 */
|
rsr a2, EXCCAUSE /* recover exc cause */
|
||||||
movi a3, _xt_exception_table
|
movi a3, _xt_exception_table
|
||||||
|
get_percpu_entry_for a3, a4
|
||||||
addx4 a4, a2, a3 /* a4 = address of exception table entry */
|
addx4 a4, a2, a3 /* a4 = address of exception table entry */
|
||||||
l32i a4, a4, 0 /* a4 = handler address */
|
l32i a4, a4, 0 /* a4 = handler address */
|
||||||
#ifdef __XTENSA_CALL0_ABI__
|
#ifdef __XTENSA_CALL0_ABI__
|
||||||
|
Loading…
x
Reference in New Issue
Block a user