Rework high interrupt code to be able to link to external handlers; add psram test that swarms cpu with interrupts
This commit is contained in:
parent
b63921a99c
commit
202a5db2d2
11 changed files with 365 additions and 283 deletions
|
@ -25,7 +25,7 @@
|
|||
#include "esp_system.h"
|
||||
#endif
|
||||
|
||||
const char *TAG = "boot_rng";
|
||||
static const char *TAG = "boot_rng";
|
||||
|
||||
void bootloader_fill_random(void *buffer, size_t length)
|
||||
{
|
||||
|
|
|
@ -165,6 +165,13 @@ config SPIRAM_CACHE_WORKAROUND
|
|||
when the cache line needs to be fetched from external RAM and an interrupt occurs. This enables a
|
||||
fix in the compiler that makes sure the specific code that is vulnerable to this will not be emitted.
|
||||
|
||||
config SPIRAM_CACHE_WORKAROUND_TEST
|
||||
bool "Debug: Test workaround by generating a lot of interrupts"
|
||||
default "n"
|
||||
help
|
||||
This setting helps testing the SPIRAM cache workaround. It generates a lot of interrupts so
|
||||
the bug, if still existing, triggers quicker.
|
||||
|
||||
choice MEMMAP_SPIRAM_TYPE
|
||||
prompt "Type of SPI RAM chip in use"
|
||||
default MEMMAP_SPIRAM_TYPE_ESPPSRAM32
|
||||
|
|
|
@ -31,6 +31,8 @@ COMPONENT_ADD_LDFLAGS := -lesp32 \
|
|||
$(addprefix -l,$(LIBS)) \
|
||||
-L $(COMPONENT_PATH)/ld \
|
||||
-T esp32_out.ld \
|
||||
-u ld_include_panic_highint_hdl \
|
||||
-u ld_include_psram_tst \
|
||||
$(addprefix -T ,$(LINKER_SCRIPTS))
|
||||
|
||||
ALL_LIB_FILES := $(patsubst %,$(COMPONENT_PATH)/lib/lib%.a,$(LIBS))
|
||||
|
|
|
@ -64,6 +64,7 @@
|
|||
#include "esp_app_trace.h"
|
||||
#include "esp_clk.h"
|
||||
#include "trax.h"
|
||||
#include "esp_psram_tst.h"
|
||||
|
||||
#include "esp_psram.h"
|
||||
|
||||
|
@ -278,6 +279,10 @@ void start_cpu0_default(void)
|
|||
esp_core_dump_init();
|
||||
#endif
|
||||
|
||||
#if CONFIG_SPIRAM_CACHE_WORKAROUND_TEST
|
||||
psram_tst_setup();
|
||||
#endif
|
||||
|
||||
xTaskCreatePinnedToCore(&main_task, "main",
|
||||
ESP_TASK_MAIN_STACK, NULL,
|
||||
ESP_TASK_MAIN_PRIO, NULL, 0);
|
||||
|
@ -306,6 +311,9 @@ void start_cpu1_default(void)
|
|||
esp_cache_err_int_init();
|
||||
esp_crosscore_int_init();
|
||||
esp_dport_access_int_init();
|
||||
#if CONFIG_SPIRAM_CACHE_WORKAROUND_TEST
|
||||
psram_tst_setup();
|
||||
#endif
|
||||
|
||||
ESP_EARLY_LOGI(TAG, "Starting scheduler on APP CPU.");
|
||||
xPortStartScheduler();
|
||||
|
|
3
components/esp32/include/esp_psram_tst.h
Normal file
3
components/esp32/include/esp_psram_tst.h
Normal file
|
@ -0,0 +1,3 @@
|
|||
|
||||
|
||||
void psram_tst_setup();
|
119
components/esp32/panic_highint_hdl.S
Normal file
119
components/esp32/panic_highint_hdl.S
Normal file
|
@ -0,0 +1,119 @@
|
|||
#include <xtensa/coreasm.h>
|
||||
#include <xtensa/corebits.h>
|
||||
#include <xtensa/config/system.h>
|
||||
#include <xtensa/simcall.h>
|
||||
#include "freertos/xtensa_context.h"
|
||||
#include "esp_panic.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "soc/soc.h"
|
||||
|
||||
|
||||
/*
|
||||
In some situations, the panic handler needs to be invoked even when (low/medium priority) interrupts
|
||||
are disabled. In that case, we use a high interrupt to panic anyway. This is the high-level interrupt
|
||||
handler for such a situation.
|
||||
*/
|
||||
|
||||
.section .iram1,"ax"
|
||||
.type xt_highint4,@function
|
||||
.align 4
|
||||
xt_highint4:
|
||||
|
||||
#ifdef XT_INTEXC_HOOKS
|
||||
/* Call interrupt hook if present to (pre)handle interrupts. */
|
||||
movi a0, _xt_intexc_hooks
|
||||
l32i a0, a0, 4<<2
|
||||
beqz a0, 1f
|
||||
.Ln_xt_highint4_call_hook:
|
||||
callx0 a0 /* must NOT disturb stack! */
|
||||
1:
|
||||
#endif
|
||||
|
||||
|
||||
/* On the ESP32, this level is used for panic events that are detected by hardware and should
|
||||
also panic when interrupts are disabled. At the moment, these are the interrupt watchdog
|
||||
as well as the cache invalid access interrupt. (24 and 25) */
|
||||
|
||||
/* Allocate exception frame and save minimal context. */
|
||||
mov a0, sp
|
||||
addi sp, sp, -XT_STK_FRMSZ
|
||||
s32i a0, sp, XT_STK_A1
|
||||
#if XCHAL_HAVE_WINDOWED
|
||||
s32e a0, sp, -12 /* for debug backtrace */
|
||||
#endif
|
||||
rsr a0, PS /* save interruptee's PS */
|
||||
s32i a0, sp, XT_STK_PS
|
||||
rsr a0, EPC_4 /* save interruptee's PC */
|
||||
s32i a0, sp, XT_STK_PC
|
||||
#if XCHAL_HAVE_WINDOWED
|
||||
s32e a0, sp, -16 /* for debug backtrace */
|
||||
#endif
|
||||
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
|
||||
|
||||
/* Save vaddr into exception frame */
|
||||
rsr a0, EXCVADDR
|
||||
s32i a0, sp, XT_STK_EXCVADDR
|
||||
|
||||
/* Figure out reason, save into EXCCAUSE reg */
|
||||
|
||||
rsr a0, INTERRUPT
|
||||
extui a0, a0, ETS_CACHEERR_INUM, 1 /* get cacheerr int bit */
|
||||
beqz a0, 1f
|
||||
/* Kill this interrupt; we cannot reset it. */
|
||||
rsr a0, INTENABLE
|
||||
movi a4, ~(1<<ETS_CACHEERR_INUM)
|
||||
and a0, a4, a0
|
||||
wsr a0, INTENABLE
|
||||
movi a0, PANIC_RSN_CACHEERR
|
||||
j 9f
|
||||
1:
|
||||
#if CONFIG_INT_WDT_CHECK_CPU1
|
||||
/* Check if the cause is the app cpu failing to tick.*/
|
||||
movi a0, int_wdt_app_cpu_ticked
|
||||
l32i a0, a0, 0
|
||||
bnez a0, 2f
|
||||
/* It is. Modify cause. */
|
||||
movi a0,PANIC_RSN_INTWDT_CPU1
|
||||
j 9f
|
||||
2:
|
||||
#endif
|
||||
/* Set EXCCAUSE to reflect cause of the wdt int trigger */
|
||||
movi a0,PANIC_RSN_INTWDT_CPU0
|
||||
9:
|
||||
/* Found the reason, now save it. */
|
||||
s32i a0, sp, XT_STK_EXCCAUSE
|
||||
|
||||
/* _xt_context_save seems to save the current a0, but we need the interuptees a0. Fix this. */
|
||||
rsr a0, EXCSAVE_4 /* save interruptee's a0 */
|
||||
|
||||
s32i a0, sp, XT_STK_A0
|
||||
|
||||
/* Set up PS for C, disable all interrupts except NMI and debug, and clear EXCM. */
|
||||
movi a0, PS_INTLEVEL(5) | PS_UM | PS_WOE
|
||||
wsr a0, PS
|
||||
|
||||
//Call panic handler
|
||||
mov a6,sp
|
||||
call4 panicHandler
|
||||
|
||||
call0 _xt_context_restore
|
||||
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 exception frame */
|
||||
rsync /* ensure PS and EPC written */
|
||||
|
||||
rsr a0, EXCSAVE_4 /* restore a0 */
|
||||
rfi 4
|
||||
|
||||
/* The linker has no reason to link in this file; all symbols it exports are already defined
|
||||
(weakly!) in the default int handler. Define a symbol here so we can use it to have the
|
||||
linker inspect this anyway. */
|
||||
|
||||
.global ld_include_panic_highint_hdl
|
||||
ld_include_panic_highint_hdl:
|
||||
|
43
components/esp32/psram_tst.c
Normal file
43
components/esp32/psram_tst.c
Normal file
|
@ -0,0 +1,43 @@
|
|||
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
|
||||
|
||||
#include "sdkconfig.h"
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include <esp_types.h>
|
||||
#include "esp_err.h"
|
||||
#include "esp_intr.h"
|
||||
#include "esp_attr.h"
|
||||
#include "esp_freertos_hooks.h"
|
||||
#include "soc/timer_group_struct.h"
|
||||
#include "soc/timer_group_reg.h"
|
||||
#include "driver/timer.h"
|
||||
#include "xtensa/core-macros.h"
|
||||
|
||||
#if CONFIG_SPIRAM_CACHE_WORKAROUND_TEST
|
||||
|
||||
void psram_tst_setup() {
|
||||
esp_err_t err;
|
||||
XTHAL_SET_CCOMPARE(2, XTHAL_GET_CCOUNT()+1000);
|
||||
err=esp_intr_alloc(ETS_INTERNAL_TIMER2_INTR_SOURCE, ESP_INTR_FLAG_LEVEL5|ESP_INTR_FLAG_IRAM, NULL, NULL, NULL);
|
||||
assert(err==ESP_OK);
|
||||
}
|
||||
|
||||
#endif
|
36
components/esp32/psram_tst_asm.S
Normal file
36
components/esp32/psram_tst_asm.S
Normal file
|
@ -0,0 +1,36 @@
|
|||
#include <xtensa/coreasm.h>
|
||||
#include <xtensa/corebits.h>
|
||||
#include <xtensa/config/system.h>
|
||||
#include <xtensa/simcall.h>
|
||||
#include "esp_panic.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "soc/soc.h"
|
||||
|
||||
|
||||
#if CONFIG_SPIRAM_CACHE_WORKAROUND_TEST
|
||||
|
||||
.section .iram1,"ax"
|
||||
.global xt_highint5
|
||||
.type xt_highint5,@function
|
||||
.align 4
|
||||
xt_highint5:
|
||||
|
||||
esync
|
||||
rsr a0, CCOUNT
|
||||
addi a0, a0, 40
|
||||
wsr a0, CCOMPARE2
|
||||
esync
|
||||
|
||||
.L_xt_highint5_exit:
|
||||
rsr a0, EXCSAVE_5 /* restore a0 */
|
||||
rfi 5
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
/* The linker has no reason to link in this file; all symbols it exports are already defined
|
||||
(weakly!) in the default int handler. Define a symbol here so we can use it to have the
|
||||
linker inspect this anyway. */
|
||||
|
||||
.global ld_include_psram_tst
|
||||
ld_include_psram_tst:
|
5
components/freertos/xtensa_int_alias.S
Normal file
5
components/freertos/xtensa_int_alias.S
Normal file
|
@ -0,0 +1,5 @@
|
|||
|
||||
.global xt_highint5
|
||||
.global _xt_highint5
|
||||
.weak xt_highint5
|
||||
.set xt_highint5, _xt_highint5
|
126
components/freertos/xtensa_vector_defaults.S
Normal file
126
components/freertos/xtensa_vector_defaults.S
Normal file
|
@ -0,0 +1,126 @@
|
|||
|
||||
#include "xtensa_rtos.h"
|
||||
#include "esp_panic.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "soc/soc.h"
|
||||
|
||||
/*
|
||||
This file contains the default handlers for the high interrupt levels. The default behavious
|
||||
is to just exit the interrupt.
|
||||
*/
|
||||
|
||||
#if XCHAL_NUM_INTLEVELS >=2 && XCHAL_EXCM_LEVEL <2 && XCHAL_DEBUGLEVEL !=2
|
||||
.global xt_highint2
|
||||
.weak xt_highint2
|
||||
.set xt_highint2, _xt_highint2
|
||||
.section .iram1,"ax"
|
||||
.type _xt_highint2,@function
|
||||
.align 4
|
||||
_xt_highint2:
|
||||
|
||||
/* Default handler does nothing; just returns */
|
||||
.align 4
|
||||
.L_xt_highint2_exit:
|
||||
rsr a0, EXCSAVE_2 /* restore a0 */
|
||||
rfi 2
|
||||
|
||||
#endif /* Level 2 */
|
||||
|
||||
#if XCHAL_NUM_INTLEVELS >=3 && XCHAL_EXCM_LEVEL <3 && XCHAL_DEBUGLEVEL !=3
|
||||
|
||||
.global xt_highint3
|
||||
.weak xt_highint3
|
||||
.set xt_highint3, _xt_highint3
|
||||
.section .iram1,"ax"
|
||||
.type _xt_highint3,@function
|
||||
.align 4
|
||||
_xt_highint3:
|
||||
|
||||
/* Default handler does nothing; just returns */
|
||||
|
||||
.align 4
|
||||
.L_xt_highint3_exit:
|
||||
rsr a0, EXCSAVE_3 /* restore a0 */
|
||||
rfi 3
|
||||
|
||||
#endif /* Level 3 */
|
||||
|
||||
#if XCHAL_NUM_INTLEVELS >=4 && XCHAL_EXCM_LEVEL <4 && XCHAL_DEBUGLEVEL !=4
|
||||
|
||||
.global xt_highint4
|
||||
.weak xt_highint4
|
||||
.set xt_highint4, _xt_highint4
|
||||
.section .iram1,"ax"
|
||||
.type _xt_highint4,@function
|
||||
.align 4
|
||||
_xt_highint4:
|
||||
|
||||
/* Default handler does nothing; just returns */
|
||||
|
||||
.align 4
|
||||
.L_xt_highint4_exit:
|
||||
rsr a0, EXCSAVE_4 /* restore a0 */
|
||||
rfi 4
|
||||
|
||||
#endif /* Level 4 */
|
||||
|
||||
#if XCHAL_NUM_INTLEVELS >=5 && XCHAL_EXCM_LEVEL <5 && XCHAL_DEBUGLEVEL !=5
|
||||
|
||||
.global xt_highint5
|
||||
.weak xt_highint5
|
||||
.set xt_highint5, _xt_highint5
|
||||
.section .iram1,"ax"
|
||||
.type _xt_highint5,@function
|
||||
.align 4
|
||||
_xt_highint5:
|
||||
|
||||
/* Default handler does nothing; just returns */
|
||||
|
||||
.align 4
|
||||
.L_xt_highint5_exit:
|
||||
rsr a0, EXCSAVE_5 /* restore a0 */
|
||||
rfi 5
|
||||
|
||||
|
||||
#endif /* Level 5 */
|
||||
|
||||
#if XCHAL_NUM_INTLEVELS >=6 && XCHAL_EXCM_LEVEL <6 && XCHAL_DEBUGLEVEL !=6
|
||||
|
||||
.global _xt_highint6
|
||||
.global xt_highint6
|
||||
.weak xt_highint6
|
||||
.set xt_highint6, _xt_highint6
|
||||
.section .iram1,"ax"
|
||||
.type _xt_highint6,@function
|
||||
.align 4
|
||||
_xt_highint6:
|
||||
|
||||
/* Default handler does nothing; just returns */
|
||||
|
||||
.align 4
|
||||
.L_xt_highint6_exit:
|
||||
rsr a0, EXCSAVE_6 /* restore a0 */
|
||||
rfi 6
|
||||
|
||||
#endif /* Level 6 */
|
||||
|
||||
#if XCHAL_HAVE_NMI
|
||||
|
||||
.global _xt_nmi
|
||||
.global xt_nmi
|
||||
.weak xt_nmi
|
||||
.set xt_nmi, _xt_nmi
|
||||
.section .iram1,"ax"
|
||||
.type _xt_nmi,@function
|
||||
.align 4
|
||||
_xt_nmi:
|
||||
|
||||
/* Default handler does nothing; just returns */
|
||||
|
||||
.align 4
|
||||
.L_xt_nmi_exit:
|
||||
rsr a0, EXCSAVE + XCHAL_NMILEVEL /* restore a0 */
|
||||
rfi XCHAL_NMILEVEL
|
||||
|
||||
#endif /* NMI */
|
||||
|
|
@ -1522,9 +1522,9 @@ the minimum necessary before jumping to the handler in the .text section.
|
|||
*******************************************************************************/
|
||||
|
||||
/*
|
||||
Currently only shells for high priority interrupt handlers are provided
|
||||
here. However a template and example can be found in the Cadence Design Systems tools
|
||||
documentation: "Microprocessor Programmer's Guide".
|
||||
These stubs just call xt_highintX/xt_nmi to handle the real interrupt. Please define
|
||||
these in an external assembly source file. If these symbols are not defined anywhere
|
||||
else, the defaults in xtensa_vector_defaults.S are used.
|
||||
*/
|
||||
|
||||
#if XCHAL_NUM_INTLEVELS >=2 && XCHAL_EXCM_LEVEL <2 && XCHAL_DEBUGLEVEL !=2
|
||||
|
@ -1533,37 +1533,14 @@ documentation: "Microprocessor Programmer's Guide".
|
|||
.section .Level2InterruptVector.text, "ax"
|
||||
.global _Level2Vector
|
||||
.type _Level2Vector,@function
|
||||
.global xt_highint2
|
||||
.align 4
|
||||
_Level2Vector:
|
||||
wsr a0, EXCSAVE_2 /* preserve a0 */
|
||||
call0 _xt_highint2 /* load interrupt handler */
|
||||
call0 xt_highint2 /* load interrupt handler */
|
||||
|
||||
.end literal_prefix
|
||||
|
||||
.section .iram1,"ax"
|
||||
.type _xt_highint2,@function
|
||||
.align 4
|
||||
_xt_highint2:
|
||||
|
||||
#ifdef XT_INTEXC_HOOKS
|
||||
/* Call interrupt hook if present to (pre)handle interrupts. */
|
||||
movi a0, _xt_intexc_hooks
|
||||
l32i a0, a0, 2<<2
|
||||
beqz a0, 1f
|
||||
.Ln_xt_highint2_call_hook:
|
||||
callx0 a0 /* must NOT disturb stack! */
|
||||
1:
|
||||
#endif
|
||||
|
||||
/* USER_EDIT:
|
||||
ADD HIGH PRIORITY LEVEL 2 INTERRUPT HANDLER CODE HERE.
|
||||
*/
|
||||
|
||||
.align 4
|
||||
.L_xt_highint2_exit:
|
||||
rsr a0, EXCSAVE_2 /* restore a0 */
|
||||
rfi 2
|
||||
|
||||
#endif /* Level 2 */
|
||||
|
||||
#if XCHAL_NUM_INTLEVELS >=3 && XCHAL_EXCM_LEVEL <3 && XCHAL_DEBUGLEVEL !=3
|
||||
|
@ -1572,38 +1549,15 @@ _xt_highint2:
|
|||
.section .Level3InterruptVector.text, "ax"
|
||||
.global _Level3Vector
|
||||
.type _Level3Vector,@function
|
||||
.global xt_highint3
|
||||
.align 4
|
||||
_Level3Vector:
|
||||
wsr a0, EXCSAVE_3 /* preserve a0 */
|
||||
call0 _xt_highint3 /* load interrupt handler */
|
||||
call0 xt_highint3 /* load interrupt handler */
|
||||
/* never returns here - call0 is used as a jump (see note at top) */
|
||||
|
||||
.end literal_prefix
|
||||
|
||||
.section .iram1,"ax"
|
||||
.type _xt_highint3,@function
|
||||
.align 4
|
||||
_xt_highint3:
|
||||
|
||||
#ifdef XT_INTEXC_HOOKS
|
||||
/* Call interrupt hook if present to (pre)handle interrupts. */
|
||||
movi a0, _xt_intexc_hooks
|
||||
l32i a0, a0, 3<<2
|
||||
beqz a0, 1f
|
||||
.Ln_xt_highint3_call_hook:
|
||||
callx0 a0 /* must NOT disturb stack! */
|
||||
1:
|
||||
#endif
|
||||
|
||||
/* USER_EDIT:
|
||||
ADD HIGH PRIORITY LEVEL 3 INTERRUPT HANDLER CODE HERE.
|
||||
*/
|
||||
|
||||
.align 4
|
||||
.L_xt_highint3_exit:
|
||||
rsr a0, EXCSAVE_3 /* restore a0 */
|
||||
rfi 3
|
||||
|
||||
#endif /* Level 3 */
|
||||
|
||||
#if XCHAL_NUM_INTLEVELS >=4 && XCHAL_EXCM_LEVEL <4 && XCHAL_DEBUGLEVEL !=4
|
||||
|
@ -1612,110 +1566,15 @@ _xt_highint3:
|
|||
.section .Level4InterruptVector.text, "ax"
|
||||
.global _Level4Vector
|
||||
.type _Level4Vector,@function
|
||||
.global xt_highint4
|
||||
.align 4
|
||||
_Level4Vector:
|
||||
wsr a0, EXCSAVE_4 /* preserve a0 */
|
||||
call0 _xt_highint4 /* load interrupt handler */
|
||||
call0 xt_highint4 /* load interrupt handler */
|
||||
/* never returns here - call0 is used as a jump (see note at top) */
|
||||
|
||||
.end literal_prefix
|
||||
|
||||
.section .iram1,"ax"
|
||||
.type _xt_highint4,@function
|
||||
.align 4
|
||||
_xt_highint4:
|
||||
|
||||
#ifdef XT_INTEXC_HOOKS
|
||||
/* Call interrupt hook if present to (pre)handle interrupts. */
|
||||
movi a0, _xt_intexc_hooks
|
||||
l32i a0, a0, 4<<2
|
||||
beqz a0, 1f
|
||||
.Ln_xt_highint4_call_hook:
|
||||
callx0 a0 /* must NOT disturb stack! */
|
||||
1:
|
||||
#endif
|
||||
|
||||
|
||||
/* On the ESP32, this level is used for panic events that are detected by hardware and should
|
||||
also panic when interrupts are disabled. At the moment, these are the interrupt watchdog
|
||||
as well as the cache invalid access interrupt. (24 and 25) */
|
||||
|
||||
/* Allocate exception frame and save minimal context. */
|
||||
mov a0, sp
|
||||
addi sp, sp, -XT_STK_FRMSZ
|
||||
s32i a0, sp, XT_STK_A1
|
||||
#if XCHAL_HAVE_WINDOWED
|
||||
s32e a0, sp, -12 /* for debug backtrace */
|
||||
#endif
|
||||
rsr a0, PS /* save interruptee's PS */
|
||||
s32i a0, sp, XT_STK_PS
|
||||
rsr a0, EPC_4 /* save interruptee's PC */
|
||||
s32i a0, sp, XT_STK_PC
|
||||
#if XCHAL_HAVE_WINDOWED
|
||||
s32e a0, sp, -16 /* for debug backtrace */
|
||||
#endif
|
||||
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
|
||||
|
||||
/* Save vaddr into exception frame */
|
||||
rsr a0, EXCVADDR
|
||||
s32i a0, sp, XT_STK_EXCVADDR
|
||||
|
||||
/* Figure out reason, save into EXCCAUSE reg */
|
||||
|
||||
rsr a0, INTERRUPT
|
||||
extui a0, a0, ETS_CACHEERR_INUM, 1 /* get cacheerr int bit */
|
||||
beqz a0, 1f
|
||||
/* Kill this interrupt; we cannot reset it. */
|
||||
rsr a0, INTENABLE
|
||||
movi a4, ~(1<<ETS_CACHEERR_INUM)
|
||||
and a0, a4, a0
|
||||
wsr a0, INTENABLE
|
||||
movi a0, PANIC_RSN_CACHEERR
|
||||
j 9f
|
||||
1:
|
||||
#if CONFIG_INT_WDT_CHECK_CPU1
|
||||
/* Check if the cause is the app cpu failing to tick.*/
|
||||
movi a0, int_wdt_app_cpu_ticked
|
||||
l32i a0, a0, 0
|
||||
bnez a0, 2f
|
||||
/* It is. Modify cause. */
|
||||
movi a0,PANIC_RSN_INTWDT_CPU1
|
||||
j 9f
|
||||
2:
|
||||
#endif
|
||||
/* Set EXCCAUSE to reflect cause of the wdt int trigger */
|
||||
movi a0,PANIC_RSN_INTWDT_CPU0
|
||||
9:
|
||||
/* Found the reason, now save it. */
|
||||
s32i a0, sp, XT_STK_EXCCAUSE
|
||||
|
||||
/* _xt_context_save seems to save the current a0, but we need the interuptees a0. Fix this. */
|
||||
rsr a0, EXCSAVE_4 /* save interruptee's a0 */
|
||||
|
||||
s32i a0, sp, XT_STK_A0
|
||||
|
||||
/* Set up PS for C, disable all interrupts except NMI and debug, and clear EXCM. */
|
||||
movi a0, PS_INTLEVEL(5) | PS_UM | PS_WOE
|
||||
wsr a0, PS
|
||||
|
||||
//Call panic handler
|
||||
mov a6,sp
|
||||
call4 panicHandler
|
||||
|
||||
call0 _xt_context_restore
|
||||
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_4
|
||||
l32i a0, sp, XT_STK_A0 /* retrieve interruptee's A0 */
|
||||
l32i sp, sp, XT_STK_A1 /* remove exception frame */
|
||||
rsync /* ensure PS and EPC written */
|
||||
|
||||
rsr a0, EXCSAVE_4 /* restore a0 */
|
||||
rfi 4
|
||||
|
||||
#endif /* Level 4 */
|
||||
|
||||
#if XCHAL_NUM_INTLEVELS >=5 && XCHAL_EXCM_LEVEL <5 && XCHAL_DEBUGLEVEL !=5
|
||||
|
@ -1724,95 +1583,15 @@ _xt_highint4:
|
|||
.section .Level5InterruptVector.text, "ax"
|
||||
.global _Level5Vector
|
||||
.type _Level5Vector,@function
|
||||
.global xt_highint5
|
||||
.align 4
|
||||
_Level5Vector:
|
||||
wsr a0, EXCSAVE_5 /* preserve a0 */
|
||||
call0 _xt_highint5 /* load interrupt handler */
|
||||
call0 xt_highint5 /* load interrupt handler */
|
||||
/* never returns here - call0 is used as a jump (see note at top) */
|
||||
|
||||
.end literal_prefix
|
||||
|
||||
#define L5_INTR_STACK_SIZE 8
|
||||
#define L5_INTR_A2_OFFSET 0
|
||||
#define L5_INTR_A3_OFFSET 4
|
||||
.data
|
||||
_l5_intr_stack:
|
||||
.space L5_INTR_STACK_SIZE
|
||||
|
||||
.section .iram1,"ax"
|
||||
.type _xt_highint5,@function
|
||||
.align 4
|
||||
_xt_highint5:
|
||||
|
||||
#ifdef XT_INTEXC_HOOKS
|
||||
/* Call interrupt hook if present to (pre)handle interrupts. */
|
||||
movi a0, _xt_intexc_hooks
|
||||
l32i a0, a0, 5<<2
|
||||
beqz a0, 1f
|
||||
.Ln_xt_highint5_call_hook:
|
||||
callx0 a0 /* must NOT disturb stack! */
|
||||
1:
|
||||
#endif
|
||||
|
||||
/* This section is for access dport register protection */
|
||||
/* Allocate exception frame and save minimal context. */
|
||||
/* Because the interrupt cause code have protection that only
|
||||
allow one cpu enter in L5 interrupt at one time, so
|
||||
there needn't have two _l5_intr_stack for each cpu */
|
||||
|
||||
movi a0, _l5_intr_stack
|
||||
s32i a2, a0, L5_INTR_A2_OFFSET
|
||||
s32i a3, a0, L5_INTR_A3_OFFSET
|
||||
|
||||
/* Check interrupt */
|
||||
rsr a0, INTERRUPT
|
||||
extui a0, a0, ETS_DPORT_INUM, 1 /* get dport int bit */
|
||||
beqz a0, 1f
|
||||
|
||||
/* handle dport interrupt */
|
||||
/* get CORE_ID */
|
||||
getcoreid a0
|
||||
beqz a0, 2f
|
||||
|
||||
/* current cpu is 1 */
|
||||
movi a0, DPORT_CPU_INTR_FROM_CPU_3_REG
|
||||
movi a2, 0
|
||||
s32i a2, a0, 0 /* clear intr */
|
||||
movi a0, 0 /* other cpu id */
|
||||
j 3f
|
||||
2:
|
||||
/* current cpu is 0 */
|
||||
movi a0, DPORT_CPU_INTR_FROM_CPU_2_REG
|
||||
movi a2, 0
|
||||
s32i a2, a0, 0 /* clear intr */
|
||||
movi a0, 1 /* other cpu id */
|
||||
3:
|
||||
/* set and wait flag */
|
||||
movi a2, dport_access_start
|
||||
addx4 a2, a0, a2
|
||||
movi a3, 1
|
||||
s32i a3, a2, 0
|
||||
memw
|
||||
movi a2, dport_access_end
|
||||
addx4 a2, a0, a2
|
||||
.check_dport_access_end:
|
||||
l32i a3, a2, 0
|
||||
beqz a3, .check_dport_access_end
|
||||
|
||||
1:
|
||||
movi a0, _l5_intr_stack
|
||||
l32i a2, a0, L5_INTR_A2_OFFSET
|
||||
l32i a3, a0, L5_INTR_A3_OFFSET
|
||||
rsync /* ensure register restored */
|
||||
|
||||
rsr a0, EXCSAVE_5 /* restore a0 */
|
||||
rfi 5
|
||||
|
||||
|
||||
.align 4
|
||||
.L_xt_highint5_exit:
|
||||
rsr a0, EXCSAVE_5 /* restore a0 */
|
||||
rfi 5
|
||||
|
||||
#endif /* Level 5 */
|
||||
|
||||
|
@ -1822,38 +1601,15 @@ _xt_highint5:
|
|||
.section .Level6InterruptVector.text, "ax"
|
||||
.global _Level6Vector
|
||||
.type _Level6Vector,@function
|
||||
.global xt_highint6
|
||||
.align 4
|
||||
_Level6Vector:
|
||||
wsr a0, EXCSAVE_6 /* preserve a0 */
|
||||
call0 _xt_highint6 /* load interrupt handler */
|
||||
call0 xt_highint6 /* load interrupt handler */
|
||||
/* never returns here - call0 is used as a jump (see note at top) */
|
||||
|
||||
.end literal_prefix
|
||||
|
||||
.section .iram1,"ax"
|
||||
.type _xt_highint6,@function
|
||||
.align 4
|
||||
_xt_highint6:
|
||||
|
||||
#ifdef XT_INTEXC_HOOKS
|
||||
/* Call interrupt hook if present to (pre)handle interrupts. */
|
||||
movi a0, _xt_intexc_hooks
|
||||
l32i a0, a0, 6<<2
|
||||
beqz a0, 1f
|
||||
.Ln_xt_highint6_call_hook:
|
||||
callx0 a0 /* must NOT disturb stack! */
|
||||
1:
|
||||
#endif
|
||||
|
||||
/* USER_EDIT:
|
||||
ADD HIGH PRIORITY LEVEL 6 INTERRUPT HANDLER CODE HERE.
|
||||
*/
|
||||
|
||||
.align 4
|
||||
.L_xt_highint6_exit:
|
||||
rsr a0, EXCSAVE_6 /* restore a0 */
|
||||
rfi 6
|
||||
|
||||
#endif /* Level 6 */
|
||||
|
||||
#if XCHAL_HAVE_NMI
|
||||
|
@ -1862,38 +1618,15 @@ _xt_highint6:
|
|||
.section .NMIExceptionVector.text, "ax"
|
||||
.global _NMIExceptionVector
|
||||
.type _NMIExceptionVector,@function
|
||||
.global xt_nmi
|
||||
.align 4
|
||||
_NMIExceptionVector:
|
||||
wsr a0, EXCSAVE + XCHAL_NMILEVEL _ /* preserve a0 */
|
||||
call0 _xt_nmi /* load interrupt handler */
|
||||
call0 xt_nmi /* load interrupt handler */
|
||||
/* never returns here - call0 is used as a jump (see note at top) */
|
||||
|
||||
.end literal_prefix
|
||||
|
||||
.section .iram1,"ax"
|
||||
.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.
|
||||
*/
|
||||
|
||||
.align 4
|
||||
.L_xt_nmi_exit:
|
||||
rsr a0, EXCSAVE + XCHAL_NMILEVEL /* restore a0 */
|
||||
rfi XCHAL_NMILEVEL
|
||||
|
||||
#endif /* NMI */
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue