mirror of
https://github.com/espressif/ESP8266_RTOS_SDK.git
synced 2025-07-15 08:32:42 +08:00
feat(esp8266): Add fucntion to pass compiling
Remove unused code.
This commit is contained in:
@ -10,7 +10,6 @@
|
||||
*/
|
||||
#include <xtensa/coreasm.h>
|
||||
#include <xtensa/config/specreg.h>
|
||||
#include "xtos-internal.h"
|
||||
|
||||
#include "freertos/xtensa_rtos.h"
|
||||
|
||||
@ -23,6 +22,14 @@
|
||||
// .section .iram.text
|
||||
.section .text
|
||||
|
||||
.macro xtos_lock ax
|
||||
rsil \ax, XCHAL_EXCM_LEVEL
|
||||
.endm
|
||||
|
||||
.macro xtos_unlock ax
|
||||
wsr \ax, PS
|
||||
.endm
|
||||
|
||||
/*
|
||||
**********************************************************************************************************
|
||||
* vPortYield
|
||||
|
@ -53,865 +53,29 @@ NOTES on the use of 'call0' for long jumps instead of 'j':
|
||||
#include <xtensa/coreasm.h>
|
||||
#include <xtensa/config/system.h>
|
||||
#include <xtensa/config/specreg.h>
|
||||
#include "xtos-internal.h"
|
||||
#include <xtensa/xtruntime-frames.h>
|
||||
#include "freertos/xtensa_rtos.h"
|
||||
|
||||
#ifdef FOR_BAOFENG
|
||||
|
||||
#define _INTERRUPT_LEVEL 3
|
||||
|
||||
STRUCT_BEGIN
|
||||
STRUCT_FIELD (long,4,HESF_,SAR)
|
||||
STRUCT_FIELD (long,4,HESF_,WINDOWSTART)
|
||||
STRUCT_FIELD (long,4,HESF_,WINDOWBASE)
|
||||
STRUCT_FIELD (long,4,HESF_,EPC1)
|
||||
STRUCT_FIELD (long,4,HESF_,EXCCAUSE)
|
||||
STRUCT_FIELD (long,4,HESF_,EXCVADDR)
|
||||
STRUCT_FIELD (long,4,HESF_,EXCSAVE1)
|
||||
STRUCT_FIELD (long,4,HESF_,VPRI) /* (XEA1 only) */
|
||||
#if XCHAL_HAVE_MAC16
|
||||
STRUCT_FIELD (long,4,HESF_,ACCLO)
|
||||
STRUCT_FIELD (long,4,HESF_,ACCHI)
|
||||
/*STRUCT_AFIELD(long,4,HESF_,MR, 4)*/
|
||||
#endif
|
||||
#if XCHAL_HAVE_LOOPS
|
||||
STRUCT_FIELD (long,4,HESF_,LCOUNT)
|
||||
STRUCT_FIELD (long,4,HESF_,LBEG)
|
||||
STRUCT_FIELD (long,4,HESF_,LEND)
|
||||
#endif
|
||||
STRUCT_AFIELD(long,4,HESF_,AREG, 64) /* address registers ar0..ar63 */
|
||||
#define HESF_AR(n) HESF_AREG+((n)*4)
|
||||
STRUCT_END(HighPriFrame)
|
||||
#define HESF_TOTALSIZE HighPriFrameSize+32 /* 32 bytes for interrupted code's save areas under SP */
|
||||
|
||||
|
||||
#if XCHAL_HAVE_XEA1 && HAVE_XSR /* could be made true for T1040 and T1050 */
|
||||
# error "high-priority interrupt stack frame needs adjustment if HAVE_XSR is allowed with XEA1"
|
||||
#endif
|
||||
|
||||
|
||||
#define PRI_N_STACK_SIZE 2048 /* default to 1 kB stack for each level-N handling */
|
||||
|
||||
|
||||
// Allocate save area and stack:
|
||||
// (must use .bss, not .comm, because the subsequent .set does not work otherwise)
|
||||
.section .bss, "aw"
|
||||
.align 16
|
||||
LABEL(_Pri_,_Stack): .space PRI_N_STACK_SIZE + HESF_TOTALSIZE
|
||||
|
||||
#if HAVE_XSR
|
||||
.data
|
||||
.global LABEL(_Pri_,_HandlerAddress)
|
||||
LABEL(_Pri_,_HandlerAddress): .space 4
|
||||
#endif
|
||||
|
||||
.section .UserEnter.text, "ax"
|
||||
.global call_user_start
|
||||
.type call_user_start,@function
|
||||
.align 4
|
||||
.literal_position
|
||||
call_user_start:
|
||||
|
||||
movi a2, 0x40100000 /* note: absolute symbol, not a ptr */
|
||||
wsr a2, vecbase
|
||||
call0 user_start /* user exception handler */
|
||||
|
||||
#if 0
|
||||
/*
|
||||
Panic handler.
|
||||
Should be reached by call0 (preferable) or jump only. If call0, a0 says where
|
||||
from. If on simulator, display panic message and abort, else loop indefinitely.
|
||||
*/
|
||||
// .section .iram.text
|
||||
.section .text
|
||||
.global _xt_panic
|
||||
.type _xt_panic,@function
|
||||
.align 4
|
||||
_xt_panic:
|
||||
#ifdef XT_SIMULATOR
|
||||
addi a4, a0, -3 /* point to call0 */
|
||||
movi a3, _xt_panic_message
|
||||
movi a2, SYS_log_msg
|
||||
simcall
|
||||
movi a2, SYS_gdb_abort
|
||||
simcall
|
||||
#else
|
||||
rsil a2, XCHAL_EXCM_LEVEL /* disable all low & med ints */
|
||||
1: j 1b /* loop infinitely */
|
||||
#endif
|
||||
|
||||
.section .rodata, "a"
|
||||
.align 4
|
||||
_xt_panic_message:
|
||||
.string "\n*** _xt_panic() was called from 0x%08x or jumped to. ***\n"
|
||||
#endif
|
||||
|
||||
#ifdef XT_INTEXC_HOOKS
|
||||
/*
|
||||
Hooks to dynamically install handlers for exceptions and interrupts.
|
||||
Allows automated regression frameworks to install handlers per test.
|
||||
Consists of an array of function pointers indexed by interrupt level,
|
||||
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.
|
||||
*/
|
||||
.data
|
||||
.global _xt_intexc_hooks
|
||||
.type _xt_intexc_hooks,@object
|
||||
.align 4
|
||||
_xt_intexc_hooks:
|
||||
.fill XT_INTEXC_HOOK_NUM, 4, 0
|
||||
#endif
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
|
||||
EXCEPTION AND LEVEL 1 INTERRUPT VECTORS AND LOW LEVEL HANDLERS
|
||||
(except window exception vectors).
|
||||
|
||||
Each vector goes at a predetermined location according to the Xtensa
|
||||
hardware configuration, which is ensured by its placement in a special
|
||||
section known to the Xtensa linker support package (LSP). It performs
|
||||
the minimum necessary before jumping to the handler in the .text section.
|
||||
|
||||
The corresponding handler goes in the normal .text section. It sets up
|
||||
the appropriate stack frame, saves a few vector-specific registers and
|
||||
calls XT_RTOS_INT_ENTER to save the rest of the interrupted context
|
||||
and enter the RTOS, then sets up a C environment. It then calls the
|
||||
user's interrupt handler code (which may be coded in C) and finally
|
||||
calls XT_RTOS_INT_EXIT to transfer control to the RTOS for scheduling.
|
||||
|
||||
While XT_RTOS_INT_EXIT does not return directly to the interruptee,
|
||||
eventually the RTOS scheduler will want to dispatch the interrupted
|
||||
task or handler. The scheduler will return to the exit point that was
|
||||
saved in the interrupt stack frame at XT_STK_EXIT.
|
||||
Add to compile passing.
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
/*
|
||||
--------------------------------------------------------------------------------
|
||||
Debug Exception.
|
||||
--------------------------------------------------------------------------------
|
||||
*/
|
||||
#undef HAVE_XSR
|
||||
#define HAVE_XSR 1
|
||||
|
||||
#if XCHAL_HAVE_DEBUG
|
||||
#define _JOIN2(a, b) a ## b
|
||||
#define _JOIN3(a, b, c) a ## b ## c
|
||||
|
||||
.begin literal_prefix .DebugExceptionVector
|
||||
.section .DebugExceptionVector.text, "ax"
|
||||
.global _DebugExceptionVector
|
||||
.align 4
|
||||
.literal_position
|
||||
_DebugExceptionVector:
|
||||
#define JOIN2(a, b) _JOIN2(a, b)
|
||||
#define JOIN3(a, b, c) _JOIN3(a, b, c)
|
||||
|
||||
#ifdef XT_SIMULATOR
|
||||
/*
|
||||
In the simulator, let the debugger (if any) handle the debug exception,
|
||||
or simply stop the simulation:
|
||||
*/
|
||||
wsr a2, EXCSAVE+XCHAL_DEBUGLEVEL /* save a2 where sim expects it */
|
||||
movi a2, SYS_gdb_enter_sktloop
|
||||
simcall /* have ISS handle debug exc. */
|
||||
#elif 0 /* change condition to 1 to use the HAL minimal debug handler */
|
||||
wsr a3, EXCSAVE+XCHAL_DEBUGLEVEL
|
||||
movi a3, xthal_debugexc_defhndlr_nw /* use default debug handler */
|
||||
jx a3
|
||||
#else
|
||||
wsr a0, EXCSAVE+XCHAL_DEBUGLEVEL /* save original a0 somewhere */
|
||||
call0 user_fatal_exception_handler /* does not return */
|
||||
rfi XCHAL_DEBUGLEVEL /* make a0 point here not later */
|
||||
#endif
|
||||
#define LABEL(a, b) _JOIN3(a, 3, b)
|
||||
|
||||
.end literal_prefix
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
--------------------------------------------------------------------------------
|
||||
Double Exception.
|
||||
Double exceptions are not a normal occurrence. They indicate a bug of some kind.
|
||||
--------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifdef XCHAL_DOUBLEEXC_VECTOR_VADDR
|
||||
|
||||
.begin literal_prefix .DoubleExceptionVector
|
||||
.section .DoubleExceptionVector.text, "ax"
|
||||
.global _DoubleExceptionVector
|
||||
.align 4
|
||||
.literal_position
|
||||
_DoubleExceptionVector:
|
||||
|
||||
#if XCHAL_HAVE_DEBUG
|
||||
break 1, 4 /* unhandled double exception */
|
||||
#endif
|
||||
call0 user_fatal_exception_handler /* does not return */
|
||||
rfde /* make a0 point here not later */
|
||||
|
||||
.end literal_prefix
|
||||
|
||||
#endif /* XCHAL_DOUBLEEXC_VECTOR_VADDR */
|
||||
|
||||
/*
|
||||
--------------------------------------------------------------------------------
|
||||
Kernel Exception (including Level 1 Interrupt from kernel mode).
|
||||
--------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
.begin literal_prefix .KernelExceptionVector
|
||||
.section .KernelExceptionVector.text, "ax"
|
||||
.global _KernelExceptionVector
|
||||
.align 4
|
||||
.literal_position
|
||||
_KernelExceptionVector:
|
||||
|
||||
wsr a0, EXCSAVE_1 /* preserve a0 */
|
||||
call0 _xt_kernel_exc /* kernel exception handler */
|
||||
/* never returns here - call0 is used as a jump (see note at top) */
|
||||
|
||||
.end literal_prefix
|
||||
|
||||
// .section .iram.text
|
||||
.section .text
|
||||
.align 4
|
||||
.literal_position
|
||||
_xt_kernel_exc:
|
||||
#if XCHAL_HAVE_DEBUG
|
||||
break 1, 0 /* unhandled kernel exception */
|
||||
#endif
|
||||
call0 user_fatal_exception_handler /* does not return */
|
||||
rfe /* make a0 point here not there */
|
||||
|
||||
|
||||
/*
|
||||
--------------------------------------------------------------------------------
|
||||
User Exception (including Level 1 Interrupt from user mode).
|
||||
--------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
.begin literal_prefix .UserExceptionVector
|
||||
.section .UserExceptionVector.text, "ax"
|
||||
.global _UserExceptionVector
|
||||
.type _UserExceptionVector,@function
|
||||
.align 4
|
||||
.literal_position
|
||||
_UserExceptionVector:
|
||||
|
||||
wsr a0, EXCSAVE_1 /* preserve a0 */
|
||||
call0 _xt_user_exc /* user exception handler */
|
||||
/* never returns here - call0 is used as a jump (see note at top) */
|
||||
|
||||
.end literal_prefix
|
||||
|
||||
// .section .iram.text
|
||||
.section .text
|
||||
/*
|
||||
Insert some waypoints for jumping beyond the signed 8-bit range
|
||||
of conditional branch instructions, so the conditional branchces
|
||||
to specific-cause exception handlers are not taken in the mainline.
|
||||
Saves some cycles in the mainline.
|
||||
*/
|
||||
|
||||
#if XCHAL_HAVE_WINDOWED
|
||||
.align 4
|
||||
_xt_to_alloca_exc:
|
||||
call0 _xt_alloca_exc /* in window vectors section */
|
||||
/* never returns here - call0 is used as a jump (see note at top) */
|
||||
#endif
|
||||
|
||||
.align 4
|
||||
.literal_position
|
||||
_xt_to_syscall_exc:
|
||||
call0 _xt_syscall_exc
|
||||
/* never returns here - call0 is used as a jump (see note at top) */
|
||||
|
||||
/* User exception handler begins here. */
|
||||
.type _xt_user_exc,@function
|
||||
.align 4
|
||||
_xt_user_exc:
|
||||
/*
|
||||
Handle alloca and syscall exceptions before allocating stack frame and
|
||||
interacting with RTOS.
|
||||
*/
|
||||
rsr a0, EXCCAUSE
|
||||
#if XCHAL_HAVE_WINDOWED
|
||||
beqi a0, EXCCAUSE_ALLOCA, _xt_to_alloca_exc
|
||||
#endif
|
||||
beqi a0, EXCCAUSE_SYSCALL, _xt_to_syscall_exc
|
||||
|
||||
/* Allocate interrupt stack frame and save minimal context. */
|
||||
mov a0, sp /* sp == a1 */
|
||||
addi sp, sp, -XT_STK_FRMSZ /* allocate interrupt stack frame */
|
||||
s32i a0, sp, XT_STK_A1 /* save pre-interrupt SP */
|
||||
rsr a0, PS /* save interruptee's PS */
|
||||
s32i a0, sp, XT_STK_PS
|
||||
rsr a0, EPC_1 /* save interruptee's PC */
|
||||
s32i a0, sp, XT_STK_PC
|
||||
rsr a0, EXCSAVE_1 /* save interruptee's a0 */
|
||||
s32i a0, sp, XT_STK_A0
|
||||
movi a0, _xt_user_exit /* save exit point for dispatch */
|
||||
s32i a0, sp, XT_STK_EXIT
|
||||
|
||||
/*
|
||||
Handle co-processor exceptions after allocating stack frame and before
|
||||
interacting with RTOS.
|
||||
*/
|
||||
#if XCHAL_CP_NUM > 0
|
||||
rsr a0, EXCCAUSE
|
||||
bgeui a0, EXCCAUSE_CP0_DISABLED, _xt_to_coproc_exc
|
||||
.L_xt_user_exc_not_coproc:
|
||||
#endif
|
||||
|
||||
/* Save rest of interrupt context and enter RTOS. */
|
||||
call0 XT_RTOS_INT_ENTER /* common RTOS interrupt entry */
|
||||
|
||||
/* !! We are now on the RTOS system stack !! */
|
||||
|
||||
/* Set up PS for C, reenable hi-pri interrupts, and clear EXCM. */
|
||||
#ifdef __XTENSA_CALL0_ABI__
|
||||
movi a0, PS_INTLEVEL(XCHAL_EXCM_LEVEL) | PS_UM
|
||||
#else
|
||||
movi a0, PS_INTLEVEL(XCHAL_EXCM_LEVEL) | PS_UM | PS_WOE
|
||||
#endif
|
||||
wsr a0, PS
|
||||
rsync
|
||||
|
||||
/* !! It is OK to call C handlers after this point. !! */
|
||||
|
||||
/* Handle exceptions per EXCCAUSE. */
|
||||
rsr a2, EXCCAUSE /* a2 = exception cause */
|
||||
beqi a2, EXCCAUSE_LEVEL1INTERRUPT, .L_xt_user_int /* level 3 int */
|
||||
|
||||
#ifdef XT_INTEXC_HOOKS
|
||||
/*
|
||||
Call exception hook to pre-handle exceptions (if installed).
|
||||
Pass EXCCAUSE in a2, and check result in a2 (if -1, skip default handling).
|
||||
*/
|
||||
movi a0, _xt_intexc_hooks
|
||||
l32i a0, a0, 0 /* user exception hook index 0 */
|
||||
beqz a0, 1f
|
||||
.Ln_xt_user_exc_call_hook:
|
||||
#ifdef __XTENSA_CALL0_ABI__
|
||||
callx0 a0
|
||||
beqi a2, -1, .L_xt_user_done
|
||||
#else
|
||||
mov a6, a2
|
||||
callx4 a0
|
||||
beqi a6, -1, .L_xt_user_done
|
||||
mov a2, a6
|
||||
#endif
|
||||
1:
|
||||
#endif
|
||||
|
||||
/* USER_EDIT:
|
||||
ADD ANY CUSTOM EXCEPTION HANDLER CODE HERE, OR CALL C HANDLER.
|
||||
The exeption cause is in A2. After handling, jump to .L_xt_user_int .
|
||||
Note on Call0 ABI: Callee-saved regs (a12-15) have not yet been saved,
|
||||
so should not be corrupted here. A C handler will not corrupt them.
|
||||
*/
|
||||
|
||||
/* If we get here, the exception has not been handled. */
|
||||
.Ln_xt_user_unhandled:
|
||||
#if XCHAL_HAVE_DEBUG
|
||||
break 1, 1 /* unhandled user exception */
|
||||
#endif
|
||||
call0 user_fatal_exception_handler
|
||||
|
||||
/* Handle level 1 interrupts. OK to enable med-pri interrupts now. */
|
||||
.L_xt_user_int:
|
||||
rsil a0, 1 /* reenable ints above level 1 */
|
||||
|
||||
/*
|
||||
Get mask of pending, enabled interrupts at this level into a2.
|
||||
Comment this out if there is only one interrupt at this level.
|
||||
*/
|
||||
rsr a2, INTENABLE
|
||||
rsr a3, INTERRUPT
|
||||
movi a4, XCHAL_INTLEVEL1_MASK
|
||||
and a2, a2, a3
|
||||
and a2, a2, a4
|
||||
|
||||
#ifdef XT_INTEXC_HOOKS
|
||||
/* Call interrupt hook if present to (pre)handle interrupts. */
|
||||
movi a0, _xt_intexc_hooks
|
||||
l32i a0, a0, 1<<2
|
||||
beqz a0, 2f
|
||||
.Ln_xt_user_int_call_hook:
|
||||
#ifdef __XTENSA_CALL0_ABI__
|
||||
callx0 a0
|
||||
beqz a2, .L_xt_user_done
|
||||
#else
|
||||
mov a6, a2
|
||||
callx4 a0
|
||||
beqz a6, .L_xt_user_done
|
||||
mov a2, a6
|
||||
#endif
|
||||
2:
|
||||
#endif
|
||||
|
||||
/* USER_EDIT:
|
||||
ADD LOW PRIORITY LEVEL 1 INTERRUPT HANDLER CODE HERE, OR CALL C HANDLER.
|
||||
At this point, a2 contains a mask of pending, enabled ints at this level.
|
||||
Note on Call0 ABI: Callee-saved regs (a12-15) have not yet been saved,
|
||||
so should not be corrupted here. A C handler will not corrupt them.
|
||||
HANDLER MUST CAUSE LEVEL TRIGGERED INTERRUPT REQUESTS TO BE DEASSERTED.
|
||||
When done, ensure a2 contains a mask of unhandled (still pending)
|
||||
enabled ints at this level, and fall through.
|
||||
*/
|
||||
|
||||
#if XT_TIMER_INTPRI == 1
|
||||
.Ln_xt_user_int_timer:
|
||||
movi a3, 0xFFBF
|
||||
and a3, a2, a3
|
||||
bnez a3, 3f
|
||||
/* Interrupt handler for the RTOS tick timer if at this level. */
|
||||
movi a3, XT_TIMER_INTEN /* timer interrupt bit */
|
||||
/*bnone a2, a3, 3f*/
|
||||
#ifdef __XTENSA_CALL0_ABI__
|
||||
sub a12, a2, a3 /* clear timer int and save mask */
|
||||
call0 XT_RTOS_TIMER_INT
|
||||
mov a2, a12 /* recover mask of remaining ints */
|
||||
beqz a2, 4f
|
||||
#else
|
||||
call4 XT_RTOS_TIMER_INT /* a2 automatically preserved */
|
||||
sub a2, a2, a3 /* clear timer int from mask */
|
||||
#endif
|
||||
3:
|
||||
call0 _xt_isr_handler
|
||||
bnez a2, .Ln_xt_user_int_timer
|
||||
#endif
|
||||
4:
|
||||
/* All interrupts at this level should have been handled now. */
|
||||
beqz a2, .L_xt_user_done
|
||||
|
||||
/* If we get here, we have an unhandled interrupt. */
|
||||
#if XCHAL_HAVE_DEBUG
|
||||
break 1, 1 /* unhandled user exception */
|
||||
/* EXCCAUSE == 4 (level 1 int) */
|
||||
#endif
|
||||
call0 user_fatal_exception_handler
|
||||
|
||||
/* Done handling after XT_RTOS_INT_ENTER. Give control to RTOS. */
|
||||
.L_xt_user_done:
|
||||
call0 XT_RTOS_INT_EXIT /* does not return directly here */
|
||||
|
||||
/*
|
||||
Exit point for dispatch. Saved in interrupt stack frame at XT_STK_EXIT
|
||||
on entry and used to return to a thread or interrupted interrupt handler.
|
||||
*/
|
||||
.global _xt_user_exit
|
||||
.type _xt_user_exit,@function
|
||||
.align 4
|
||||
_xt_user_exit:
|
||||
l32i a0, sp, XT_STK_PS /* retrieve interruptee's PS */
|
||||
wsr a0, PS
|
||||
l32i a0, sp, XT_STK_PC /* retrieve interruptee's PC */
|
||||
wsr a0, EPC_1
|
||||
l32i a0, sp, XT_STK_A0 /* retrieve interruptee's A0 */
|
||||
l32i sp, sp, XT_STK_A1 /* remove interrupt stack frame */
|
||||
rsync /* ensure PS and EPC written */
|
||||
rfe /* PS.EXCM is cleared */
|
||||
|
||||
/*
|
||||
--------------------------------------------------------------------------------
|
||||
Syscall Exception Handler (jumped to from User Exception Handler).
|
||||
Syscall 0 is required to spill the register windows (no-op in Call 0 ABI).
|
||||
Only syscall 0 is handled here. Other syscalls return -1 to caller in a2.
|
||||
--------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
// .section .iram.text
|
||||
.section .text
|
||||
.type _xt_syscall_exc,@function
|
||||
.align 4
|
||||
_xt_syscall_exc:
|
||||
|
||||
#ifdef __XTENSA_CALL0_ABI__
|
||||
/*
|
||||
Save minimal regs for scratch. Syscall 0 does nothing in Call0 ABI.
|
||||
Use a minimal stack frame (16B) to save A2 & A3 for scratch.
|
||||
PS.EXCM could be cleared here, but unlikely to improve worst-case latency.
|
||||
rsr a0, PS
|
||||
addi a0, a0, -PS_EXCM_MASK
|
||||
wsr a0, PS
|
||||
*/
|
||||
addi sp, sp, -16
|
||||
s32i a2, sp, 8
|
||||
s32i a3, sp, 12
|
||||
#else /* Windowed ABI */
|
||||
/*
|
||||
Save necessary context and spill the register windows.
|
||||
PS.EXCM is still set and must remain set until after the spill.
|
||||
Reuse context save function though it saves more than necessary.
|
||||
For this reason, a full interrupt stack frame is allocated.
|
||||
*/
|
||||
addi sp, sp, -XT_STK_FRMSZ /* allocate interrupt stack frame */
|
||||
s32i a12, sp, XT_STK_A12 /* _xt_context_save requires A12- */
|
||||
s32i a13, sp, XT_STK_A13 /* A13 to have already been saved */
|
||||
call0 _xt_context_save
|
||||
#endif
|
||||
|
||||
/*
|
||||
Grab the interruptee's PC and skip over the 'syscall' instruction.
|
||||
If it's at the end of a zero-overhead loop and it's not on the last
|
||||
iteration, decrement loop counter and skip to beginning of loop.
|
||||
*/
|
||||
rsr a2, EPC_1 /* a2 = PC of 'syscall' */
|
||||
addi a3, a2, 3 /* ++PC */
|
||||
#if XCHAL_HAVE_LOOPS
|
||||
rsr a0, LEND /* if (PC == LEND */
|
||||
bne a3, a0, 1f
|
||||
rsr a0, LCOUNT /* && LCOUNT != 0) */
|
||||
beqz a0, 1f /* { */
|
||||
addi a0, a0, -1 /* --LCOUNT */
|
||||
rsr a3, LBEG /* PC = LBEG */
|
||||
wsr a0, LCOUNT /* } */
|
||||
#endif
|
||||
1: wsr a3, EPC_1 /* update PC */
|
||||
|
||||
/* Restore interruptee's context and return from exception. */
|
||||
#ifdef __XTENSA_CALL0_ABI__
|
||||
l32i a2, sp, 8
|
||||
l32i a3, sp, 12
|
||||
addi sp, sp, 16
|
||||
#else
|
||||
call0 _xt_context_restore
|
||||
addi sp, sp, XT_STK_FRMSZ
|
||||
#endif
|
||||
movi a0, -1
|
||||
movnez a2, a0, a2 /* return -1 if not syscall 0 */
|
||||
rsr a0, EXCSAVE_1
|
||||
rfe
|
||||
|
||||
|
||||
/*
|
||||
Currently only shells for high priority interrupt handlers are provided
|
||||
here. However a template and example can be found in the Tensilica tools
|
||||
documentation: "Microprocessor Programmer's Guide".
|
||||
*/
|
||||
|
||||
#if XCHAL_HAVE_NMI
|
||||
|
||||
.begin literal_prefix .NMIExceptionVector
|
||||
.section .NMIExceptionVector.text, "ax"
|
||||
.global _NMIExceptionVector
|
||||
.type _NMIExceptionVector,@function
|
||||
.align 4
|
||||
.literal_position
|
||||
_NMIExceptionVector:
|
||||
wsr a0, EXCSAVE + XCHAL_NMILEVEL _ /* preserve a0 */
|
||||
call0 _xt_nmi /* load interrupt handler */
|
||||
/* never returns here - call0 is used as a jump (see note at top) */
|
||||
|
||||
.end literal_prefix
|
||||
|
||||
// .section .iram.text
|
||||
.section .text
|
||||
.type _xt_nmi,@function
|
||||
.align 4
|
||||
_xt_nmi:
|
||||
|
||||
#ifdef XT_INTEXC_HOOKS
|
||||
/* Call interrupt hook if present to (pre)handle interrupts. */
|
||||
movi a0, _xt_intexc_hooks
|
||||
l32i a0, a0, XCHAL_NMILEVEL<<2
|
||||
beqz a0, 1f
|
||||
.Ln_xt_nmi_call_hook:
|
||||
callx0 a0 /* must NOT disturb stack! */
|
||||
1:
|
||||
#endif
|
||||
|
||||
/* USER_EDIT:
|
||||
ADD HIGH PRIORITY NON-MASKABLE INTERRUPT (NMI) HANDLER CODE HERE.
|
||||
*/
|
||||
|
||||
movi a0, LABEL(_Pri_,_Stack) + PRI_N_STACK_SIZE // get ptr to save area
|
||||
// interlock
|
||||
|
||||
// Save a few registers so we can do some work:
|
||||
s32i a2, a0, HESF_AR(2)
|
||||
#if HAVE_XSR
|
||||
//movi a0, LABEL(_Level,FromVector) // this dispatcher's address
|
||||
movi a2, LABEL(_Pri_,_HandlerAddress) // dispatcher address var.
|
||||
s32i a1, a0, HESF_AR(1)
|
||||
l32i a2, a2, 0 // get dispatcher address
|
||||
s32i a3, a0, HESF_AR(3)
|
||||
xsr a2, EXCSAVE_LEVEL // get saved a0, restore dispatcher address
|
||||
#else
|
||||
rsr a2, EXCSAVE_LEVEL // get saved a0
|
||||
s32i a1, a0, HESF_AR(1)
|
||||
s32i a3, a0, HESF_AR(3)
|
||||
#endif
|
||||
s32i a4, a0, HESF_AR(4)
|
||||
s32i a2, a0, HESF_AR(0)
|
||||
|
||||
// Save/restore all exception state
|
||||
// (IMPORTANT: this code assumes no general exceptions occur
|
||||
// during the execution of this dispatcher until this state
|
||||
// is completely saved and from the point it is restored.)
|
||||
//
|
||||
// Exceptions that may normally occur within the C handler
|
||||
// include window exceptions (affecting EPC1), alloca exceptions
|
||||
// (affecting EPC1/EXCCAUSE and its handling uses EXCSAVE1),
|
||||
// and possibly others depending on the particular C handler
|
||||
// (possibly needing save/restore of EXCVADDR; and EXCVADDR
|
||||
// is also possibly corrupted by any access thru an auto-refill
|
||||
// way on a processor with a full MMU).
|
||||
//
|
||||
rsr a3, EPC1
|
||||
rsr a4, EXCCAUSE
|
||||
s32i a3, a0, HESF_EPC1
|
||||
s32i a4, a0, HESF_EXCCAUSE
|
||||
#if !XCHAL_HAVE_XEA1
|
||||
rsr a3, EXCVADDR
|
||||
s32i a3, a0, HESF_EXCVADDR
|
||||
#endif
|
||||
rsr a4, EXCSAVE1
|
||||
s32i a4, a0, HESF_EXCSAVE1
|
||||
|
||||
#ifdef __XTENSA_WINDOWED_ABI__
|
||||
// Save remainder of entire address register file (!):
|
||||
movi a2, XCHAL_NUM_AREGS - 8 // how many saved so far
|
||||
#endif
|
||||
|
||||
s32i a5, a0, HESF_AR(5)
|
||||
s32i a6, a0, HESF_AR(6)
|
||||
s32i a7, a0, HESF_AR(7)
|
||||
|
||||
1: s32i a8, a0, HESF_AR(8)
|
||||
s32i a9, a0, HESF_AR(9)
|
||||
s32i a10, a0, HESF_AR(10)
|
||||
s32i a11, a0, HESF_AR(11)
|
||||
s32i a12, a0, HESF_AR(12)
|
||||
s32i a13, a0, HESF_AR(13)
|
||||
s32i a14, a0, HESF_AR(14)
|
||||
s32i a15, a0, HESF_AR(15)
|
||||
|
||||
#ifdef __XTENSA_WINDOWED_ABI__
|
||||
addi a8, a2, -8
|
||||
addi a10, a0, 8*4
|
||||
rotw 2
|
||||
bnez a2, 1b // loop until done
|
||||
|
||||
rotw 2
|
||||
// back to original a2 ...
|
||||
|
||||
// Save a few other registers required for C:
|
||||
rsr a3, WINDOWSTART
|
||||
rsr a4, WINDOWBASE
|
||||
s32i a3, a0, HESF_WINDOWSTART
|
||||
s32i a4, a0, HESF_WINDOWBASE
|
||||
|
||||
// Setup window registers for first caller:
|
||||
movi a3, 1
|
||||
movi a4, 0
|
||||
wsr a3, WINDOWSTART
|
||||
wsr a4, WINDOWBASE
|
||||
rsync
|
||||
|
||||
// Note: register window has rotated, ie. a0..a15 clobbered.
|
||||
|
||||
#endif /* __XTENSA_WINDOWED_ABI__ */
|
||||
|
||||
movi a1, LABEL(_Pri_,_Stack) + PRI_N_STACK_SIZE // get ptr to save area (is also initial stack ptr)
|
||||
movi a0, 0 // mark start of call frames in stack
|
||||
|
||||
// Critical state saved, a bit more to do to allow window exceptions...
|
||||
|
||||
// We now have a C-coherent stack and window state.
|
||||
// Still have to fix PS while making sure interrupts stay disabled
|
||||
// at the appropriate level (ie. level 2 and below are disabled in this case).
|
||||
|
||||
#if XCHAL_HAVE_XEA1
|
||||
movi a7, _xtos_intstruct // address of interrupt management globals
|
||||
rsilft a3, _INTERRUPT_LEVEL, XTOS_LOCKLEVEL // lockout
|
||||
movi a4, ~INTLEVEL_N_BELOW_MASK // mask out all interrupts at this level or lower
|
||||
l32i a3, a7, XTOS_VPRI_ENABLED_OFS // read previous _xtos_vpri_enabled
|
||||
l32i a5, a7, XTOS_ENABLED_OFS // read _xtos_enabled
|
||||
s32i a4, a7, XTOS_VPRI_ENABLED_OFS // set new _xtos_vpri_enabled (mask interrupts as if at _INTERRUPT_LEVEL)
|
||||
s32i a3, a1, HESF_VPRI // save previous vpri
|
||||
movi a2, 0x50020 // WOE=1, UM=1, INTLEVEL=0
|
||||
and a3, a5, a4 // mask out selected interrupts
|
||||
wsr a3, INTENABLE // disable all low-priority interrupts
|
||||
#else
|
||||
// Load PS for C code, clear EXCM (NOTE: this step is different for XEA1):
|
||||
# ifdef __XTENSA_CALL0_ABI__
|
||||
movi a2, 0x00020 + _INTERRUPT_LEVEL // WOE=0, CALLINC=0, UM=1, INTLEVEL=N, EXCM=0, RING=0
|
||||
# else
|
||||
movi a2, 0x50020 + _INTERRUPT_LEVEL // WOE=1, CALLINC=1, UM=1, INTLEVEL=N, EXCM=0, RING=0
|
||||
# endif
|
||||
|
||||
#endif
|
||||
wsr a2, PS // update PS to enable window exceptions, etc as per above
|
||||
rsync
|
||||
|
||||
// Okay, window exceptions can now happen (although we have to call
|
||||
// deep before any will happen because we've reset WINDOWSTART).
|
||||
|
||||
// Save other state that might get clobbered by C code:
|
||||
|
||||
////////////////// COMMON DISPATCH CODE BEGIN
|
||||
|
||||
rsr a14, SAR
|
||||
s32i a14, a1, HESF_SAR
|
||||
#if XCHAL_HAVE_LOOPS
|
||||
rsr a14, LCOUNT
|
||||
s32i a14, a1, HESF_LCOUNT
|
||||
rsr a14, LBEG
|
||||
s32i a14, a1, HESF_LBEG
|
||||
rsr a14, LEND
|
||||
s32i a14, a1, HESF_LEND
|
||||
#endif
|
||||
#if XCHAL_HAVE_MAC16
|
||||
rsr a14, ACCLO
|
||||
s32i a14, a1, HESF_ACCLO
|
||||
rsr a14, ACCHI
|
||||
s32i a14, a1, HESF_ACCHI
|
||||
#endif
|
||||
|
||||
#ifdef __XTENSA_CALL0_ABI__
|
||||
#ifdef FOR_BAOFENG
|
||||
movi a13, NMI_Handler
|
||||
#else
|
||||
movi a13, wDev_ProcessFiq
|
||||
#endif
|
||||
callx0 a13 // call interrupt's C handler
|
||||
#else
|
||||
movi a13, NMI_Handler
|
||||
callx4 a13 // call interrupt's C handler
|
||||
#endif
|
||||
|
||||
// Restore everything, and return.
|
||||
|
||||
// Three temp registers are required for this code to be optimal (no interlocks) in
|
||||
// T2xxx microarchitectures with 7-stage pipe; otherwise only two
|
||||
// registers would be needed.
|
||||
//
|
||||
#if XCHAL_HAVE_LOOPS
|
||||
l32i a13, a1, HESF_LCOUNT
|
||||
l32i a14, a1, HESF_LBEG
|
||||
l32i a15, a1, HESF_LEND
|
||||
wsr a13, LCOUNT
|
||||
wsr a14, LBEG
|
||||
wsr a15, LEND
|
||||
#endif
|
||||
|
||||
#if XCHAL_HAVE_MAC16
|
||||
l32i a13, a1, HESF_ACCLO
|
||||
l32i a14, a1, HESF_ACCHI
|
||||
wsr a13, ACCLO
|
||||
wsr a14, ACCHI
|
||||
#endif
|
||||
l32i a15, a1, HESF_SAR
|
||||
wsr a15, SAR
|
||||
|
||||
////////////////// COMMON DISPATCH CODE END
|
||||
|
||||
#if XCHAL_HAVE_XEA1
|
||||
// Here, a7 = address of interrupt management globals
|
||||
l32i a4, a1, HESF_VPRI // restore previous vpri
|
||||
rsil a3, XTOS_LOCKLEVEL // lockout
|
||||
l32i a5, a7, XTOS_ENABLED_OFS // read _xtos_enabled
|
||||
s32i a4, a7, XTOS_VPRI_ENABLED_OFS // set new _xtos_vpri_enabled
|
||||
movi a2, 0x00020 + _INTERRUPT_LEVEL // WOE=0, UM=1, INTLEVEL=N
|
||||
/* movi a2, 0x00020 + 0 // WOE=0, UM=1, INTLEVEL=N */
|
||||
and a3, a5, a4 // mask out selected interrupts
|
||||
wsr a3, INTENABLE // disable all low-priority interrupts
|
||||
#else
|
||||
// Load PS for interrupt exit, set EXCM:
|
||||
movi a2, 0x00030 + _INTERRUPT_LEVEL // WOE=0, CALLINC=0, UM=1, INTLEVEL=N, EXCM=1, RING=0
|
||||
/* movi a2, 0x00030 + 0 // WOE=0, CALLINC=0, UM=1, INTLEVEL=N, EXCM=1, RING=0 */
|
||||
#endif
|
||||
wsr a2, PS // update PS to disable window exceptions, etc as per above
|
||||
rsync
|
||||
|
||||
// NOTE: here for XEA1, restore INTENABLE etc...
|
||||
|
||||
#ifdef __XTENSA_WINDOWED_ABI__
|
||||
// Restore window registers:
|
||||
l32i a2, a1, HESF_WINDOWSTART
|
||||
l32i a3, a1, HESF_WINDOWBASE
|
||||
wsr a2, WINDOWSTART
|
||||
wsr a3, WINDOWBASE
|
||||
rsync
|
||||
// Note: register window has rotated, ie. a0..a15 clobbered.
|
||||
|
||||
// Reload initial stack pointer:
|
||||
movi a1, LABEL(_Pri_,_Stack) + PRI_N_STACK_SIZE // - 16
|
||||
movi a6, XCHAL_NUM_AREGS - 8 // how many saved so far
|
||||
addi a7, a1, -8*4
|
||||
|
||||
// Restore entire register file (!):
|
||||
|
||||
1:
|
||||
addi a14, a6, -8
|
||||
addi a15, a7, 8*4
|
||||
l32i a4, a15, HESF_AR(4)
|
||||
l32i a5, a15, HESF_AR(5)
|
||||
l32i a6, a15, HESF_AR(6)
|
||||
l32i a7, a15, HESF_AR(7)
|
||||
l32i a8, a15, HESF_AR(8)
|
||||
l32i a9, a15, HESF_AR(9)
|
||||
l32i a10,a15, HESF_AR(10)
|
||||
l32i a11,a15, HESF_AR(11)
|
||||
rotw 2
|
||||
bnez a6, 1b // loop until done
|
||||
|
||||
l32i a4, a7, HESF_AR(12)
|
||||
l32i a5, a7, HESF_AR(13)
|
||||
l32i a6, a7, HESF_AR(14)
|
||||
l32i a7, a7, HESF_AR(15)
|
||||
rotw 2
|
||||
|
||||
// back to original a1 ...
|
||||
|
||||
#else /* Call0 ABI: */
|
||||
|
||||
l32i a4, a1, HESF_AR(4) // restore general registers
|
||||
l32i a5, a1, HESF_AR(5)
|
||||
l32i a6, a1, HESF_AR(6)
|
||||
l32i a7, a1, HESF_AR(7)
|
||||
l32i a8, a1, HESF_AR(8)
|
||||
l32i a9, a1, HESF_AR(9)
|
||||
l32i a10, a1, HESF_AR(10)
|
||||
l32i a11, a1, HESF_AR(11)
|
||||
l32i a12, a1, HESF_AR(12)
|
||||
l32i a13, a1, HESF_AR(13)
|
||||
l32i a14, a1, HESF_AR(14)
|
||||
l32i a15, a1, HESF_AR(15)
|
||||
|
||||
#endif /* __XTENSA_WINDOWED_ABI__ */
|
||||
|
||||
// Restore exception state:
|
||||
l32i a2, a1, HESF_EPC1
|
||||
l32i a3, a1, HESF_EXCCAUSE
|
||||
wsr a2, EPC1
|
||||
wsr a3, EXCCAUSE
|
||||
#if !XCHAL_HAVE_XEA1
|
||||
l32i a2, a1, HESF_EXCVADDR
|
||||
wsr a2, EXCVADDR
|
||||
#endif
|
||||
l32i a3, a1, HESF_EXCSAVE1
|
||||
wsr a3, EXCSAVE1
|
||||
|
||||
l32i a0, a1, HESF_AR(0)
|
||||
|
||||
l32i a2, a1, HESF_AR(2)
|
||||
l32i a3, a1, HESF_AR(3)
|
||||
l32i a1, a1, HESF_AR(1)
|
||||
|
||||
rfi XCHAL_NMILEVEL
|
||||
|
||||
#if 0
|
||||
.align 4
|
||||
.L_xt_nmi_exit:
|
||||
rsr a0, EXCSAVE + XCHAL_NMILEVEL /* restore a0 */
|
||||
rfi XCHAL_NMILEVEL
|
||||
#endif
|
||||
#endif /* NMI */
|
||||
|
||||
|
||||
#else /*********************Seperate from BAOFENG and NORMAL********************/
|
||||
#define EXCSAVE_LEVEL _JOIN2(EXCSAVE_, 3)
|
||||
|
||||
/*******************************************************************************/
|
||||
|
||||
#define _INTERRUPT_LEVEL 3
|
||||
|
||||
@ -1374,9 +538,10 @@ LoadStoreErrorHandler:
|
||||
.type call_user_start,@function
|
||||
.align 4
|
||||
.literal_position
|
||||
vector_entr:
|
||||
.word 0x40100000
|
||||
call_user_start:
|
||||
|
||||
movi a2, 0x40100000 /* note: absolute symbol, not a ptr */
|
||||
l32r a2, 0x40100000
|
||||
wsr a2, vecbase
|
||||
call0 user_start /* user exception handler */
|
||||
|
||||
@ -2230,9 +1395,3 @@ nmi_rfi:
|
||||
rfi XCHAL_NMILEVEL
|
||||
#endif
|
||||
#endif /* NMI */
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user