diff --git a/components/hal/interrupt_controller_hal.c b/components/hal/interrupt_controller_hal.c index f3c5728301..93bce347c9 100644 --- a/components/hal/interrupt_controller_hal.c +++ b/components/hal/interrupt_controller_hal.c @@ -14,11 +14,27 @@ #include "hal/interrupt_controller_hal.h" +#if __riscv +#include "riscv/instruction_decode.h" + +static bool is_interrupt_number_reserved(int interrupt_number) +{ + extern int _vector_table; + extern int _interrupt_handler; + const intptr_t pc = (intptr_t)(&_vector_table + interrupt_number); + + /* JAL instructions are relative to the PC there are executed from. */ + const intptr_t destination = pc + riscv_decode_offset_from_jal_instruction(pc); + + return destination != (intptr_t)&_interrupt_handler; +} +#endif + int_type_t interrupt_controller_hal_desc_type(int interrupt_number) { #ifndef SOC_CPU_HAS_FLEXIBLE_INTC const int_desc_t *int_desc = interrupt_controller_hal_desc_table(); - return(int_desc[interrupt_number].type); + return (int_desc[interrupt_number].type); #else return (INTTP_NA); #endif @@ -28,7 +44,7 @@ int interrupt_controller_hal_desc_level(int interrupt_number) { #ifndef SOC_CPU_HAS_FLEXIBLE_INTC const int_desc_t *int_desc = interrupt_controller_hal_desc_table(); - return(int_desc[interrupt_number].level); + return (int_desc[interrupt_number].level); #else return 1; #endif @@ -38,8 +54,12 @@ int_desc_flag_t interrupt_controller_hal_desc_flags(int interrupt_number, int cp { #ifndef SOC_CPU_HAS_FLEXIBLE_INTC const int_desc_t *int_desc = interrupt_controller_hal_desc_table(); - return(int_desc[interrupt_number].cpuflags[cpu_number]); + return (int_desc[interrupt_number].cpuflags[cpu_number]); +#else +#if __riscv + return is_interrupt_number_reserved(interrupt_number) ? INTDESC_RESVD : INTDESC_NORMAL; #else return INTDESC_NORMAL; #endif +#endif } diff --git a/components/riscv/CMakeLists.txt b/components/riscv/CMakeLists.txt index c42b51db9d..0290ca9937 100644 --- a/components/riscv/CMakeLists.txt +++ b/components/riscv/CMakeLists.txt @@ -7,10 +7,11 @@ if(BOOTLOADER_BUILD) else() set(priv_requires soc freertos) set(srcs - "interrupt.c" - "stdatomic.c" "expression_with_stack_riscv.c" "expression_with_stack_riscv_asm.S" + "instruction_decode.c" + "interrupt.c" + "stdatomic.c" "vectors.S") endif() diff --git a/components/soc/esp32c3/include/soc/int_caps.h b/components/riscv/include/riscv/instruction_decode.h similarity index 68% rename from components/soc/esp32c3/include/soc/int_caps.h rename to components/riscv/include/riscv/instruction_decode.h index c84aa3a564..5625680f82 100644 --- a/components/soc/esp32c3/include/soc/int_caps.h +++ b/components/riscv/include/riscv/instruction_decode.h @@ -3,7 +3,7 @@ // 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 @@ -14,12 +14,20 @@ #pragma once +#include + #ifdef __cplusplus extern "C" { #endif -#define SOC_INTERRUPT_LEVEL_CAN_SET (1) -#define SOC_INTERRUPT_TYPE_CAN_SET (1) +/** + * @brief Decode the offset value from a RISC-V JAL instruction + * @note This API will abort if the instruction is not JAL formatted. + * + * @param inst_addr Address of JAL instruction + * @return int offset value + */ +int riscv_decode_offset_from_jal_instruction(const intptr_t inst_addr); #ifdef __cplusplus } diff --git a/components/riscv/instruction_decode.c b/components/riscv/instruction_decode.c new file mode 100644 index 0000000000..89abccbbbb --- /dev/null +++ b/components/riscv/instruction_decode.c @@ -0,0 +1,38 @@ +// Copyright 2020 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 +#include "riscv/instruction_decode.h" + +typedef union { + struct { + unsigned int opcode: 7; + unsigned int rd: 5; + int imm_19_12: 8; + int imm_11: 1; + int imm_10_1: 10; + int imm20: 1; + }; + unsigned int inst; +} riscv_jal_intruction_t; + +int riscv_decode_offset_from_jal_instruction(const intptr_t inst_addr) +{ + riscv_jal_intruction_t *jal_inst = (riscv_jal_intruction_t *)inst_addr; + // check if it's a valid JAL instruction + if (jal_inst->opcode != 0x6f && jal_inst->rd != 0) { + abort(); + } + return (jal_inst->imm_10_1 | jal_inst->imm_11 << 10 | jal_inst->imm_19_12 << 11 | jal_inst->imm20 << 19) << 1; +}