summaryrefslogtreecommitdiff
path: root/ports/xtensa/xcc/src
diff options
context:
space:
mode:
Diffstat (limited to 'ports/xtensa/xcc/src')
-rw-r--r--ports/xtensa/xcc/src/tx_clib_lock.c40
-rw-r--r--ports/xtensa/xcc/src/tx_initialize_low_level.c2
-rw-r--r--ports/xtensa/xcc/src/tx_thread_schedule.S27
-rw-r--r--ports/xtensa/xcc/src/tx_thread_system_return.S43
-rw-r--r--ports/xtensa/xcc/src/xtensa_context.S4
-rw-r--r--ports/xtensa/xcc/src/xtensa_intr.c12
-rw-r--r--ports/xtensa/xcc/src/xtensa_intr_asm.S5
-rw-r--r--ports/xtensa/xcc/src/xtensa_intr_wrapper.c2
-rw-r--r--ports/xtensa/xcc/src/xtensa_vectors.S321
9 files changed, 373 insertions, 83 deletions
diff --git a/ports/xtensa/xcc/src/tx_clib_lock.c b/ports/xtensa/xcc/src/tx_clib_lock.c
index 9e308720..43f6e220 100644
--- a/ports/xtensa/xcc/src/tx_clib_lock.c
+++ b/ports/xtensa/xcc/src/tx_clib_lock.c
@@ -66,6 +66,8 @@ TX_MUTEX clib_lock_mutex;
void
__malloc_lock (struct _reent * ptr)
{
+ (void) ptr;
+
if (_tx_thread_system_state != TX_INITIALIZE_IS_FINISHED) {
return;
}
@@ -80,6 +82,8 @@ __malloc_lock (struct _reent * ptr)
void
__malloc_unlock (struct _reent * ptr)
{
+ (void) ptr;
+
if (_tx_thread_system_state != TX_INITIALIZE_IS_FINISHED) {
return;
}
@@ -99,6 +103,8 @@ __malloc_unlock (struct _reent * ptr)
void
__env_lock (struct _reent * ptr)
{
+ (void) ptr;
+
if (_tx_thread_system_state != TX_INITIALIZE_IS_FINISHED) {
return;
}
@@ -113,6 +119,8 @@ __env_lock (struct _reent * ptr)
void
__env_unlock (struct _reent * ptr)
{
+ (void) ptr;
+
if (_tx_thread_system_state != TX_INITIALIZE_IS_FINISHED) {
return;
}
@@ -128,6 +136,12 @@ __env_unlock (struct _reent * ptr)
#include <errno.h>
#include <sys/reent.h>
+#if defined(__DYNAMIC_REENT__)
+// Helps to keep code similar between dynamic and non-dynamic.
+#undef _reent_ptr
+struct _reent * _reent_ptr;
+#endif
+
#define XT_NUM_CLIB_LOCKS (_MAX_LOCK + FOPEN_MAX)
typedef TX_MUTEX * _Rmtx;
@@ -201,6 +215,32 @@ _Mtxunlock (_Rmtx * mtx)
#endif /* XSHAL_CLIB == XTHAL_CLIB_XCLIB */
+#if defined(__DYNAMIC_REENT__)
+/**************************************************************************/
+/* Return libc context pointer for current thread. Overrides weak */
+/* version in libc. Until real threads are active, use the libc's */
+/* global reent struct. */
+/**************************************************************************/
+struct _reent *
+__getreent(void)
+{
+ TX_THREAD * thread_ptr = _tx_thread_current_ptr;
+
+ if (thread_ptr) {
+ return &(thread_ptr->tx_thread_clib_reent);
+ }
+
+#if XSHAL_CLIB == XTHAL_CLIB_XCLIB
+ extern struct _reent g_reent; /* from xclib */
+ return &g_reent;
+#elif XSHAL_CLIB == XTHAL_CLIB_NEWLIB
+ extern struct _reent * _impure_ptr; /* from newlib */
+ return _impure_ptr;
+#else
+#error "Unsupported C library for __DYNAMIC_REENT__"
+#endif
+}
+#endif
/**************************************************************************/
/* _sbrk_r - heap allocator. This function is called when the memory */
diff --git a/ports/xtensa/xcc/src/tx_initialize_low_level.c b/ports/xtensa/xcc/src/tx_initialize_low_level.c
index de2c2b93..d52689cf 100644
--- a/ports/xtensa/xcc/src/tx_initialize_low_level.c
+++ b/ports/xtensa/xcc/src/tx_initialize_low_level.c
@@ -80,6 +80,8 @@ VOID _tx_initialize_low_level(VOID)
/* Disable interrupts - don't want any that interact with ThreadX yet. */
TX_DISABLE
+ /* Suppress compiler warning about set but not used variable. */
+ (void) interrupt_save;
/*
Disable stack limit checking if present. Whatever was set up earlier
diff --git a/ports/xtensa/xcc/src/tx_thread_schedule.S b/ports/xtensa/xcc/src/tx_thread_schedule.S
index 448dc6d7..6c595170 100644
--- a/ports/xtensa/xcc/src/tx_thread_schedule.S
+++ b/ports/xtensa/xcc/src/tx_thread_schedule.S
@@ -166,9 +166,18 @@ _tx_thread_schedule:
#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
/* Call the thread entry function to indicate the thread is executing. */
+ /* Note a2 may be trashed by this call, must be reloaded. */
#ifdef __XTENSA_CALL0_ABI__
call0 _tx_execution_thread_enter
+ movi a2, _tx_thread_current_ptr
+ l32i a2, a2, 0
#else
+ /* Ensure that PS.WOE is set for windowed call */
+ movi a0, PS_WOE
+ rsr.ps a3
+ or a3, a3, a0
+ wsr.ps a3
+ rsync
call8 _tx_execution_thread_enter
#endif
#endif
@@ -229,14 +238,24 @@ _tx_thread_schedule:
rsync /* ensure wsr.CPENABLE has completed */
#endif
- wsr a3, PS /* no need to sync PS, delay is OK */
-
- /* This does not return to its caller, but to the selected thread. */
+ /* De-allocate the remainder of the frame before reenabling interrupts
+ * to avoid overrunning a task stack of TX_MINIMUM_STACK bytes, which
+ * can only handle one XT_STK_FRMSZ.
+ */
#ifdef __XTENSA_CALL0_ABI__
/* 'addi sp, sp, imm' could turn into 'addmi, addi' sequence and make */
/* the sp briefly point to an illegal stack location. Avoid that. */
- addi a2, sp, XT_STK_FRMSZ
+ addi a2, sp, XT_STK_FRMSZ /* fully deallocate stack frame */
mov sp, a2
+ #else
+ addi a2, sp, XT_STK_FRMSZ - 48 /* initial SP at solicited entry; */
+ movsp sp, a2 /* retw will deallocate remainder */
+ #endif
+
+ wsr a3, PS /* no need to sync PS, delay is OK */
+
+ /* This does not return to its caller, but to the selected thread. */
+ #ifdef __XTENSA_CALL0_ABI__
ret
#else
retw
diff --git a/ports/xtensa/xcc/src/tx_thread_system_return.S b/ports/xtensa/xcc/src/tx_thread_system_return.S
index d1fc4a9f..af0fa24b 100644
--- a/ports/xtensa/xcc/src/tx_thread_system_return.S
+++ b/ports/xtensa/xcc/src/tx_thread_system_return.S
@@ -70,26 +70,25 @@ _tx_thread_system_return:
Since this is solicited, no need to save regs compiler doesn't preserve.
*/
-#if XCHAL_HAVE_XEA3
#ifdef __XTENSA_CALL0_ABI__
- addi sp, sp, -16
+ addi a2, sp, -16 /* avoid addi/addmi relaxation that */
+ mov sp, a2 /* might temporarily move sp up */
#else
entry sp, 48
#endif
+#if XCHAL_HAVE_XEA3
s32i a0, sp, 0 /* save return address */
-#else
- #ifdef __XTENSA_CALL0_ABI__
- addi a2, sp, -XT_STK_FRMSZ /* avoid addi/addmi relaxation that */
- mov sp, a2 /* might temporarily move sp up */
- #else
- entry sp, XT_STK_FRMSZ
- #endif
#endif
#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
/* Call the thread exit function to indicate the thread is no longer executing. */
#ifdef __XTENSA_CALL0_ABI__
+ /* Preserve a0 across the call. */
+#if !XCHAL_HAVE_XEA3
+ s32i a0, sp, 0
+#endif
call0 _tx_execution_thread_exit
+ l32i a0, sp, 0
#else
call8 _tx_execution_thread_exit
#endif
@@ -109,6 +108,7 @@ _tx_thread_system_return:
interrupts enabled, but we will have to revert SP to point above
the exception frame because that is what the dispatch code expects.
Must disable interrupts before that.
+ TODO: disable interrupts prior to stack allocation as we do for XEA2
*/
movi a0, .Lret
@@ -185,7 +185,27 @@ _tx_thread_system_return:
#else /* XEA1 or XEA2 */
+ /* Disable interrupts before allocating the full stack frame. Taking
+ * an interrupt will allocate a second exception stack frame, which will
+ * overrun a task stack of TX_MINIMUM_STACK bytes.
+ * Read PS so it can be saved off after stack adjustment.
+ */
rsr a2, PS
+ XT_INTS_DISABLE(a3)
+
+ /* Allocate the remainder of the frame here; we already allocated
+ * 16 bytes for call0 or 48 bytes for windowed upon entry.
+ * This memory will be deallocated in the solicited exit logic prior
+ * to reenabling interrupts.
+ */
+ #ifdef __XTENSA_CALL0_ABI__
+ addi a3, sp, -XT_STK_FRMSZ + 16 // avoid addi/addmi relaxation again
+ mov sp, a3
+ #else
+ addi a3, sp, -XT_STK_FRMSZ + 48
+ movsp sp, a3
+ #endif
+
s32i a0, sp, XT_STK_PC
s32i a2, sp, XT_STK_PS
#ifdef __XTENSA_CALL0_ABI__
@@ -205,8 +225,6 @@ _tx_thread_system_return:
wsr a2, PS
rsync
call0 xthal_window_spill_nw
- l32i a0, sp, XT_STK_PS
- wsr a0, PS // Restore PS value
rsync
#endif
@@ -226,10 +244,9 @@ _tx_thread_system_return:
a4 = &_tx_timer_time_slice
*/
- /* Lock out interrupts (except hi-pri). */
+ /* Already locked out interrupts (except hi-pri). */
/* Grab thread control block of current thread. */
movi a2, _tx_thread_current_ptr /* a2 = &_tx_thread_current_ptr */
- XT_INTS_DISABLE(a0)
l32i a3, a2, 0 /* a3 points to TCB */
/* Mark as having solicited entry to kernel (used on exit). */
diff --git a/ports/xtensa/xcc/src/xtensa_context.S b/ports/xtensa/xcc/src/xtensa_context.S
index e4b9aa0a..7e58ba14 100644
--- a/ports/xtensa/xcc/src/xtensa_context.S
+++ b/ports/xtensa/xcc/src/xtensa_context.S
@@ -131,7 +131,7 @@ _xt_context_save:
s32i a3, sp, XT_STK_ATOMCTL
#endif
- #if XT_USE_SWPRI
+ #ifdef XT_USE_SWPRI
/* Save virtual priority mask */
movi a3, _xt_vpri_mask
l32i a3, a3, 0
@@ -318,7 +318,7 @@ _xt_context_restore:
ret
-#endif /* XCHAL_HAVE_XEA3 */
+#endif /* XCHAL_HAVE_XEA2 */
/*******************************************************************************
diff --git a/ports/xtensa/xcc/src/xtensa_intr.c b/ports/xtensa/xcc/src/xtensa_intr.c
index c5f320cb..2f0622cd 100644
--- a/ports/xtensa/xcc/src/xtensa_intr.c
+++ b/ports/xtensa/xcc/src/xtensa_intr.c
@@ -1,5 +1,5 @@
/*******************************************************************************
-Copyright (c) 2006-2019 Cadence Design Systems Inc.
+Copyright (c) 2006-2023 Cadence Design Systems Inc.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
@@ -80,7 +80,7 @@ xt_exc_handler xt_set_exception_handler(uint32_t n, xt_exc_handler f)
#if XCHAL_HAVE_INTERRUPTS
-#if XCHAL_HAVE_XEA2
+#if XCHAL_HAVE_XEA2 && (XCHAL_NUM_INTERRUPTS <= 32)
/* Defined in xtensa_intr_asm.S */
extern uint32_t _xt_intenable;
extern uint32_t _xt_vpri_mask;
@@ -93,7 +93,7 @@ typedef struct xt_handler_table_entry {
void * arg;
} xt_handler_table_entry;
-#if (XT_USE_INT_WRAPPER || XCHAL_HAVE_XEA3)
+#if XCHAL_HAVE_XEA3
extern xt_handler_table_entry _xt_interrupt_table[XCHAL_NUM_INTERRUPTS + 1];
#else
extern xt_handler_table_entry _xt_interrupt_table[XCHAL_NUM_INTERRUPTS];
@@ -131,7 +131,7 @@ xt_handler xt_set_interrupt_handler(uint32_t n, xt_handler f, void * arg)
}
#endif
-#if (XT_USE_INT_WRAPPER || XCHAL_HAVE_XEA3)
+#if XCHAL_HAVE_XEA3
entry = _xt_interrupt_table + n + 1;
#else
entry = _xt_interrupt_table + n;
@@ -157,7 +157,7 @@ xt_handler xt_set_interrupt_handler(uint32_t n, xt_handler f, void * arg)
*/
void xt_interrupt_enable(uint32_t intnum)
{
-#if XCHAL_HAVE_XEA2
+#if XCHAL_HAVE_XEA2 && (XCHAL_NUM_INTERRUPTS <= 32)
uint32_t ps = XT_RSIL(15);
// New INTENABLE = (_xt_intenable | mask) & _xt_vpri_mask.
@@ -177,7 +177,7 @@ void xt_interrupt_enable(uint32_t intnum)
*/
void xt_interrupt_disable(uint32_t intnum)
{
-#if XCHAL_HAVE_XEA2
+#if XCHAL_HAVE_XEA2 && (XCHAL_NUM_INTERRUPTS <= 32)
uint32_t ps = XT_RSIL(15);
// New INTENABLE = (_xt_intenable & ~mask) & _xt_vpri_mask.
diff --git a/ports/xtensa/xcc/src/xtensa_intr_asm.S b/ports/xtensa/xcc/src/xtensa_intr_asm.S
index e972378a..c2bf1574 100644
--- a/ports/xtensa/xcc/src/xtensa_intr_asm.S
+++ b/ports/xtensa/xcc/src/xtensa_intr_asm.S
@@ -45,7 +45,7 @@
-------------------------------------------------------------------------------
*/
-#if XCHAL_HAVE_XEA2
+#if XCHAL_HAVE_XEA2 && (XCHAL_NUM_INTERRUPTS <= 32)
.data
.global _xt_intdata
@@ -112,9 +112,6 @@ _xt_interrupt_table:
#if XCHAL_HAVE_XEA3
.word xt_interrupt_wrapper
.word 0
-#elif XT_USE_INT_WRAPPER
- .word 0
- .word 0
#endif
.set i, 0
diff --git a/ports/xtensa/xcc/src/xtensa_intr_wrapper.c b/ports/xtensa/xcc/src/xtensa_intr_wrapper.c
index 4ccb29f5..76efec68 100644
--- a/ports/xtensa/xcc/src/xtensa_intr_wrapper.c
+++ b/ports/xtensa/xcc/src/xtensa_intr_wrapper.c
@@ -40,7 +40,7 @@
#include "tx_thread.h"
#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
-#include "tx_execution_profile.h"
+#include "../../utility/execution_profile_kit/tx_execution_profile.h"
#endif
diff --git a/ports/xtensa/xcc/src/xtensa_vectors.S b/ports/xtensa/xcc/src/xtensa_vectors.S
index 7b09638e..1dedd83d 100644
--- a/ports/xtensa/xcc/src/xtensa_vectors.S
+++ b/ports/xtensa/xcc/src/xtensa_vectors.S
@@ -75,6 +75,12 @@
/* Enable stack backtrace across exception/interrupt - see below */
#define XT_DEBUG_BACKTRACE 1
+#if (XCHAL_NUM_INTERRUPTS > 32)
+#define XT_EXTD_INTERRUPTS 1
+#else
+#define XT_EXTD_INTERRUPTS 0
+#endif
+
/*
--------------------------------------------------------------------------------
@@ -103,6 +109,97 @@
addi \aout, \aout, 1 /* return aout + 1 */
.endm
+
+/*
+--------------------------------------------------------------------------------
+ Macro debug_backtrace
+
+ This bit of code provides a nice debug backtrace in the debugger.
+ It does take a few more instructions, so undef XT_DEBUG_BACKTRACE
+ if you want to save the cycles.
+
+ Input : "ra" - Return address register (clobbered)
+ Input : "tmp" - Temp register (clobbered), must be a different register
+ Input : "level" - Numeric interrupt level
+ Output : "ra" - Return address modified to simulate call4
+--------------------------------------------------------------------------------
+*/
+
+ .macro debug_backtrace ra, tmp, level
+ #if XT_DEBUG_BACKTRACE
+ #ifndef __XTENSA_CALL0_ABI__
+ rsr \ra, EPC_1 + \level - 1 /* return address */
+ movi \tmp, 0xC0000000 /* constant with top 2 bits set (call size) */
+ or \ra, \ra, \tmp /* set top 2 bits */
+ addx2 \ra, \tmp, \ra /* clear top bit -- simulating call4 size */
+ #endif
+ #endif
+ .endm
+
+
+/*
+--------------------------------------------------------------------------------
+ Macro call_exec_isr_entry_fn
+
+ Call the ISR enter function to indicate an ISR is executing.
+
+ Inputs : None
+ Output : Nothing
+--------------------------------------------------------------------------------
+*/
+ .macro call_exec_isr_entry_fn
+ #ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
+ #ifdef __XTENSA_CALL0_ABI__
+ /* Preserve a2 across the call, a12 is callee-saved for call0 ABI. */
+ mov a12, a2
+ call0 _tx_execution_isr_enter
+ mov a2, a12
+ #else
+ call4 _tx_execution_isr_enter
+ #endif
+ #endif
+ .endm
+
+
+/*
+--------------------------------------------------------------------------------
+ Macro call_int_hook
+
+ Call interrupt hook if present to (pre)handle interrupts.
+ NOTE: macro does not parameterize all used registers since they cannot freely
+ be changed, either due to ABI conventions or other assembly code in this file.
+
+ Input : "level" - Interrupt level being processed
+ Input : "block" - Index of interrupt block being processed [0..3]
+ Input : "goto_on_done" - Label where control proceeds to if hook returns 0
+ Input : a2 - bitmask of pending interrupts in block being processed [0..3]
+ Output : a2 - updated bitmask of pending interrupts
+ Clobbers : a2, a4, and:
+ Clobbers : for windowed ABI: a6, a7
+ Clobbers : for call0 ABI: a3
+--------------------------------------------------------------------------------
+*/
+ .macro call_int_hook level, block, goto_on_done
+ #ifdef XT_INTEXC_HOOKS
+ movi a4, _xt_intexc_hooks
+ l32i a4, a4, \level << 2
+ beqz a4, 2f
+ #ifdef __XTENSA_CALL0_ABI__
+ movi a3, \block
+ callx0 a4
+ beqz a2, \goto_on_done
+ #else
+ mov a6, a2
+ movi a7, \block
+ callx4 a4
+ beqz a6, \goto_on_done
+ mov a2, a6
+ #endif
+2:
+ #endif
+ .endm
+
+
/*
--------------------------------------------------------------------------------
Macro dispatch_c_isr - dispatch interrupts to user ISRs.
@@ -124,59 +221,134 @@
NOTE: This macro will use registers a0 and a2-a6. The arguments are:
level -- interrupt level
mask -- interrupt bitmask for this level
+ mask1 -- interrupt bitmask for this level for bits 63:32 (XT_EXTD_INTERRUPTS)
+ mask2 -- interrupt bitmask for this level for bits 95:64 (XT_EXTD_INTERRUPTS)
+ mask3 -- interrupt bitmask for this level for bits 127:96 (XT_EXTD_INTERRUPTS)
--------------------------------------------------------------------------------
*/
- .macro dispatch_c_isr level mask
+ .macro dispatch_c_isr level mask mask1 mask2 mask3
/* Get mask of pending, enabled interrupts at this level into a2. */
.L_xt_user_int_&level&:
- rsr a2, INTENABLE
+
+ #if XT_EXTD_INTERRUPTS
+
+ /* When > 32 interrupts are configured, maintain at least 2 instructions
+ between RSR.INTERRUPT and branch instructions to avoid interlocks.
+ */
+ #if (XCHAL_NUM_INTERRUPTS > 96)
+ rsr a6, INTERRUPT3
+ #endif
+ #if (XCHAL_NUM_INTERRUPTS > 64)
+ rsr a5, INTERRUPT2
+ #endif
+ rsr a4, INTERRUPT1
rsr a3, INTERRUPT
- movi a4, \mask
- and a2, a2, a3
- and a2, a2, a4
- beqz a2, 9f /* nothing to do */
+ #if (XCHAL_NUM_INTERRUPTS > 96)
+ _bnez a6, .L_xt_user_int_&level&_chk_blk3
+ #endif
+ #if (XCHAL_NUM_INTERRUPTS > 64)
+ _bnez a5, .L_xt_user_int_&level&_chk_blk2
+ #endif
+ _bnez a4, .L_xt_user_int_&level&_chk_blk1
+ _bnez a3, .L_xt_user_int_&level&_chk
+ j 9f /* spurious */
- /* This bit of code provides a nice debug backtrace in the debugger.
- It does take a few more instructions, so undef XT_DEBUG_BACKTRACE
- if you want to save the cycles.
+ #if (XCHAL_NUM_INTERRUPTS > 96)
+ /* Identify and process block 3 interrupts. If none are active,
+ proceed to check subsequent blocks; thus preserve a3-a5.
*/
- #if XT_DEBUG_BACKTRACE
- #ifndef __XTENSA_CALL0_ABI__
- rsr a0, EPC_1 + \level - 1 /* return address */
- movi a4, 0xC0000000 /* constant with top 2 bits set (call size) */
- or a0, a0, a4 /* set top 2 bits */
- addx2 a0, a4, a0 /* clear top bit -- simulating call4 size */
+.L_xt_user_int_&level&_chk_blk3:
+ rsr a2, INTENABLE3
+ and a2, a2, a6
+ movi a6, \mask3
+ and a2, a2, a6
+ beqz a2, .L_xt_user_int_&level&_chk_blk2
+
+ /* Block 3 interrupt(s) pending */
+ debug_backtrace a0, a4, \level
+ call_exec_isr_entry_fn
+ call_int_hook \level, 3, 9f
+ extract_msb a4, a2 /* a4 = MSB of a2, a2 trashed */
+ wsr a4, INTCLEAR3 /* clear sw or edge-triggered interrupt */
+ #ifndef TX_NO_TIMER
+ #if (XT_TIMER_INTEN_BLK == 3)
+ movi a3, XT_TIMER_INTEN_BIT /* a3 = timer interrupt bit */
+ beq a3, a4, 7f /* if timer interrupt then skip table */
#endif
#endif
+ movi a5, _xt_interrupt_table + 8*96 /* a5 = dispatch table for block 3 */
+ j .L_xt_user_int_&level&_post_clear
+ #endif
- #ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
- /* Call the ISR enter function to indicate an ISR is executing. */
- #ifdef __XTENSA_CALL0_ABI__
- call0 _tx_execution_isr_enter
- #else
- call4 _tx_execution_isr_enter
+ #if (XCHAL_NUM_INTERRUPTS > 64)
+ /* Identify and process block 2 interrupts. If none are active,
+ proceed to check subsequent blocks; thus preserve a3-a4.
+ */
+.L_xt_user_int_&level&_chk_blk2:
+ rsr a2, INTENABLE2
+ movi a6, \mask2
+ and a2, a2, a5
+ and a2, a2, a6
+ beqz a2, .L_xt_user_int_&level&_chk_blk1
+
+ /* Block 2 interrupt(s) pending */
+ debug_backtrace a0, a4, \level
+ call_exec_isr_entry_fn
+ call_int_hook \level, 2, 9f
+ extract_msb a4, a2 /* a4 = MSB of a2, a2 trashed */
+ wsr a4, INTCLEAR2 /* clear sw or edge-triggered interrupt */
+ #ifndef TX_NO_TIMER
+ #if (XT_TIMER_INTEN_BLK == 2)
+ movi a3, XT_TIMER_INTEN_BIT /* a3 = timer interrupt bit */
+ beq a3, a4, 7f /* if timer interrupt then skip table */
+ #endif
#endif
+ movi a5, _xt_interrupt_table + 8*64 /* a5 = dispatch table for block 2 */
+ j .L_xt_user_int_&level&_post_clear
#endif
- #ifdef XT_INTEXC_HOOKS
- /* Call interrupt hook if present to (pre)handle interrupts. */
- movi a4, _xt_intexc_hooks
- l32i a4, a4, \level << 2
- beqz a4, 2f
- #ifdef __XTENSA_CALL0_ABI__
- callx0 a4
- beqz a2, 9f
- #else
- mov a6, a2
- callx4 a4
- beqz a6, 9f
- mov a2, a6
+ /* Identify and process block 1 interrupts. If none are active,
+ proceed to check subsequent blocks; thus preserve a3.
+ */
+.L_xt_user_int_&level&_chk_blk1:
+ rsr a2, INTENABLE1
+ movi a6, \mask1
+ and a2, a2, a4
+ and a2, a2, a6
+ beqz a2, .L_xt_user_int_&level&_chk
+
+ /* Block 1 interrupt(s) pending */
+ debug_backtrace a0, a4, \level
+ call_exec_isr_entry_fn
+ call_int_hook \level, 1, 9f
+ extract_msb a4, a2 /* a4 = MSB of a2, a2 trashed */
+ wsr a4, INTCLEAR1 /* clear sw or edge-triggered interrupt */
+ #ifndef TX_NO_TIMER
+ #if (XT_TIMER_INTEN_BLK == 1)
+ movi a3, XT_TIMER_INTEN_BIT /* a3 = timer interrupt bit */
+ beq a3, a4, 7f /* if timer interrupt then skip table */
#endif
-2:
#endif
+ movi a5, _xt_interrupt_table + 8*32 /* a5 = dispatch table for block 1 */
+ j .L_xt_user_int_&level&_post_clear
+
+ #else /* !XT_EXTD_INTERRUPTS */
+ rsr a3, INTERRUPT
+ #endif
+
+.L_xt_user_int_&level&_chk:
+ rsr a2, INTENABLE
+ movi a4, \mask
+ and a2, a2, a3
+ and a2, a2, a4
+ beqz a2, 9f /* nothing to do */
+
+ debug_backtrace a0, a4, \level
+ call_exec_isr_entry_fn
+ call_int_hook \level, 0, 9f
/* Now look up in the dispatch table and call user ISR if any. */
/* If multiple bits are set then MSB has highest priority. */
@@ -186,7 +358,7 @@
#ifdef XT_USE_SWPRI
/* Enable all interrupts at this level that are numerically higher
than the one we just selected, since they are treated as higher
- priority.
+ priority. NOTE: SWPRI disabled for XT_EXTD_INTERRUPTS.
*/
movi a3, \mask /* a3 = all interrupts at this level */
add a2, a4, a4 /* a2 = a4 << 1 */
@@ -205,33 +377,42 @@
#endif
wsr a4, INTCLEAR /* clear sw or edge-triggered interrupt */
-
#ifndef TX_NO_TIMER
- movi a3, XT_TIMER_INTEN /* a3 = timer interrupt bit */
+ #if (XT_TIMER_INTEN_BLK == 0)
+ movi a3, XT_TIMER_INTEN_BIT /* a3 = timer interrupt bit */
beq a3, a4, 7f /* if timer interrupt then skip table */
#endif
+ #endif
+ movi a5, _xt_interrupt_table
+ /* Execution could arrive here from the direct, <= 32 interrupt case, or
+ from one of the XT_EXTD_INTERRUPTS blocks. Regardless, we have:
+ a4 = MSB (of 32-bit block) of pending interrupt bits, already cleared
+ a5 = Base of interrupt table (of 32-bit block)
+ */
+.L_xt_user_int_&level&_post_clear:
find_ms_setbit a3, a4, a3, 0 /* a3 = interrupt number */
- movi a4, _xt_interrupt_table
- addx8 a3, a3, a4 /* a3 = address of interrupt table entry */
+ addx8 a3, a3, a5 /* a3 = address of interrupt table entry */
l32i a4, a3, XIE_HANDLER /* a4 = handler address */
#ifdef __XTENSA_CALL0_ABI__
+ #ifdef XT_USE_SWPRI
mov a12, a6 /* save in callee-saved reg */
+ #endif
l32i a2, a3, XIE_ARG /* a2 = handler arg */
callx0 a4 /* call handler */
+ #ifdef XT_USE_SWPRI
mov a2, a12
- #else
+ #endif
+ #else /* !__XTENSA_CALL0_ABI__ */
+ #ifdef XT_USE_SWPRI
mov a2, a6 /* save in windowed reg */
+ #endif
l32i a6, a3, XIE_ARG /* a6 = handler arg */
callx4 a4 /* call handler */
#endif
- #ifdef XT_USE_SWPRI
j 8f
- #else
- j .L_xt_user_int_&level& /* check for more interrupts */
- #endif
7:
@@ -245,24 +426,24 @@
*/
#ifdef __XTENSA_CALL0_ABI__
+ #ifdef XT_USE_SWPRI
mov a12, a6
+ #endif
call0 XT_RTOS_TIMER_INT
+ #ifdef XT_USE_SWPRI
mov a2, a12
+ #endif
#else
+ #ifdef XT_USE_SWPRI
mov a2, a6
+ #endif
call4 XT_RTOS_TIMER_INT
#endif
.endif
#endif
- #ifdef XT_USE_SWPRI
- j 8f
- #else
- j .L_xt_user_int_&level& /* check for more interrupts */
- #endif
-
- #ifdef XT_USE_SWPRI
8:
+ #ifdef XT_USE_SWPRI
/*
Restore old value of _xt_vpri_mask from a2. Also update INTENABLE from
virtual _xt_intenable which _could_ have changed during interrupt
@@ -275,7 +456,17 @@
s32i a2, a3, 4 /* update _xt_vpri_mask */
and a4, a4, a2 /* a4 = masked intenable */
wsr a4, INTENABLE /* update INTENABLE */
- #endif
+
+ #elif XT_EXTD_INTERRUPTS
+
+ rsr a2, INTPBL /* INTPBL bit(n-1): pending Ln interrupt */
+ bbsi.l a2, \level - 1, .L_xt_user_int_&level&
+
+ #else
+
+ j .L_xt_user_int_&level& /* check for more interrupts */
+
+ #endif /* XT_USE_SWPRI */
9:
/* done */
@@ -769,7 +960,11 @@ _xt_lowint1:
/* OK to call C code at this point, dispatch user ISRs */
+#if XT_EXTD_INTERRUPTS
+ dispatch_c_isr 1 XCHAL_INTLEVEL1_MASK XCHAL_INTLEVEL1_MASK1 XCHAL_INTLEVEL1_MASK2 XCHAL_INTLEVEL1_MASK3
+#else
dispatch_c_isr 1 XCHAL_INTLEVEL1_MASK
+#endif
/* Done handling interrupts, transfer control to OS */
call0 XT_RTOS_INT_EXIT /* does not return directly here */
@@ -849,7 +1044,11 @@ _xt_medint2:
/* OK to call C code at this point, dispatch user ISRs */
+#if XT_EXTD_INTERRUPTS
+ dispatch_c_isr 2 XCHAL_INTLEVEL2_MASK XCHAL_INTLEVEL2_MASK1 XCHAL_INTLEVEL2_MASK2 XCHAL_INTLEVEL2_MASK3
+#else
dispatch_c_isr 2 XCHAL_INTLEVEL2_MASK
+#endif
/* Done handling interrupts, transfer control to OS */
call0 XT_RTOS_INT_EXIT /* does not return directly here */
@@ -920,7 +1119,11 @@ _xt_medint3:
/* OK to call C code at this point, dispatch user ISRs */
+#if XT_EXTD_INTERRUPTS
+ dispatch_c_isr 3 XCHAL_INTLEVEL3_MASK XCHAL_INTLEVEL3_MASK1 XCHAL_INTLEVEL3_MASK2 XCHAL_INTLEVEL3_MASK3
+#else
dispatch_c_isr 3 XCHAL_INTLEVEL3_MASK
+#endif
/* Done handling interrupts, transfer control to OS */
call0 XT_RTOS_INT_EXIT /* does not return directly here */
@@ -990,7 +1193,11 @@ _xt_medint4:
/* OK to call C code at this point, dispatch user ISRs */
+#if XT_EXTD_INTERRUPTS
+ dispatch_c_isr 4 XCHAL_INTLEVEL4_MASK XCHAL_INTLEVEL4_MASK1 XCHAL_INTLEVEL4_MASK2 XCHAL_INTLEVEL4_MASK3
+#else
dispatch_c_isr 4 XCHAL_INTLEVEL4_MASK
+#endif
/* Done handling interrupts, transfer control to OS */
call0 XT_RTOS_INT_EXIT /* does not return directly here */
@@ -1060,7 +1267,11 @@ _xt_medint5:
/* OK to call C code at this point, dispatch user ISRs */
+#if XT_EXTD_INTERRUPTS
+ dispatch_c_isr 5 XCHAL_INTLEVEL5_MASK XCHAL_INTLEVEL5_MASK1 XCHAL_INTLEVEL5_MASK2 XCHAL_INTLEVEL5_MASK3
+#else
dispatch_c_isr 5 XCHAL_INTLEVEL5_MASK
+#endif
/* Done handling interrupts, transfer control to OS */
call0 XT_RTOS_INT_EXIT /* does not return directly here */
@@ -1130,7 +1341,11 @@ _xt_medint6:
/* OK to call C code at this point, dispatch user ISRs */
+#if XT_EXTD_INTERRUPTS
+ dispatch_c_isr 6 XCHAL_INTLEVEL6_MASK XCHAL_INTLEVEL6_MASK1 XCHAL_INTLEVEL6_MASK2 XCHAL_INTLEVEL6_MASK3
+#else
dispatch_c_isr 6 XCHAL_INTLEVEL6_MASK
+#endif
/* Done handling interrupts, transfer control to OS */
call0 XT_RTOS_INT_EXIT /* does not return directly here */