Browse Source
Add ULP Coprocessor support for ESP32C6. Signed-off-by: Lucas Tamborrino <lucas.tamborrino@espressif.com>pull/87487/head
14 changed files with 642 additions and 66 deletions
@ -0,0 +1,63 @@ |
|||||||
|
/* |
||||||
|
* Copyright (c) 2025 Espressif Systems (Shanghai) Co., Ltd. |
||||||
|
* |
||||||
|
* SPDX-License-Identifier: Apache-2.0 |
||||||
|
*/ |
||||||
|
#include <mem.h> |
||||||
|
#include <freq.h> |
||||||
|
#include <zephyr/dt-bindings/gpio/gpio.h> |
||||||
|
#include <zephyr/dt-bindings/interrupt-controller/esp-esp32c6-intmux.h> |
||||||
|
#include <zephyr/dt-bindings/clock/esp32c6_clock.h> |
||||||
|
#include <dt-bindings/pinctrl/esp32c6-pinctrl.h> |
||||||
|
|
||||||
|
/ { |
||||||
|
#address-cells = <1>; |
||||||
|
#size-cells = <1>; |
||||||
|
|
||||||
|
cpus { |
||||||
|
#address-cells = <1>; |
||||||
|
#size-cells = <0>; |
||||||
|
|
||||||
|
cpu0: cpu@0 { |
||||||
|
device_type = "cpu"; |
||||||
|
compatible = "espressif,riscv"; |
||||||
|
riscv,isa = "rv32imac_zicsr_zifencei"; |
||||||
|
reg = <0>; |
||||||
|
clock-source = <ESP32_RTC_FAST_CLK_SRC_XTAL_D2>; |
||||||
|
clock-frequency = <DT_FREQ_M(20)>; |
||||||
|
xtal-freq = <DT_FREQ_M(40)>; |
||||||
|
}; |
||||||
|
}; |
||||||
|
|
||||||
|
soc { |
||||||
|
#address-cells = <1>; |
||||||
|
#size-cells = <1>; |
||||||
|
compatible = "simple-bus"; |
||||||
|
ranges; |
||||||
|
|
||||||
|
sramlp: memory@50000000 { |
||||||
|
#address-cells = <1>; |
||||||
|
#size-cells = <1>; |
||||||
|
compatible = "mmio-sram"; |
||||||
|
reg = <0x50000000 DT_SIZE_K(16)>; |
||||||
|
|
||||||
|
shmlp: memory@0 { |
||||||
|
reg = <0x0 0x10>; |
||||||
|
}; |
||||||
|
}; |
||||||
|
|
||||||
|
flash: flash-controller@60002000 { |
||||||
|
compatible = "espressif,esp32-flash-controller"; |
||||||
|
reg = <0x60002000 0x1000>; |
||||||
|
#address-cells = <1>; |
||||||
|
#size-cells = <1>; |
||||||
|
|
||||||
|
flash0: flash@0 { |
||||||
|
compatible = "soc-nv-flash"; |
||||||
|
erase-block-size = <4096>; |
||||||
|
write-block-size = <4>; |
||||||
|
/* Flash size is specified in SOC/SIP dtsi */ |
||||||
|
}; |
||||||
|
}; |
||||||
|
}; |
||||||
|
}; |
@ -0,0 +1,12 @@ |
|||||||
|
/* |
||||||
|
* Copyright (c) 2025 Espressif Systems (Shanghai) Co., Ltd. |
||||||
|
* |
||||||
|
* SPDX-License-Identifier: Apache-2.0 |
||||||
|
*/ |
||||||
|
|
||||||
|
#include "esp32c6_lpcore.dtsi" |
||||||
|
|
||||||
|
/* 4MB flash */ |
||||||
|
&flash0 { |
||||||
|
reg = <0x0 DT_SIZE_M(4)>; |
||||||
|
}; |
@ -0,0 +1,85 @@ |
|||||||
|
# Copyright (c) 2025 Espressif Systems (Shanghai) Co., Ltd. |
||||||
|
# SPDX-License-Identifier: Apache-2.0 |
||||||
|
|
||||||
|
menu "Ultra Low Power (ULP) Coprocessor" |
||||||
|
|
||||||
|
config ULP_COPROC_ENABLED |
||||||
|
bool "Ultra Low Power (ULP) Coprocessor" |
||||||
|
help |
||||||
|
Enable this feature if you plan to use the ULP Coprocessor. |
||||||
|
Once this option is enabled, further ULP co-processor configuration will appear in the menu. |
||||||
|
|
||||||
|
choice ULP_COPROC_TYPE |
||||||
|
prompt "ULP Coprocessor type" |
||||||
|
depends on ULP_COPROC_ENABLED |
||||||
|
default ULP_COPROC_TYPE_LP_CORE if SOC_SERIES_ESP32C6 |
||||||
|
help |
||||||
|
Choose the ULP Coprocessor type: ULP FSM (Finite State Machine) or ULP RISC-V. |
||||||
|
|
||||||
|
config ULP_COPROC_TYPE_FSM |
||||||
|
bool "ULP FSM (Finite State Machine)" |
||||||
|
depends on SOC_SERIES_ESP32 || SOC_SERIES_ESP32S2 || SOC_SERIES_ESP32S3 |
||||||
|
|
||||||
|
config ULP_COPROC_TYPE_RISCV |
||||||
|
bool "ULP RISC-V" |
||||||
|
depends on SOC_SERIES_ESP32S2 || SOC_SERIES_ESP32S3 |
||||||
|
|
||||||
|
config ULP_COPROC_TYPE_LP_CORE |
||||||
|
bool "LP core RISC-V" |
||||||
|
depends on SOC_SERIES_ESP32C6 |
||||||
|
endchoice |
||||||
|
|
||||||
|
menu "ULP RISC-V Settings" |
||||||
|
depends on ULP_COPROC_TYPE_RISCV |
||||||
|
|
||||||
|
config ULP_RISCV_INTERRUPT_ENABLE |
||||||
|
bool "ULP RISC-V interrupts" |
||||||
|
help |
||||||
|
Turn on this setting to enabled interrupts on the ULP RISC-V core. |
||||||
|
|
||||||
|
endmenu |
||||||
|
|
||||||
|
menu "ULP Debugging Options" |
||||||
|
|
||||||
|
config ULP_PANIC_OUTPUT_ENABLE |
||||||
|
bool "Panic handler outputs to LP UART" |
||||||
|
depends on ULP_COPROC_TYPE_LP_CORE |
||||||
|
help |
||||||
|
Set this option to enable panic handler functionality. If this option is |
||||||
|
enabled then the LP Core will output a panic dump over LP UART, |
||||||
|
similar to what the main core does. Output depends on LP UART already being |
||||||
|
initialized and configured. |
||||||
|
Disabling this option will reduce the LP core binary size by not |
||||||
|
linking in panic handler functionality. |
||||||
|
|
||||||
|
config ULP_HP_UART_CONSOLE_PRINT |
||||||
|
bool "Route lp_core_printf to the console HP-UART" |
||||||
|
depends on ULP_COPROC_TYPE_LP_CORE |
||||||
|
help |
||||||
|
Set this option to route lp_core_printf to the console HP-UART. |
||||||
|
This allows you to easily view print outputs from the LP core, without |
||||||
|
having to connect to the LP-UART. This option comes with the following |
||||||
|
limitations: |
||||||
|
|
||||||
|
1. There is no mutual exclusion between the HP-Core and the LP-Core accessing |
||||||
|
the HP-UART, which means that if both cores are logging heavily the output |
||||||
|
strings might get mangled together. |
||||||
|
2. The HP-UART can only work while the HP-Core is running, which means that |
||||||
|
if the HP-Core is in deep sleep, the LP-Core will not be able to print to the |
||||||
|
console HP-UART. |
||||||
|
|
||||||
|
Due to these limitations it is only recommended to use this option for easy debugging. |
||||||
|
For more serious use-cases you should use the LP-UART. |
||||||
|
|
||||||
|
config ULP_NORESET_UNDER_DEBUG |
||||||
|
bool "Avoid resetting LP core when debugger is attached" |
||||||
|
depends on ULP_COPROC_TYPE_LP_CORE |
||||||
|
default y |
||||||
|
help |
||||||
|
Enable this feature to avoid resetting LP core in sleep mode when debugger is attached, |
||||||
|
otherwise configured HW breakpoints and dcsr.ebreak* bits will be missed. |
||||||
|
This is a workaround until it will be fixed in HW. |
||||||
|
|
||||||
|
endmenu |
||||||
|
|
||||||
|
endmenu # Ultra Low Power (ULP) Coprocessor |
@ -0,0 +1,131 @@ |
|||||||
|
/* |
||||||
|
* Copyright (c) 2025 Espressif Systems (Shanghai) Co., Ltd. |
||||||
|
* SPDX-License-Identifier: Apache-2.0 |
||||||
|
*/ |
||||||
|
#include <zephyr/devicetree.h> |
||||||
|
#include <zephyr/linker/sections.h> |
||||||
|
#include <zephyr/linker/linker-defs.h> |
||||||
|
#include <zephyr/linker/linker-tool.h> |
||||||
|
|
||||||
|
#include "memory.h" |
||||||
|
|
||||||
|
#define ALIGN_DOWN(SIZE, AL) (SIZE & ~(AL - 1)) |
||||||
|
/* Ensure the end where the shared memory starts is aligned to 8 bytes |
||||||
|
if updating this also update the same in ulp_lp_core_memory_shared.c |
||||||
|
*/ |
||||||
|
#define ALIGNED_COPROC_MEM ALIGN_DOWN(ULP_COPROC_RESERVE_MEM, 0x8) |
||||||
|
|
||||||
|
#define RODATA_REGION ram |
||||||
|
#define RAMABLE_REGION ram |
||||||
|
#define ROMABLE_REGION ram |
||||||
|
|
||||||
|
/* User available memory segments */ |
||||||
|
_aligned_coproc_mem = ALIGNED_COPROC_MEM; |
||||||
|
_vector_table_org = LPSRAM_IRAM_START; |
||||||
|
_vector_table_len = 0x80; |
||||||
|
_ram_org = _vector_table_org + _vector_table_len; |
||||||
|
_ram_len = _aligned_coproc_mem - _vector_table_len - ULP_SHARED_MEM; |
||||||
|
_shared_mem_org = _ram_org + _ram_len; |
||||||
|
_shared_mem_len = ULP_SHARED_MEM; |
||||||
|
|
||||||
|
ENTRY(reset_vector) |
||||||
|
|
||||||
|
MEMORY |
||||||
|
{ |
||||||
|
/*first 128byte for exception/interrupt vectors*/ |
||||||
|
vector_table(RX) : ORIGIN = _vector_table_org , LENGTH = _vector_table_len |
||||||
|
ram(RWX) : ORIGIN = _ram_org, LENGTH = _ram_len |
||||||
|
shared_mem_ram(RW) : ORIGIN = _shared_mem_org, LENGTH = _shared_mem_len |
||||||
|
} |
||||||
|
|
||||||
|
SECTIONS |
||||||
|
{ |
||||||
|
.vector.text : |
||||||
|
{ |
||||||
|
__mtvec_base = .; |
||||||
|
KEEP (*(.init.vector .init.vector.*)) |
||||||
|
} > vector_table |
||||||
|
|
||||||
|
. = ORIGIN(ram); |
||||||
|
|
||||||
|
.text ALIGN(4): |
||||||
|
{ |
||||||
|
*(.text.vectors) /* Default reset vector must link to offset 0x80 */ |
||||||
|
__text_region_start = ABSOLUTE(.); |
||||||
|
*(.text) |
||||||
|
*(.text*) |
||||||
|
__text_region_end = ABSOLUTE(.); |
||||||
|
} >ram |
||||||
|
|
||||||
|
#include <zephyr/linker/rel-sections.ld> |
||||||
|
|
||||||
|
.rodata ALIGN(4): |
||||||
|
{ |
||||||
|
__rodata_region_start = ABSOLUTE(.); |
||||||
|
*(.rodata .srodata) |
||||||
|
*(.rodata* .srodata*) |
||||||
|
__rodata_region_end = .; |
||||||
|
|
||||||
|
} > ram |
||||||
|
|
||||||
|
#include <zephyr/linker/common-rom/common-rom-kernel-devices.ld> |
||||||
|
|
||||||
|
.rodata.end ALIGN(4): |
||||||
|
{ |
||||||
|
_rodata_reserved_end = ABSOLUTE(.); |
||||||
|
} > ram |
||||||
|
|
||||||
|
.data ALIGN(4): |
||||||
|
{ |
||||||
|
_image_ram_start = ABSOLUTE(.); |
||||||
|
*(.data) |
||||||
|
*(.data*) |
||||||
|
*(.sdata) |
||||||
|
*(.sdata*) |
||||||
|
|
||||||
|
} > ram |
||||||
|
|
||||||
|
#include <snippets-data-sections.ld> |
||||||
|
#include <zephyr/linker/common-ram.ld> |
||||||
|
#include <snippets-ram-sections.ld> |
||||||
|
|
||||||
|
.data.end ALIGN(4): |
||||||
|
{ |
||||||
|
_image_ram_end = ABSOLUTE(.); |
||||||
|
} > ram |
||||||
|
|
||||||
|
.data.noinit (NOLOAD): |
||||||
|
{ |
||||||
|
. = ALIGN(4); |
||||||
|
*(.noinit) |
||||||
|
*(.noinit.*) |
||||||
|
. = ALIGN(4); |
||||||
|
} > ram |
||||||
|
|
||||||
|
.bss ALIGN(4) : |
||||||
|
{ |
||||||
|
*(.bss) |
||||||
|
*(.bss*) |
||||||
|
*(.sbss) |
||||||
|
*(.sbss*) |
||||||
|
PROVIDE(end = .); |
||||||
|
_heap_sentry = .; |
||||||
|
} >ram |
||||||
|
|
||||||
|
#include <zephyr/linker/ram-end.ld> |
||||||
|
|
||||||
|
__stack_top = ORIGIN(ram) + LENGTH(ram); |
||||||
|
|
||||||
|
#include <zephyr/linker/debug-sections.ld> |
||||||
|
SECTION_PROLOGUE(.riscv.attributes, 0,) |
||||||
|
{ |
||||||
|
KEEP(*(.riscv.attributes)) |
||||||
|
KEEP(*(.gnu.attributes)) |
||||||
|
} |
||||||
|
|
||||||
|
. = ORIGIN(shared_mem_ram); |
||||||
|
.shared_mem (ALIGN(4)) : |
||||||
|
{ |
||||||
|
KEEP(*(.shared_mem)) |
||||||
|
} > shared_mem_ram |
||||||
|
} |
@ -0,0 +1,47 @@ |
|||||||
|
/*
|
||||||
|
* Copyright (c) 2025 Espressif Systems (Shanghai) Co., Ltd. |
||||||
|
* |
||||||
|
* SPDX-License-Identifier: Apache-2.0 |
||||||
|
*/ |
||||||
|
|
||||||
|
#include <zephyr/kernel.h> |
||||||
|
#include "bootloader_flash_priv.h" |
||||||
|
#include <zephyr/storage/flash_map.h> |
||||||
|
#include "ulp_lp_core.h" |
||||||
|
#include "lp_core_uart.h" |
||||||
|
#include <zephyr/logging/log.h> |
||||||
|
|
||||||
|
LOG_MODULE_REGISTER(soc, CONFIG_SOC_LOG_LEVEL); |
||||||
|
|
||||||
|
void IRAM_ATTR lp_core_image_init(void) |
||||||
|
{ |
||||||
|
const uint32_t lpcore_img_off = FIXED_PARTITION_OFFSET(slot0_lpcore_partition); |
||||||
|
const uint32_t lpcore_img_size = 0x4000; |
||||||
|
int ret = 0; |
||||||
|
|
||||||
|
LOG_INF("Getting LPU image at %p, size %d", (void *)lpcore_img_off, lpcore_img_size); |
||||||
|
|
||||||
|
const uint8_t *data = (const uint8_t *)bootloader_mmap(lpcore_img_off, lpcore_img_size); |
||||||
|
|
||||||
|
ret = ulp_lp_core_load_binary(data, lpcore_img_size); |
||||||
|
if (ret) { |
||||||
|
LOG_ERR("Failed to load LP core image: %d", ret); |
||||||
|
} |
||||||
|
|
||||||
|
LOG_INF("LP core image loaded"); |
||||||
|
|
||||||
|
/* Set LP core wakeup source as the HP CPU */ |
||||||
|
ulp_lp_core_cfg_t cfg = { |
||||||
|
.wakeup_source = ULP_LP_CORE_WAKEUP_SOURCE_HP_CPU, |
||||||
|
}; |
||||||
|
|
||||||
|
ret = ulp_lp_core_run(&cfg); |
||||||
|
if (ret) { |
||||||
|
LOG_ERR("Failed to start LP core: %d", ret); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void soc_late_init_hook(void) |
||||||
|
{ |
||||||
|
lp_core_image_init(); |
||||||
|
} |
@ -0,0 +1,32 @@ |
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD |
||||||
|
* |
||||||
|
* SPDX-License-Identifier: Apache-2.0 |
||||||
|
*/ |
||||||
|
|
||||||
|
#include "soc/soc_caps.h" |
||||||
|
#include "esp_rom_caps.h" |
||||||
|
#include "rom/ets_sys.h" |
||||||
|
#include "ulp_lp_core_utils.h" |
||||||
|
#include "ulp_lp_core_lp_timer_shared.h" |
||||||
|
#include "ulp_lp_core_memory_shared.h" |
||||||
|
#include "ulp_lp_core_print.h" |
||||||
|
#include <soc.h> |
||||||
|
#include <kernel_internal.h> |
||||||
|
|
||||||
|
extern void main(void); |
||||||
|
|
||||||
|
/* Initialize lp core related system functions before calling user's main*/ |
||||||
|
void lp_core_startup(void) |
||||||
|
{ |
||||||
|
#if CONFIG_ULP_HP_UART_CONSOLE_PRINT && ESP_ROM_HAS_LP_ROM |
||||||
|
ets_install_putc1(lp_core_print_char); |
||||||
|
#endif |
||||||
|
|
||||||
|
ulp_lp_core_update_wakeup_cause(); |
||||||
|
|
||||||
|
/* Start Zephyr */ |
||||||
|
z_cstart(); |
||||||
|
|
||||||
|
CODE_UNREACHABLE; |
||||||
|
} |
@ -0,0 +1,25 @@ |
|||||||
|
/* |
||||||
|
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD |
||||||
|
* |
||||||
|
* SPDX-License-Identifier: Apache-2.0 |
||||||
|
*/ |
||||||
|
|
||||||
|
.section .text.vectors |
||||||
|
.global reset_vector
|
||||||
|
|
||||||
|
/* The reset vector, jumps to startup code */ |
||||||
|
reset_vector: |
||||||
|
|
||||||
|
/* _vector_table: Only 256-byte aligned addresses are allowed */ |
||||||
|
la t0, _vector_table |
||||||
|
csrw mtvec, t0 |
||||||
|
|
||||||
|
j __start |
||||||
|
|
||||||
|
__start: |
||||||
|
|
||||||
|
/* setup the stack pointer */ |
||||||
|
la sp, __stack_top |
||||||
|
call lp_core_startup |
||||||
|
loop: |
||||||
|
j loop |
@ -0,0 +1,22 @@ |
|||||||
|
/* |
||||||
|
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD |
||||||
|
* |
||||||
|
* SPDX-License-Identifier: Apache-2.0 |
||||||
|
*/ |
||||||
|
|
||||||
|
.section .init.vector,"ax" |
||||||
|
|
||||||
|
.global _vector_table
|
||||||
|
.type _vector_table, @function
|
||||||
|
_vector_table: |
||||||
|
.option push
|
||||||
|
.option norvc
|
||||||
|
|
||||||
|
.rept 30
|
||||||
|
j _panic_handler |
||||||
|
.endr |
||||||
|
j _interrupt_handler // All interrupts are routed to mtvec + 4*30, i.e. the 31st entry |
||||||
|
j _panic_handler |
||||||
|
|
||||||
|
.option pop
|
||||||
|
.size _vector_table, .-_vector_table |
@ -0,0 +1,142 @@ |
|||||||
|
/* |
||||||
|
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD |
||||||
|
* |
||||||
|
* SPDX-License-Identifier: Apache-2.0 |
||||||
|
*/ |
||||||
|
|
||||||
|
#include "riscv/rvruntime-frames.h" |
||||||
|
#include <soc/soc_caps.h> |
||||||
|
|
||||||
|
.equ SAVE_REGS, 32 |
||||||
|
.equ CONTEXT_SIZE, (SAVE_REGS * 4) |
||||||
|
/* Macro which first allocates space on the stack to save general |
||||||
|
* purpose registers, and then save them. GP register is excluded. |
||||||
|
* The default size allocated on the stack is CONTEXT_SIZE, but it |
||||||
|
* can be overridden. */ |
||||||
|
.macro save_general_regs cxt_size=CONTEXT_SIZE |
||||||
|
addi sp, sp, -\cxt_size |
||||||
|
sw ra, RV_STK_RA(sp) |
||||||
|
sw tp, RV_STK_TP(sp) |
||||||
|
sw t0, RV_STK_T0(sp) |
||||||
|
sw t1, RV_STK_T1(sp) |
||||||
|
sw t2, RV_STK_T2(sp) |
||||||
|
sw s0, RV_STK_S0(sp) |
||||||
|
sw s1, RV_STK_S1(sp) |
||||||
|
sw a0, RV_STK_A0(sp) |
||||||
|
sw a1, RV_STK_A1(sp) |
||||||
|
sw a2, RV_STK_A2(sp) |
||||||
|
sw a3, RV_STK_A3(sp) |
||||||
|
sw a4, RV_STK_A4(sp) |
||||||
|
sw a5, RV_STK_A5(sp) |
||||||
|
sw a6, RV_STK_A6(sp) |
||||||
|
sw a7, RV_STK_A7(sp) |
||||||
|
sw s2, RV_STK_S2(sp) |
||||||
|
sw s3, RV_STK_S3(sp) |
||||||
|
sw s4, RV_STK_S4(sp) |
||||||
|
sw s5, RV_STK_S5(sp) |
||||||
|
sw s6, RV_STK_S6(sp) |
||||||
|
sw s7, RV_STK_S7(sp) |
||||||
|
sw s8, RV_STK_S8(sp) |
||||||
|
sw s9, RV_STK_S9(sp) |
||||||
|
sw s10, RV_STK_S10(sp) |
||||||
|
sw s11, RV_STK_S11(sp) |
||||||
|
sw t3, RV_STK_T3(sp) |
||||||
|
sw t4, RV_STK_T4(sp) |
||||||
|
sw t5, RV_STK_T5(sp) |
||||||
|
sw t6, RV_STK_T6(sp) |
||||||
|
.endm |
||||||
|
|
||||||
|
.macro save_mepc
|
||||||
|
csrr t0, mepc |
||||||
|
sw t0, RV_STK_MEPC(sp) |
||||||
|
.endm |
||||||
|
|
||||||
|
/* Restore the general purpose registers (excluding gp) from the context on |
||||||
|
* the stack. The context is then deallocated. The default size is CONTEXT_SIZE |
||||||
|
* but it can be overridden. */ |
||||||
|
.macro restore_general_regs cxt_size=CONTEXT_SIZE |
||||||
|
lw ra, RV_STK_RA(sp) |
||||||
|
lw tp, RV_STK_TP(sp) |
||||||
|
lw t0, RV_STK_T0(sp) |
||||||
|
lw t1, RV_STK_T1(sp) |
||||||
|
lw t2, RV_STK_T2(sp) |
||||||
|
lw s0, RV_STK_S0(sp) |
||||||
|
lw s1, RV_STK_S1(sp) |
||||||
|
lw a0, RV_STK_A0(sp) |
||||||
|
lw a1, RV_STK_A1(sp) |
||||||
|
lw a2, RV_STK_A2(sp) |
||||||
|
lw a3, RV_STK_A3(sp) |
||||||
|
lw a4, RV_STK_A4(sp) |
||||||
|
lw a5, RV_STK_A5(sp) |
||||||
|
lw a6, RV_STK_A6(sp) |
||||||
|
lw a7, RV_STK_A7(sp) |
||||||
|
lw s2, RV_STK_S2(sp) |
||||||
|
lw s3, RV_STK_S3(sp) |
||||||
|
lw s4, RV_STK_S4(sp) |
||||||
|
lw s5, RV_STK_S5(sp) |
||||||
|
lw s6, RV_STK_S6(sp) |
||||||
|
lw s7, RV_STK_S7(sp) |
||||||
|
lw s8, RV_STK_S8(sp) |
||||||
|
lw s9, RV_STK_S9(sp) |
||||||
|
lw s10, RV_STK_S10(sp) |
||||||
|
lw s11, RV_STK_S11(sp) |
||||||
|
lw t3, RV_STK_T3(sp) |
||||||
|
lw t4, RV_STK_T4(sp) |
||||||
|
lw t5, RV_STK_T5(sp) |
||||||
|
lw t6, RV_STK_T6(sp) |
||||||
|
addi sp,sp, \cxt_size |
||||||
|
.endm |
||||||
|
|
||||||
|
.macro restore_mepc
|
||||||
|
lw t0, RV_STK_MEPC(sp) |
||||||
|
csrw mepc, t0 |
||||||
|
.endm |
||||||
|
|
||||||
|
|
||||||
|
/* _panic_handler: handle all exception */ |
||||||
|
.section .text.handlers,"ax" |
||||||
|
.global _panic_handler
|
||||||
|
.type _panic_handler, @function
|
||||||
|
_panic_handler: |
||||||
|
save_general_regs RV_STK_FRMSZ |
||||||
|
save_mepc |
||||||
|
|
||||||
|
addi t0, sp, RV_STK_FRMSZ /* Restore sp with the value when trap happened */ |
||||||
|
|
||||||
|
/* Save CSRs */ |
||||||
|
sw t0, RV_STK_SP(sp) |
||||||
|
csrr t0, mstatus |
||||||
|
sw t0, RV_STK_MSTATUS(sp) |
||||||
|
csrr t0, mcause |
||||||
|
sw t0, RV_STK_MCAUSE(sp) |
||||||
|
csrr t0, mtvec |
||||||
|
sw t0, RV_STK_MTVEC(sp) |
||||||
|
csrr t0, mhartid |
||||||
|
sw t0, RV_STK_MHARTID(sp) |
||||||
|
csrr t0, mtval |
||||||
|
sw t0, RV_STK_MTVAL(sp) |
||||||
|
|
||||||
|
csrr a1, mcause /* Exception cause */ |
||||||
|
|
||||||
|
mv a0, sp /* RvExcFrame *regs */ |
||||||
|
call ulp_lp_core_panic_handler |
||||||
|
_end: |
||||||
|
j _end /* loop forever */ |
||||||
|
|
||||||
|
|
||||||
|
/* _interrupt_handler: handle all interrupt */ |
||||||
|
.section .text.handlers,"ax" |
||||||
|
.global _interrupt_handler
|
||||||
|
.type _interrupt_handler, @function
|
||||||
|
_interrupt_handler: |
||||||
|
/* Save registers & mepc to stack */ |
||||||
|
save_general_regs |
||||||
|
save_mepc |
||||||
|
|
||||||
|
call ulp_lp_core_intr_handler |
||||||
|
|
||||||
|
/* Restore registers & mepc from stack */ |
||||||
|
restore_mepc |
||||||
|
restore_general_regs |
||||||
|
/* Exit, this will also re-enable the interrupts */ |
||||||
|
mret |
Loading…
Reference in new issue