diff --git a/esp-hal-common/Cargo.toml b/esp-hal-common/Cargo.toml index 9bfbca900..536aa76cc 100644 --- a/esp-hal-common/Cargo.toml +++ b/esp-hal-common/Cargo.toml @@ -11,14 +11,15 @@ repository = "https://github.com/esp-rs/esp-hal" license = "MIT OR Apache-2.0" [dependencies] -embedded-hal = { version = "0.2", features = ["unproven"] } -nb = "1.0" -paste = "1.0" -riscv = { version = "0.7", optional = true } -void = { version = "1.0", default-features = false } -xtensa-lx = { version = "0.6.0", optional = true } -xtensa-lx-rt = { version = "0.9.0", optional = true } -procmacros = { path = "../esp-hal-procmacros", package = "esp-hal-procmacros" } +embedded-hal = { version = "0.2", features = ["unproven"] } +nb = "1.0" +paste = "1.0" +riscv = { version = "0.7", optional = true } +riscv-atomic-emulation-trap = { version = "0.1.0", optional = true } +void = { version = "1.0", default-features = false } +xtensa-lx = { version = "0.6.0", optional = true } +xtensa-lx-rt = { version = "0.9.0", optional = true } +procmacros = { path = "../esp-hal-procmacros", package = "esp-hal-procmacros" } # IMPORTANT: # Each supported device MUST have its PAC included below along with a # corresponding feature. @@ -29,7 +30,7 @@ esp32s3_pac = { package = "esp32s3", git = "https://github.com/esp-rs/esp-pacs.g [features] esp32 = ["esp32_pac", "esp32_pac/rt", "xtensa-lx/esp32", "xtensa-lx-rt/esp32", "procmacros/rtc_slow", "dual_core"] -esp32c3 = ["esp32c3_pac", "esp32c3_pac/rt", "riscv", "single_core"] +esp32c3 = ["esp32c3_pac", "esp32c3_pac/rt", "riscv", "riscv-atomic-emulation-trap", "single_core"] esp32s2 = ["esp32s2_pac", "esp32s2_pac/rt", "xtensa-lx/esp32", "xtensa-lx-rt/esp32s2", "procmacros/rtc_slow", "single_core"] esp32s3 = ["esp32s3_pac", "esp32s3_pac/rt", "xtensa-lx/esp32", "xtensa-lx-rt/esp32s3", "procmacros/rtc_slow", "dual_core"] diff --git a/esp-hal-common/src/interrupt/riscv.rs b/esp-hal-common/src/interrupt/riscv.rs index 030ad48f6..c6ae65de8 100644 --- a/esp-hal-common/src/interrupt/riscv.rs +++ b/esp-hal-common/src/interrupt/riscv.rs @@ -187,7 +187,6 @@ pub fn get_status(_core: Cpu) -> u128 { } } -// TODO should this be aligned with Atomic Emulation Trap Handler in future? /// Registers saved in trap handler #[doc(hidden)] #[allow(missing_docs)] @@ -235,14 +234,12 @@ pub struct TrapFrame { #[export_name = "_start_trap_rust_hal"] pub unsafe extern "C" fn start_trap_rust_hal(trap_frame: *mut TrapFrame) { extern "C" { - pub fn _start_trap_rust(trap_frame: *const TrapFrame); - pub fn DefaultHandler(); } let cause = mcause::read(); if cause.is_exception() { - _start_trap_rust(trap_frame); + handle_exception(trap_frame); } else { let code = riscv::register::mcause::read().code(); match code { @@ -282,6 +279,89 @@ pub unsafe extern "C" fn start_trap_rust_hal(trap_frame: *mut TrapFrame) { } } +/// Apply atomic emulation if needed. Call the default exception handler +/// otherwise. +/// +/// # Safety +/// +/// This function is called from an trap handler. +#[doc(hidden)] +unsafe fn handle_exception(trap_frame: *mut TrapFrame) { + extern "C" { + pub fn _start_trap_atomic_rust(trap_frame: *mut riscv_atomic_emulation_trap::TrapFrame); + } + + let mut atomic_emulation_trap_frame = riscv_atomic_emulation_trap::TrapFrame { + pc: riscv::register::mepc::read(), + ra: (*trap_frame).ra, + sp: (*trap_frame).sp, + gp: (*trap_frame).gp, + tp: (*trap_frame).tp, + t0: (*trap_frame).t0, + t1: (*trap_frame).t1, + t2: (*trap_frame).t2, + fp: (*trap_frame).s0, + s1: (*trap_frame).s1, + a0: (*trap_frame).a0, + a1: (*trap_frame).a1, + a2: (*trap_frame).a2, + a3: (*trap_frame).a3, + a4: (*trap_frame).a4, + a5: (*trap_frame).a5, + a6: (*trap_frame).a6, + a7: (*trap_frame).a7, + s2: (*trap_frame).s2, + s3: (*trap_frame).s3, + s4: (*trap_frame).s4, + s5: (*trap_frame).s5, + s6: (*trap_frame).s6, + s7: (*trap_frame).s7, + s8: (*trap_frame).s8, + s9: (*trap_frame).s9, + s10: (*trap_frame).s10, + s11: (*trap_frame).s11, + t3: (*trap_frame).t3, + t4: (*trap_frame).t4, + t5: (*trap_frame).t5, + t6: (*trap_frame).t6, + }; + + _start_trap_atomic_rust(&mut atomic_emulation_trap_frame); + + riscv::register::mepc::write(atomic_emulation_trap_frame.pc); + (*trap_frame).ra = atomic_emulation_trap_frame.ra; + (*trap_frame).sp = atomic_emulation_trap_frame.sp; + (*trap_frame).gp = atomic_emulation_trap_frame.gp; + (*trap_frame).tp = atomic_emulation_trap_frame.tp; + (*trap_frame).t0 = atomic_emulation_trap_frame.t0; + (*trap_frame).t1 = atomic_emulation_trap_frame.t1; + (*trap_frame).t2 = atomic_emulation_trap_frame.t2; + (*trap_frame).s0 = atomic_emulation_trap_frame.fp; + (*trap_frame).s1 = atomic_emulation_trap_frame.s1; + (*trap_frame).a0 = atomic_emulation_trap_frame.a0; + (*trap_frame).a1 = atomic_emulation_trap_frame.a1; + (*trap_frame).a2 = atomic_emulation_trap_frame.a2; + (*trap_frame).a3 = atomic_emulation_trap_frame.a3; + (*trap_frame).a4 = atomic_emulation_trap_frame.a4; + (*trap_frame).a5 = atomic_emulation_trap_frame.a5; + (*trap_frame).a6 = atomic_emulation_trap_frame.a6; + (*trap_frame).a7 = atomic_emulation_trap_frame.a7; + (*trap_frame).s2 = atomic_emulation_trap_frame.s2; + (*trap_frame).s3 = atomic_emulation_trap_frame.s3; + (*trap_frame).s4 = atomic_emulation_trap_frame.s4; + (*trap_frame).s5 = atomic_emulation_trap_frame.s5; + (*trap_frame).s6 = atomic_emulation_trap_frame.s6; + (*trap_frame).s7 = atomic_emulation_trap_frame.s7; + (*trap_frame).s8 = atomic_emulation_trap_frame.s8; + (*trap_frame).s9 = atomic_emulation_trap_frame.s9; + (*trap_frame).s10 = atomic_emulation_trap_frame.s10; + (*trap_frame).s11 = atomic_emulation_trap_frame.s11; + (*trap_frame).t3 = atomic_emulation_trap_frame.t3; + (*trap_frame).t4 = atomic_emulation_trap_frame.t4; + (*trap_frame).t5 = atomic_emulation_trap_frame.t5; + (*trap_frame).t6 = atomic_emulation_trap_frame.t6; +} + #[doc(hidden)] #[no_mangle] pub fn _setup_interrupts() { diff --git a/esp32c3-hal/.cargo/config.toml b/esp32c3-hal/.cargo/config.toml index d8bdbe8ac..460af7588 100644 --- a/esp32c3-hal/.cargo/config.toml +++ b/esp32c3-hal/.cargo/config.toml @@ -4,6 +4,13 @@ rustflags = [ "-C", "link-arg=-Tlinkall.x" ] +# for testing: you can specify this target to see atomic emulation in action +[target.riscv32imac-unknown-none-elf] +runner = "espflash --format direct-boot --monitor" +rustflags = [ + "-C", "link-arg=-Tlinkall.x" +] + [build] target = "riscv32imc-unknown-none-elf" diff --git a/esp32c3-hal/Cargo.toml b/esp32c3-hal/Cargo.toml index bfa608264..8f3f8a2e5 100644 --- a/esp32c3-hal/Cargo.toml +++ b/esp32c3-hal/Cargo.toml @@ -27,13 +27,14 @@ categories = [ format = "direct-boot" [dependencies] -bare-metal = "1.0" -embedded-hal = { version = "0.2", features = ["unproven"] } -nb = "1.0" -riscv = "0.7" -riscv-rt = { version = "0.8.1", optional = true } -void = { version = "1.0", default-features = false } -r0 = "1.0.0" +bare-metal = "1.0" +embedded-hal = { version = "0.2", features = ["unproven"] } +nb = "1.0" +riscv = "0.7" +riscv-rt = { version = "0.8.1", optional = true } +void = { version = "1.0", default-features = false } +r0 = "1.0.0" +riscv-atomic-emulation-trap = "0.1.0" [dependencies.esp-hal-common] path = "../esp-hal-common"