mirror of
https://github.com/esp-rs/esp-hal.git
synced 2025-09-30 22:01:11 +00:00
Move esp-riscv-rt into esp-hal (#578)
* Move esp-riscv-rt into esp-hal * Add changelog entry
This commit is contained in:
parent
aef0ff4e45
commit
8361ca308c
17
.github/workflows/ci.yml
vendored
17
.github/workflows/ci.yml
vendored
@ -312,6 +312,23 @@ jobs:
|
||||
- name: check esp32s3-hal (async, i2c)
|
||||
run: cd esp32s3-hal/ && cargo check --example=embassy_i2c --features=embassy,embassy-time-timg0,async
|
||||
|
||||
esp-riscv-rt:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: dtolnay/rust-toolchain@v1
|
||||
with:
|
||||
target: riscv32imac-unknown-none-elf, riscv32imc-unknown-none-elf
|
||||
toolchain: nightly
|
||||
components: rust-src
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
|
||||
- name: Check esp-riscv-rt (imc)
|
||||
run: cd esp-riscv-rt/ && cargo check --target=riscv32imc-unknown-none-elf -Zbuild-std=core
|
||||
- name: Check esp-riscv-rt (imac)
|
||||
run: cd esp-riscv-rt/ && cargo check --target=riscv32imac-unknown-none-elf -Zbuild-std=core
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# MSRV
|
||||
|
||||
|
@ -37,6 +37,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
- Fix Async GPIO not disabling interupts on chips with multiple banks (#572)
|
||||
- Add unified field-based efuse access
|
||||
- Add `timer_interrupt` example in ESP32-H2 and refactor `clk_src` configuration (#576)
|
||||
- Move `esp-riscv-rt` into esp-hal (#578)
|
||||
|
||||
### Changed
|
||||
|
||||
|
@ -38,7 +38,7 @@ embassy-time = { version = "0.1.1", features = ["nightly"], optional = tru
|
||||
embassy-futures = { version = "0.1.0", optional = true }
|
||||
|
||||
# RISC-V
|
||||
esp-riscv-rt = { version = "0.3.0", optional = true }
|
||||
esp-riscv-rt = { version = "0.3.0", path = "../esp-riscv-rt", optional = true }
|
||||
riscv-atomic-emulation-trap = { version = "0.4.0", optional = true }
|
||||
|
||||
# Xtensa
|
||||
|
26
esp-riscv-rt/Cargo.toml
Normal file
26
esp-riscv-rt/Cargo.toml
Normal file
@ -0,0 +1,26 @@
|
||||
[package]
|
||||
name = "esp-riscv-rt"
|
||||
version = "0.3.0"
|
||||
edition = "2021"
|
||||
rust-version = "1.60"
|
||||
description = "Minimal runtime / startup for RISC-V CPUs from Espressif"
|
||||
repository = "https://github.com/esp-rs/esp-hal"
|
||||
license = "MIT OR Apache-2.0"
|
||||
keywords = ["esp32", "riscv", "runtime", "startup"]
|
||||
categories = ["embedded", "no-std"]
|
||||
|
||||
[dependencies]
|
||||
riscv = "0.10.1"
|
||||
riscv-rt-macros = "0.2.0"
|
||||
|
||||
[dev-dependencies]
|
||||
panic-halt = "0.2.0"
|
||||
|
||||
[features]
|
||||
has-mie-mip = []
|
||||
zero-bss = []
|
||||
zero-rtc-fast-bss = []
|
||||
init-data = []
|
||||
init-rw-text = []
|
||||
init-rtc-fast-data = []
|
||||
init-rtc-fast-text = []
|
32
esp-riscv-rt/README.md
Normal file
32
esp-riscv-rt/README.md
Normal file
@ -0,0 +1,32 @@
|
||||
# esp-riscv-rt
|
||||
|
||||
[](https://crates.io/crates/esp-riscv-rt)
|
||||
[](https://docs.rs/esp-riscv-rt)
|
||||

|
||||

|
||||
|
||||
> Minimal runtime / startup for RISC-V CPUs from Espressif.
|
||||
|
||||
Much of the code in this repository originated in the [rust-embedded/riscv-rt](https://github.com/rust-embedded/riscv-rt) repository.
|
||||
|
||||
## [Documentation](https://docs.rs/crate/esp-riscv-rt)
|
||||
|
||||
## Minimum Supported Rust Version (MSRV)
|
||||
|
||||
This crate is guaranteed to compile on stable Rust 1.60 and up. It _might_
|
||||
compile with older versions but that may change in any new patch release.
|
||||
|
||||
## License
|
||||
|
||||
Licensed under either of:
|
||||
|
||||
- Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
|
||||
- MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
|
||||
|
||||
at your option.
|
||||
|
||||
### Contribution
|
||||
|
||||
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in
|
||||
the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without
|
||||
any additional terms or conditions.
|
6
esp-riscv-rt/build.rs
Normal file
6
esp-riscv-rt/build.rs
Normal file
@ -0,0 +1,6 @@
|
||||
use std::{env, path::PathBuf};
|
||||
|
||||
fn main() {
|
||||
let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
|
||||
println!("cargo:rustc-link-search={}", out_dir.display());
|
||||
}
|
644
esp-riscv-rt/src/lib.rs
Normal file
644
esp-riscv-rt/src/lib.rs
Normal file
@ -0,0 +1,644 @@
|
||||
//! Minimal startup / runtime for RISC-V CPUs from Espressif
|
||||
//!
|
||||
//! # Minimum Supported Rust Version (MSRV)
|
||||
//!
|
||||
//! This crate is guaranteed to compile on stable Rust 1.60 and up. It *might*
|
||||
//! compile with older versions but that may change in any new patch release.
|
||||
//!
|
||||
//! # Features
|
||||
//!
|
||||
//! This crate provides:
|
||||
//!
|
||||
//! - Before main initialization of the `.bss` and `.data` sections controlled
|
||||
//! by features
|
||||
//! - `#[entry]` to declare the entry point of the program
|
||||
|
||||
// NOTE: Adapted from riscv-rt/src/lib.rs
|
||||
#![no_std]
|
||||
|
||||
use core::arch::global_asm;
|
||||
|
||||
pub use riscv;
|
||||
use riscv::register::{
|
||||
mcause,
|
||||
mtvec::{self, TrapMode},
|
||||
};
|
||||
pub use riscv_rt_macros::{entry, pre_init};
|
||||
|
||||
pub use self::Interrupt as interrupt;
|
||||
|
||||
#[export_name = "error: esp-riscv-rt appears more than once in the dependency graph"]
|
||||
#[doc(hidden)]
|
||||
pub static __ONCE__: () = ();
|
||||
|
||||
extern "C" {
|
||||
// Boundaries of the .bss section
|
||||
static mut _bss_end: u32;
|
||||
static mut _bss_start: u32;
|
||||
|
||||
// Boundaries of the .data section
|
||||
static mut _data_end: u32;
|
||||
static mut _data_start: u32;
|
||||
|
||||
// Initial values of the .data section (stored in Flash)
|
||||
static _sidata: u32;
|
||||
}
|
||||
|
||||
/// Rust entry point (_start_rust)
|
||||
///
|
||||
/// Zeros bss section, initializes data section and calls main. This function
|
||||
/// never returns.
|
||||
#[link_section = ".init.rust"]
|
||||
#[export_name = "_start_rust"]
|
||||
pub unsafe extern "C" fn start_rust(a0: usize, a1: usize, a2: usize) -> ! {
|
||||
extern "Rust" {
|
||||
// This symbol will be provided by the user via `#[entry]`
|
||||
fn main(a0: usize, a1: usize, a2: usize) -> !;
|
||||
|
||||
fn __post_init();
|
||||
|
||||
fn _setup_interrupts();
|
||||
|
||||
}
|
||||
|
||||
__post_init();
|
||||
|
||||
_setup_interrupts();
|
||||
|
||||
main(a0, a1, a2);
|
||||
}
|
||||
|
||||
/// Registers saved in trap handler
|
||||
#[allow(missing_docs)]
|
||||
#[derive(Debug, Default, Clone, Copy)]
|
||||
#[repr(C)]
|
||||
pub struct TrapFrame {
|
||||
pub ra: usize,
|
||||
pub t0: usize,
|
||||
pub t1: usize,
|
||||
pub t2: usize,
|
||||
pub t3: usize,
|
||||
pub t4: usize,
|
||||
pub t5: usize,
|
||||
pub t6: usize,
|
||||
pub a0: usize,
|
||||
pub a1: usize,
|
||||
pub a2: usize,
|
||||
pub a3: usize,
|
||||
pub a4: usize,
|
||||
pub a5: usize,
|
||||
pub a6: usize,
|
||||
pub a7: usize,
|
||||
pub s0: usize,
|
||||
pub s1: usize,
|
||||
pub s2: usize,
|
||||
pub s3: usize,
|
||||
pub s4: usize,
|
||||
pub s5: usize,
|
||||
pub s6: usize,
|
||||
pub s7: usize,
|
||||
pub s8: usize,
|
||||
pub s9: usize,
|
||||
pub s10: usize,
|
||||
pub s11: usize,
|
||||
pub gp: usize,
|
||||
pub tp: usize,
|
||||
pub sp: usize,
|
||||
pub pc: usize,
|
||||
pub mstatus: usize,
|
||||
pub mcause: usize,
|
||||
pub mtval: usize,
|
||||
}
|
||||
|
||||
/// Trap entry point rust (_start_trap_rust)
|
||||
///
|
||||
/// `scause`/`mcause` is read to determine the cause of the trap. XLEN-1 bit
|
||||
/// indicates if it's an interrupt or an exception. The result is examined and
|
||||
/// ExceptionHandler or one of the core interrupt handlers is called.
|
||||
#[link_section = ".trap.rust"]
|
||||
#[export_name = "_start_trap_rust"]
|
||||
pub unsafe extern "C" fn start_trap_rust(trap_frame: *const TrapFrame) {
|
||||
extern "C" {
|
||||
fn ExceptionHandler(trap_frame: &TrapFrame);
|
||||
fn DefaultHandler();
|
||||
}
|
||||
|
||||
unsafe {
|
||||
let cause = mcause::read();
|
||||
|
||||
if cause.is_exception() {
|
||||
ExceptionHandler(&*trap_frame)
|
||||
} else if cause.code() < __INTERRUPTS.len() {
|
||||
let h = &__INTERRUPTS[cause.code()];
|
||||
if h.reserved == 0 {
|
||||
DefaultHandler();
|
||||
} else {
|
||||
(h.handler)();
|
||||
}
|
||||
} else {
|
||||
DefaultHandler();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
#[no_mangle]
|
||||
#[allow(unused_variables, non_snake_case)]
|
||||
pub fn DefaultExceptionHandler(trap_frame: &TrapFrame) -> ! {
|
||||
loop {
|
||||
// Prevent this from turning into a UDF instruction
|
||||
// see rust-lang/rust#28728 for details
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
#[no_mangle]
|
||||
#[allow(unused_variables, non_snake_case)]
|
||||
pub fn DefaultInterruptHandler() {
|
||||
loop {
|
||||
// Prevent this from turning into a UDF instruction
|
||||
// see rust-lang/rust#28728 for details
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Interrupts
|
||||
#[doc(hidden)]
|
||||
pub enum Interrupt {
|
||||
UserSoft,
|
||||
SupervisorSoft,
|
||||
MachineSoft,
|
||||
UserTimer,
|
||||
SupervisorTimer,
|
||||
MachineTimer,
|
||||
UserExternal,
|
||||
SupervisorExternal,
|
||||
MachineExternal,
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
fn UserSoft();
|
||||
fn SupervisorSoft();
|
||||
fn MachineSoft();
|
||||
fn UserTimer();
|
||||
fn SupervisorTimer();
|
||||
fn MachineTimer();
|
||||
fn UserExternal();
|
||||
fn SupervisorExternal();
|
||||
fn MachineExternal();
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub union Vector {
|
||||
pub handler: unsafe extern "C" fn(),
|
||||
pub reserved: usize,
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
#[no_mangle]
|
||||
pub static __INTERRUPTS: [Vector; 12] = [
|
||||
Vector { handler: UserSoft },
|
||||
Vector {
|
||||
handler: SupervisorSoft,
|
||||
},
|
||||
Vector { reserved: 0 },
|
||||
Vector {
|
||||
handler: MachineSoft,
|
||||
},
|
||||
Vector { handler: UserTimer },
|
||||
Vector {
|
||||
handler: SupervisorTimer,
|
||||
},
|
||||
Vector { reserved: 0 },
|
||||
Vector {
|
||||
handler: MachineTimer,
|
||||
},
|
||||
Vector {
|
||||
handler: UserExternal,
|
||||
},
|
||||
Vector {
|
||||
handler: SupervisorExternal,
|
||||
},
|
||||
Vector { reserved: 0 },
|
||||
Vector {
|
||||
handler: MachineExternal,
|
||||
},
|
||||
];
|
||||
|
||||
#[doc(hidden)]
|
||||
#[no_mangle]
|
||||
#[rustfmt::skip]
|
||||
pub unsafe extern "Rust" fn default_post_init() {}
|
||||
|
||||
/// Default implementation of `_setup_interrupts` that sets `mtvec`/`stvec` to a
|
||||
/// trap handler address.
|
||||
#[doc(hidden)]
|
||||
#[no_mangle]
|
||||
#[rustfmt::skip]
|
||||
pub unsafe extern "Rust" fn default_setup_interrupts() {
|
||||
extern "C" {
|
||||
fn _start_trap();
|
||||
}
|
||||
|
||||
mtvec::write(_start_trap as usize, TrapMode::Direct);
|
||||
}
|
||||
|
||||
/// Parse cfg attributes inside a global_asm call.
|
||||
macro_rules! cfg_global_asm {
|
||||
{@inner, [$($x:tt)*], } => {
|
||||
global_asm!{$($x)*}
|
||||
};
|
||||
(@inner, [$($x:tt)*], #[cfg($meta:meta)] $asm:literal, $($rest:tt)*) => {
|
||||
#[cfg($meta)]
|
||||
cfg_global_asm!{@inner, [$($x)* $asm,], $($rest)*}
|
||||
#[cfg(not($meta))]
|
||||
cfg_global_asm!{@inner, [$($x)*], $($rest)*}
|
||||
};
|
||||
{@inner, [$($x:tt)*], $asm:literal, $($rest:tt)*} => {
|
||||
cfg_global_asm!{@inner, [$($x)* $asm,], $($rest)*}
|
||||
};
|
||||
{$($asms:tt)*} => {
|
||||
cfg_global_asm!{@inner, [], $($asms)*}
|
||||
};
|
||||
}
|
||||
|
||||
cfg_global_asm! {
|
||||
r#"
|
||||
/*
|
||||
Entry point of all programs (_start).
|
||||
|
||||
It initializes DWARF call frame information, the stack pointer, the
|
||||
frame pointer (needed for closures to work in start_rust) and the global
|
||||
pointer. Then it calls _start_rust.
|
||||
*/
|
||||
|
||||
.section .init, "ax"
|
||||
.global _start
|
||||
|
||||
_start:
|
||||
/* Jump to the absolute address defined by the linker script. */
|
||||
lui ra, %hi(_abs_start)
|
||||
jr %lo(_abs_start)(ra)
|
||||
|
||||
_abs_start:
|
||||
.option norelax
|
||||
.cfi_startproc
|
||||
.cfi_undefined ra
|
||||
"#,
|
||||
#[cfg(feature = "has-mie-mip")]
|
||||
r#"
|
||||
csrw mie, 0
|
||||
csrw mip, 0
|
||||
"#,
|
||||
#[cfg(feature = "zero-bss")]
|
||||
r#"
|
||||
la a0, _bss_start
|
||||
la a1, _bss_end
|
||||
mv a3, x0
|
||||
1:
|
||||
sw a3, 0(a0)
|
||||
addi a0, a0, 4
|
||||
blt a0, a1, 1b
|
||||
"#,
|
||||
#[cfg(feature = "zero-rtc-fast-bss")]
|
||||
r#"
|
||||
la a0, _rtc_fast_bss_start
|
||||
la a1, _rtc_fast_bss_end
|
||||
mv a3, x0
|
||||
1:
|
||||
sw a3, 0(a0)
|
||||
addi a0, a0, 4
|
||||
blt a0, a1, 1b
|
||||
"#,
|
||||
#[cfg(feature = "init-data")]
|
||||
r#"
|
||||
la a0, _data_start
|
||||
la a1, _data_end
|
||||
la a2, _sidata
|
||||
1:
|
||||
lw a3, 0(a2)
|
||||
sw a3, 0(a0)
|
||||
addi a0, a0, 4
|
||||
addi a2, a2, 4
|
||||
blt a0, a1, 1b
|
||||
"#,
|
||||
#[cfg(feature = "init-rw-text")]
|
||||
r#"
|
||||
la a0, _srwtext
|
||||
la a1, _erwtext
|
||||
la a2, _irwtext
|
||||
1:
|
||||
lw a3, 0(a2)
|
||||
sw a3, 0(a0)
|
||||
addi a0, a0, 4
|
||||
addi a2, a2, 4
|
||||
blt a0, a1, 1b
|
||||
"#,
|
||||
#[cfg(feature = "init-rtc-fast-data")]
|
||||
r#"
|
||||
la a0, _rtc_fast_data_start
|
||||
la a1, _rtc_fast_data_end
|
||||
la a2, _irtc_fast_data
|
||||
1:
|
||||
lw a3, 0(a2)
|
||||
sw a3, 0(a0)
|
||||
addi a0, a0, 4
|
||||
addi a2, a2, 4
|
||||
blt a0, a1, 1b
|
||||
"#,
|
||||
#[cfg(feature = "init-rtc-fast-text")]
|
||||
r#"
|
||||
la a0, _srtc_fast_text
|
||||
la a1, _ertc_fast_text
|
||||
la a2, _irtc_fast_text
|
||||
1:
|
||||
lw a3, 0(a2)
|
||||
sw a3, 0(a0)
|
||||
addi a0, a0, 4
|
||||
addi a2, a2, 4
|
||||
blt a0, a1, 1b
|
||||
"#,
|
||||
r#"
|
||||
li x1, 0
|
||||
li x2, 0
|
||||
li x3, 0
|
||||
li x4, 0
|
||||
li x5, 0
|
||||
li x6, 0
|
||||
li x7, 0
|
||||
li x8, 0
|
||||
li x9, 0
|
||||
li x10,0
|
||||
li x11,0
|
||||
li x12,0
|
||||
li x13,0
|
||||
li x14,0
|
||||
li x15,0
|
||||
li x16,0
|
||||
li x17,0
|
||||
li x18,0
|
||||
li x19,0
|
||||
li x20,0
|
||||
li x21,0
|
||||
li x22,0
|
||||
li x23,0
|
||||
li x24,0
|
||||
li x25,0
|
||||
li x26,0
|
||||
li x27,0
|
||||
li x28,0
|
||||
li x29,0
|
||||
li x30,0
|
||||
li x31,0
|
||||
|
||||
.option push
|
||||
.option norelax
|
||||
la gp, __global_pointer$
|
||||
.option pop
|
||||
|
||||
// Check hart ID
|
||||
csrr t2, mhartid
|
||||
lui t0, %hi(_max_hart_id)
|
||||
add t0, t0, %lo(_max_hart_id)
|
||||
bgtu t2, t0, abort
|
||||
|
||||
// Allocate stacks
|
||||
la sp, _stack_start
|
||||
lui t0, %hi(_hart_stack_size)
|
||||
add t0, t0, %lo(_hart_stack_size)
|
||||
|
||||
beqz t2, 2f // Jump if single-hart
|
||||
mv t1, t2
|
||||
mv t3, t0
|
||||
1:
|
||||
add t0, t0, t3
|
||||
addi t1, t1, -1
|
||||
bnez t1, 1b
|
||||
2:
|
||||
sub sp, sp, t0
|
||||
|
||||
// Set frame pointer
|
||||
add s0, sp, zero
|
||||
|
||||
jal zero, _start_rust
|
||||
|
||||
.cfi_endproc
|
||||
|
||||
/*
|
||||
Trap entry points (_start_trap, _start_trapN for N in 1..=31)
|
||||
|
||||
The default implementation saves all registers to the stack and calls
|
||||
_start_trap_rust, then restores all saved registers before `mret`
|
||||
*/
|
||||
.section .trap, "ax"
|
||||
.weak _start_trap
|
||||
.weak _start_trap1
|
||||
.weak _start_trap2
|
||||
.weak _start_trap3
|
||||
.weak _start_trap4
|
||||
.weak _start_trap5
|
||||
.weak _start_trap6
|
||||
.weak _start_trap7
|
||||
.weak _start_trap8
|
||||
.weak _start_trap9
|
||||
.weak _start_trap10
|
||||
.weak _start_trap11
|
||||
.weak _start_trap12
|
||||
.weak _start_trap13
|
||||
.weak _start_trap14
|
||||
.weak _start_trap15
|
||||
.weak _start_trap16
|
||||
.weak _start_trap17
|
||||
.weak _start_trap18
|
||||
.weak _start_trap19
|
||||
.weak _start_trap20
|
||||
.weak _start_trap21
|
||||
.weak _start_trap22
|
||||
.weak _start_trap23
|
||||
.weak _start_trap24
|
||||
.weak _start_trap25
|
||||
.weak _start_trap26
|
||||
.weak _start_trap27
|
||||
.weak _start_trap28
|
||||
.weak _start_trap29
|
||||
.weak _start_trap30
|
||||
.weak _start_trap31
|
||||
|
||||
_start_trap1:
|
||||
_start_trap2:
|
||||
_start_trap3:
|
||||
_start_trap4:
|
||||
_start_trap5:
|
||||
_start_trap6:
|
||||
_start_trap7:
|
||||
_start_trap8:
|
||||
_start_trap9:
|
||||
_start_trap10:
|
||||
_start_trap11:
|
||||
_start_trap12:
|
||||
_start_trap13:
|
||||
_start_trap14:
|
||||
_start_trap15:
|
||||
_start_trap16:
|
||||
_start_trap17:
|
||||
_start_trap18:
|
||||
_start_trap19:
|
||||
_start_trap20:
|
||||
_start_trap21:
|
||||
_start_trap22:
|
||||
_start_trap23:
|
||||
_start_trap24:
|
||||
_start_trap25:
|
||||
_start_trap26:
|
||||
_start_trap27:
|
||||
_start_trap28:
|
||||
_start_trap29:
|
||||
_start_trap30:
|
||||
_start_trap31:
|
||||
|
||||
_start_trap:
|
||||
addi sp, sp, -40*4
|
||||
|
||||
sw ra, 0*4(sp)
|
||||
sw t0, 1*4(sp)
|
||||
sw t1, 2*4(sp)
|
||||
sw t2, 3*4(sp)
|
||||
sw t3, 4*4(sp)
|
||||
sw t4, 5*4(sp)
|
||||
sw t5, 6*4(sp)
|
||||
sw t6, 7*4(sp)
|
||||
sw a0, 8*4(sp)
|
||||
sw a1, 9*4(sp)
|
||||
sw a2, 10*4(sp)
|
||||
sw a3, 11*4(sp)
|
||||
sw a4, 12*4(sp)
|
||||
sw a5, 13*4(sp)
|
||||
sw a6, 14*4(sp)
|
||||
sw a7, 15*4(sp)
|
||||
sw s0, 16*4(sp)
|
||||
sw s1, 17*4(sp)
|
||||
sw s2, 18*4(sp)
|
||||
sw s3, 19*4(sp)
|
||||
sw s4, 20*4(sp)
|
||||
sw s5, 21*4(sp)
|
||||
sw s6, 22*4(sp)
|
||||
sw s7, 23*4(sp)
|
||||
sw s8, 24*4(sp)
|
||||
sw s9, 25*4(sp)
|
||||
sw s10, 26*4(sp)
|
||||
sw s11, 27*4(sp)
|
||||
sw gp, 28*4(sp)
|
||||
sw tp, 29*4(sp)
|
||||
csrrs t1, mepc, x0
|
||||
sw t1, 31*4(sp)
|
||||
csrrs t1, mstatus, x0
|
||||
sw t1, 32*4(sp)
|
||||
csrrs t1, mcause, x0
|
||||
sw t1, 33*4(sp)
|
||||
csrrs t1, mtval, x0
|
||||
sw t1, 34*4(sp)
|
||||
|
||||
addi s0, sp, 40*4
|
||||
sw s0, 30*4(sp)
|
||||
|
||||
add a0, sp, zero
|
||||
jal ra, _start_trap_rust_hal
|
||||
|
||||
lw t1, 31*4(sp)
|
||||
csrrw x0, mepc, t1
|
||||
|
||||
lw t1, 32*4(sp)
|
||||
csrrw x0, mstatus, t1
|
||||
|
||||
lw ra, 0*4(sp)
|
||||
lw t0, 1*4(sp)
|
||||
lw t1, 2*4(sp)
|
||||
lw t2, 3*4(sp)
|
||||
lw t3, 4*4(sp)
|
||||
lw t4, 5*4(sp)
|
||||
lw t5, 6*4(sp)
|
||||
lw t6, 7*4(sp)
|
||||
lw a0, 8*4(sp)
|
||||
lw a1, 9*4(sp)
|
||||
lw a2, 10*4(sp)
|
||||
lw a3, 11*4(sp)
|
||||
lw a4, 12*4(sp)
|
||||
lw a5, 13*4(sp)
|
||||
lw a6, 14*4(sp)
|
||||
lw a7, 15*4(sp)
|
||||
lw s0, 16*4(sp)
|
||||
lw s1, 17*4(sp)
|
||||
lw s2, 18*4(sp)
|
||||
lw s3, 19*4(sp)
|
||||
lw s4, 20*4(sp)
|
||||
lw s5, 21*4(sp)
|
||||
lw s6, 22*4(sp)
|
||||
lw s7, 23*4(sp)
|
||||
lw s8, 24*4(sp)
|
||||
lw s9, 25*4(sp)
|
||||
lw s10, 26*4(sp)
|
||||
lw s11, 27*4(sp)
|
||||
lw gp, 28*4(sp)
|
||||
lw tp, 29*4(sp)
|
||||
lw sp, 30*4(sp)
|
||||
|
||||
# SP was restored from the original SP
|
||||
mret
|
||||
|
||||
/* Make sure there is an abort when linking */
|
||||
.section .text.abort
|
||||
.globl abort
|
||||
abort:
|
||||
j abort
|
||||
|
||||
/*
|
||||
Interrupt vector table (_vector_table)
|
||||
*/
|
||||
|
||||
.section .trap, "ax"
|
||||
.weak _vector_table
|
||||
.type _vector_table, @function
|
||||
|
||||
.option push
|
||||
.balign 0x100
|
||||
.option norelax
|
||||
.option norvc
|
||||
|
||||
_vector_table:
|
||||
j _start_trap
|
||||
j _start_trap1
|
||||
j _start_trap2
|
||||
j _start_trap3
|
||||
j _start_trap4
|
||||
j _start_trap5
|
||||
j _start_trap6
|
||||
j _start_trap7
|
||||
j _start_trap8
|
||||
j _start_trap9
|
||||
j _start_trap10
|
||||
j _start_trap11
|
||||
j _start_trap12
|
||||
j _start_trap13
|
||||
j _start_trap14
|
||||
j _start_trap15
|
||||
j _start_trap16
|
||||
j _start_trap17
|
||||
j _start_trap18
|
||||
j _start_trap19
|
||||
j _start_trap20
|
||||
j _start_trap21
|
||||
j _start_trap22
|
||||
j _start_trap23
|
||||
j _start_trap24
|
||||
j _start_trap25
|
||||
j _start_trap26
|
||||
j _start_trap27
|
||||
j _start_trap28
|
||||
j _start_trap29
|
||||
j _start_trap30
|
||||
j _start_trap31
|
||||
|
||||
.option pop
|
||||
"#,
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user