diff options
Diffstat (limited to 'ports/xtensa/xcc/src')
| -rw-r--r-- | ports/xtensa/xcc/src/tx_clib_lock.c | 40 | ||||
| -rw-r--r-- | ports/xtensa/xcc/src/tx_initialize_low_level.c | 2 | ||||
| -rw-r--r-- | ports/xtensa/xcc/src/tx_thread_schedule.S | 27 | ||||
| -rw-r--r-- | ports/xtensa/xcc/src/tx_thread_system_return.S | 43 | ||||
| -rw-r--r-- | ports/xtensa/xcc/src/xtensa_context.S | 4 | ||||
| -rw-r--r-- | ports/xtensa/xcc/src/xtensa_intr.c | 12 | ||||
| -rw-r--r-- | ports/xtensa/xcc/src/xtensa_intr_asm.S | 5 | ||||
| -rw-r--r-- | ports/xtensa/xcc/src/xtensa_intr_wrapper.c | 2 | ||||
| -rw-r--r-- | ports/xtensa/xcc/src/xtensa_vectors.S | 321 |
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 */ |
