Support atomic emulation for ESP32C3 if needed

This commit is contained in:
bjoernQ 2022-02-24 11:34:34 +01:00 committed by Jesse Braham
parent e7ad8ce7a1
commit 83f961431c
4 changed files with 109 additions and 20 deletions

View File

@ -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"]

View File

@ -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() {

View File

@ -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"

View File

@ -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"