1/* 2 * SPDX-FileCopyrightText: 2017-2021 Espressif Systems (Shanghai) CO LTD 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 */ 6 7#include <xtensa/coreasm.h> 8#include <xtensa/corebits.h> 9#include <xtensa/config/system.h> 10#include "freertos/xtensa_context.h" 11#include "esp_private/panic_reason.h" 12#include "sdkconfig.h" 13#include "soc/soc.h" 14#include "soc/dport_reg.h" 15 16/* High-priority interrupt - IPC_ISR handler */ 17 18#if CONFIG_ESP_SYSTEM_CHECK_INT_LEVEL_5 19#define LX_INTR_STACK_SIZE 16 20#define LX_INTR_A0_OFFSET 0 21#define LX_INTR_A2_OFFSET 4 22#define LX_INTR_A3_OFFSET 8 23#define LX_INTR_A4_OFFSET 12 24#define EXCSAVE_X EXCSAVE_5 25#define RFI_X 5 26 27#elif CONFIG_ESP_SYSTEM_CHECK_INT_LEVEL_4 28 29#define LX_INTR_STACK_SIZE 16 30#define LX_INTR_A0_OFFSET 0 31#define LX_INTR_A2_OFFSET 4 32#define LX_INTR_A3_OFFSET 8 33#define LX_INTR_A4_OFFSET 12 34#define EXCSAVE_X EXCSAVE_4 35#define RFI_X 4 36 37#endif /* CONFIG_ESP_SYSTEM_CHECK_INT_LEVEL_5 */ 38 39 .data 40_lx_intr_stack: 41 .space LX_INTR_STACK_SIZE 42 .section .iram1,"ax" 43 .global esp_ipc_isr_handler 44 .type esp_ipc_isr_handler,@function 45 .align 4 46esp_ipc_isr_handler: 47 /* Allocate exception frame and save minimal context. */ 48 /* Because the interrupt cause code has protection that only 49 allows one cpu to enter in the IPC_ISR section of the LX 50 interrupt at one time, there's no need to have two 51 _lx_intr_stack for each cpu */ 52 53 /* Save A0, A2, A3, A4 so we can use those registers further*/ 54 movi a0, _lx_intr_stack 55 s32i a2, a0, LX_INTR_A2_OFFSET 56 s32i a3, a0, LX_INTR_A3_OFFSET 57 s32i a4, a0, LX_INTR_A4_OFFSET 58 rsr a2, EXCSAVE_X 59 s32i a2, a0, LX_INTR_A0_OFFSET 60 61 /* disable nested iterrupts */ 62 /* PS.EXCM is changed from 1 to 0 . It allows using usually exception handler instead of the Double exception handler. */ 63 /* PS_UM = 1 */ 64 movi a0, PS_INTLEVEL(5) | PS_UM 65 wsr a0, PS 66 rsync 67 /* restore PS will be done by rfi the end */ 68 69 /* 70 * Reset isr interrupt flags 71 */ 72#if CONFIG_ESP_SYSTEM_CHECK_INT_LEVEL_5 73 /* This int is level-triggered and doesn't need clearing. 74 Do nothing here and clear int status by peripheral register later.*/ 75#elif CONFIG_ESP_SYSTEM_CHECK_INT_LEVEL_4 76 /* This int is edge-triggered and needs clearing. */ 77 movi a3, (1 << ETS_IPC_ISR_INUM) 78 wsr a3, INTCLEAR 79#endif /* CONFIG_ESP_SYSTEM_CHECK_INT_LEVEL_5 */ 80 81 /* get CORE_ID */ 82 getcoreid a3 83 beqz a3, 1f 84 85 /* current cpu is 1 */ 86 movi a3, SYSTEM_CPU_INTR_FROM_CPU_3_REG 87 movi a4, 0 88 s32i a4, a3, 0 /* clear intr */ 89 j 2f 901: 91 /* current cpu is 0 */ 92 movi a3, SYSTEM_CPU_INTR_FROM_CPU_2_REG 93 movi a4, 0 94 s32i a4, a3, 0 /* clear intr */ 952: 96 97 /* set the start flag */ 98 movi a0, esp_ipc_isr_start_fl 99 s32i a0, a0, 0 100 101 /* Call the esp_ipc_function(void* arg) */ 102 movi a0, esp_ipc_func 103 l32i a0, a0, 0 104 movi a2, esp_ipc_func_arg 105 l32i a2, a2, 0 106 callx0 a0 107 108 /* Done. Restore registers and return. */ 109 movi a0, _lx_intr_stack 110 l32i a2, a0, LX_INTR_A2_OFFSET 111 l32i a3, a0, LX_INTR_A3_OFFSET 112 l32i a4, a0, LX_INTR_A4_OFFSET 113 114 /* set the end flag */ 115 movi a0, esp_ipc_isr_end_fl 116 s32i a0, a0, 0 117 118 /* restore a0 */ 119 rsr a0, EXCSAVE_X 120 /* restores PS from EPS[X] and jumps to the address in EPC[X] */ 121 rfi RFI_X 122