Skip to content

Commit

Permalink
RISC-V: Make atomic emulation opt-in
Browse files Browse the repository at this point in the history
  • Loading branch information
bugadani committed Nov 6, 2023
1 parent 111d006 commit 95f24bd
Show file tree
Hide file tree
Showing 23 changed files with 139 additions and 132 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Changed

- C2, C3: atomic emulation trap is now opt-in and `esp-hal` now uses `portable-atomic` by default (#904)

### Fixed

- ESP32-C2/C3 examples: fix build error (#899)
Expand Down
11 changes: 9 additions & 2 deletions esp-hal-common/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ strum = { version = "0.25.0", default-features = false, features
void = { version = "1.0.2", default-features = false }
usb-device = { version = "0.2.9", optional = true }

# atomic polyfill options
portable-atomic = { version = "1.5.1", default-features = false, optional = true }
riscv-atomic-emulation-trap = { version = "0.4.1", optional = true }

# async
embedded-hal-async = { version = "=1.0.0-rc.1", optional = true }
embedded-io-async = { version = "0.6.0", optional = true }
Expand All @@ -43,7 +47,6 @@ embassy-time = { version = "0.1.5", optional = true, features = ["nightly"

# RISC-V
esp-riscv-rt = { version = "0.5.0", optional = true, path = "../esp-riscv-rt" }
riscv-atomic-emulation-trap = { version = "0.4.1", optional = true }

# Xtensa
xtensa-lx = { version = "0.8.0", optional = true }
Expand Down Expand Up @@ -125,9 +128,13 @@ embassy-time-systick = []
embassy-time-timg0 = []

# Architecture-specific features (intended for internal use)
riscv = ["critical-section/restore-state-u8", "esp-riscv-rt", "esp-riscv-rt/zero-bss", "riscv-atomic-emulation-trap"]
riscv = ["critical-section/restore-state-u8", "esp-riscv-rt", "esp-riscv-rt/zero-bss"]
xtensa = ["critical-section/restore-state-u32"]

portable-atomic = ["dep:portable-atomic"]
riscv-atomic-emulation = ["dep:riscv-atomic-emulation-trap", "atomic-emulation"]
atomic-emulation = []

# Initialize / clear data sections and RTC memory
rv-init-data = ["esp-riscv-rt/init-data", "esp-riscv-rt/init-rw-text"]
rv-zero-rtc-bss = ["esp-riscv-rt/zero-rtc-fast-bss"]
Expand Down
22 changes: 22 additions & 0 deletions esp-hal-common/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,28 @@ fn main() -> Result<(), Box<dyn Error>> {
unreachable!() // We've confirmed exactly one known device was selected
};

// The C6 has an "atomic" peripheral but it's an exception, not the rule
// For S2, we just keep lying for now. The target has emulation support
// force-enabled.
let has_native_atomic_support = matches!(
device_name,
"esp32" | "esp32s2" | "esp32s3" | "esp32c6" | "esp32h2"
);

let atomic_emulation_enabled = cfg!(feature = "atomic-emulation");
let portable_atomic_enabled = cfg!(feature = "portable-atomic");

if atomic_emulation_enabled && portable_atomic_enabled {
panic!("The `atomic-emulation` and `portable-atomic` features cannot be used together");
}

if has_native_atomic_support {
if atomic_emulation_enabled {
println!("cargo:warning={} has native atomic instructions, the `atomic-emulation` feature is not needed", device_name);
}
println!("cargo:rustc-cfg=has_native_atomic_support");
}

// Load the configuration file for the configured device:
let chip_toml_path = PathBuf::from(env!("CARGO_MANIFEST_DIR"))
.join("devices")
Expand Down
14 changes: 7 additions & 7 deletions esp-hal-common/src/embassy/executor/xtensa/interrupt.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
//! Multicore-aware interrupt-mode executor.
use core::{
cell::UnsafeCell,
marker::PhantomData,
mem::MaybeUninit,
sync::atomic::{AtomicUsize, Ordering},
};
use core::{cell::UnsafeCell, marker::PhantomData, mem::MaybeUninit};

use embassy_executor::{raw, SendSpawner};

use crate::{get_core, interrupt, peripherals, peripherals::SYSTEM};
use crate::{
atomic::{AtomicUsize, Ordering},
get_core,
interrupt,
peripherals::{self, SYSTEM},
};

static FROM_CPU_IRQ_USED: AtomicUsize = AtomicUsize::new(0);

Expand Down
11 changes: 6 additions & 5 deletions esp-hal-common/src/embassy/executor/xtensa/thread.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
//! Multicore-aware thread-mode embassy executor.
use core::{
marker::PhantomData,
sync::atomic::{AtomicBool, Ordering},
};
use core::marker::PhantomData;

use embassy_executor::{raw, Spawner};

use crate::{get_core, prelude::interrupt};
use crate::{
atomic::{AtomicBool, Ordering},
get_core,
prelude::interrupt,
};
#[cfg(multi_core)]
use crate::{
interrupt,
Expand Down
139 changes: 71 additions & 68 deletions esp-hal-common/src/interrupt/riscv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -474,74 +474,77 @@ unsafe fn handle_exception(pc: usize, trap_frame: *mut TrapFrame) {
return;
}

let mut frame = [
0,
(*trap_frame).ra,
(*trap_frame).sp,
(*trap_frame).gp,
(*trap_frame).tp,
(*trap_frame).t0,
(*trap_frame).t1,
(*trap_frame).t2,
(*trap_frame).s0,
(*trap_frame).s1,
(*trap_frame).a0,
(*trap_frame).a1,
(*trap_frame).a2,
(*trap_frame).a3,
(*trap_frame).a4,
(*trap_frame).a5,
(*trap_frame).a6,
(*trap_frame).a7,
(*trap_frame).s2,
(*trap_frame).s3,
(*trap_frame).s4,
(*trap_frame).s5,
(*trap_frame).s6,
(*trap_frame).s7,
(*trap_frame).s8,
(*trap_frame).s9,
(*trap_frame).s10,
(*trap_frame).s11,
(*trap_frame).t3,
(*trap_frame).t4,
(*trap_frame).t5,
(*trap_frame).t6,
];
riscv_atomic_emulation_trap::atomic_emulation((*trap_frame).pc, &mut frame);

(*trap_frame).ra = frame[1];
(*trap_frame).sp = frame[2];
(*trap_frame).gp = frame[3];
(*trap_frame).tp = frame[4];
(*trap_frame).t0 = frame[5];
(*trap_frame).t1 = frame[6];
(*trap_frame).t2 = frame[7];
(*trap_frame).s0 = frame[8];
(*trap_frame).s1 = frame[9];
(*trap_frame).a0 = frame[10];
(*trap_frame).a1 = frame[11];
(*trap_frame).a2 = frame[12];
(*trap_frame).a3 = frame[13];
(*trap_frame).a4 = frame[14];
(*trap_frame).a5 = frame[15];
(*trap_frame).a6 = frame[16];
(*trap_frame).a7 = frame[17];
(*trap_frame).s2 = frame[18];
(*trap_frame).s3 = frame[19];
(*trap_frame).s4 = frame[20];
(*trap_frame).s5 = frame[21];
(*trap_frame).s6 = frame[22];
(*trap_frame).s7 = frame[23];
(*trap_frame).s8 = frame[24];
(*trap_frame).s9 = frame[25];
(*trap_frame).s10 = frame[26];
(*trap_frame).s11 = frame[27];
(*trap_frame).t3 = frame[28];
(*trap_frame).t4 = frame[29];
(*trap_frame).t5 = frame[30];
(*trap_frame).t6 = frame[31];
(*trap_frame).pc = pc + 4;
#[cfg(feature = "atomic-emulation")]
{
let mut frame = [
0,
(*trap_frame).ra,
(*trap_frame).sp,
(*trap_frame).gp,
(*trap_frame).tp,
(*trap_frame).t0,
(*trap_frame).t1,
(*trap_frame).t2,
(*trap_frame).s0,
(*trap_frame).s1,
(*trap_frame).a0,
(*trap_frame).a1,
(*trap_frame).a2,
(*trap_frame).a3,
(*trap_frame).a4,
(*trap_frame).a5,
(*trap_frame).a6,
(*trap_frame).a7,
(*trap_frame).s2,
(*trap_frame).s3,
(*trap_frame).s4,
(*trap_frame).s5,
(*trap_frame).s6,
(*trap_frame).s7,
(*trap_frame).s8,
(*trap_frame).s9,
(*trap_frame).s10,
(*trap_frame).s11,
(*trap_frame).t3,
(*trap_frame).t4,
(*trap_frame).t5,
(*trap_frame).t6,
];
riscv_atomic_emulation_trap::atomic_emulation((*trap_frame).pc, &mut frame);

(*trap_frame).ra = frame[1];
(*trap_frame).sp = frame[2];
(*trap_frame).gp = frame[3];
(*trap_frame).tp = frame[4];
(*trap_frame).t0 = frame[5];
(*trap_frame).t1 = frame[6];
(*trap_frame).t2 = frame[7];
(*trap_frame).s0 = frame[8];
(*trap_frame).s1 = frame[9];
(*trap_frame).a0 = frame[10];
(*trap_frame).a1 = frame[11];
(*trap_frame).a2 = frame[12];
(*trap_frame).a3 = frame[13];
(*trap_frame).a4 = frame[14];
(*trap_frame).a5 = frame[15];
(*trap_frame).a6 = frame[16];
(*trap_frame).a7 = frame[17];
(*trap_frame).s2 = frame[18];
(*trap_frame).s3 = frame[19];
(*trap_frame).s4 = frame[20];
(*trap_frame).s5 = frame[21];
(*trap_frame).s6 = frame[22];
(*trap_frame).s7 = frame[23];
(*trap_frame).s8 = frame[24];
(*trap_frame).s9 = frame[25];
(*trap_frame).s10 = frame[26];
(*trap_frame).s11 = frame[27];
(*trap_frame).t3 = frame[28];
(*trap_frame).t4 = frame[29];
(*trap_frame).t5 = frame[30];
(*trap_frame).t6 = frame[31];
(*trap_frame).pc = pc + 4;
}
}

#[doc(hidden)]
Expand Down
8 changes: 7 additions & 1 deletion esp-hal-common/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,12 @@ pub mod trapframe {
// be directly exposed.
mod soc;

#[cfg(any(has_native_atomic_support, feature = "atomic-emulation"))]
use core::sync::atomic;

#[cfg(feature = "portable-atomic")]
use portable_atomic as atomic;

#[no_mangle]
extern "C" fn EspDefaultHandler(_level: u32, _interrupt: peripherals::Interrupt) {
#[cfg(feature = "log")]
Expand Down Expand Up @@ -317,7 +323,7 @@ mod critical_section_impl {

#[cfg(multi_core)]
mod multicore {
use core::sync::atomic::{AtomicUsize, Ordering};
use crate::atomic::{AtomicUsize, Ordering};

// We're using a value that we know get_raw_core() will never return. This
// avoids an unnecessary increment of the core ID.
Expand Down
2 changes: 1 addition & 1 deletion esp32-hal/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ lis3dh-async = "0.8.0"
sha2 = { version = "0.10.8", default-features = false}
smart-leds = "0.3.0"
ssd1306 = "0.8.4"
static_cell = { version = "=1.2.0", features = ["nightly"] }
static_cell = { version = "2.0.0", features = ["nightly"] }

[features]
default = ["rt", "vectored", "xtal-40mhz"]
Expand Down
16 changes: 0 additions & 16 deletions esp32c2-hal/.cargo/config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,6 @@ runner = "espflash flash --monitor"
rustflags = [
"-C", "link-arg=-Tlinkall.x",
"-C", "force-frame-pointers",

# comment the cfgs below if you do _not_ wish to emulate atomics.
# enable the atomic codegen option for RISCV
"-C", "target-feature=+a",
# tell the core library have atomics even though it's not specified in the target definition
"--cfg", "target_has_atomic_load_store",
"--cfg", 'target_has_atomic_load_store="8"',
"--cfg", 'target_has_atomic_load_store="16"',
"--cfg", 'target_has_atomic_load_store="32"',
"--cfg", 'target_has_atomic_load_store="ptr"',
# enable cas
"--cfg", "target_has_atomic",
"--cfg", 'target_has_atomic="8"',
"--cfg", 'target_has_atomic="16"',
"--cfg", 'target_has_atomic="32"',
"--cfg", 'target_has_atomic="ptr"',
]

[build]
Expand Down
7 changes: 5 additions & 2 deletions esp32c2-hal/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ heapless = "0.7.16"
lis3dh-async = "0.8.0"
sha2 = { version = "0.10.8", default-features = false}
ssd1306 = "0.8.4"
static_cell = { version = "=1.2.0", features = ["nightly"] }
static_cell = { version = "2.0.0", features = ["nightly"] }
hex-literal = "0.4.1"
crypto-bigint = {version = "0.5.3", default-features = false }
elliptic-curve = {version = "0.13.6", default-features = false, features = ["sec1"] }
Expand All @@ -50,7 +50,7 @@ p256 = {version = "0.13.2", default-features = false, features = ["
embassy-sync = "0.3.0"

[features]
default = ["rt", "vectored", "xtal-40mhz"]
default = ["rt", "vectored", "xtal-40mhz", "portable-atomic"]
async = ["esp-hal-common/async"]
debug = ["esp-hal-common/debug"]
defmt = ["esp-hal-common/defmt", "esp-println/defmt"]
Expand All @@ -70,6 +70,9 @@ embassy = ["esp-hal-common/embassy"]
embassy-time-systick = ["esp-hal-common/embassy-time-systick", "embassy-time/tick-hz-16_000_000"]
embassy-time-timg0 = ["esp-hal-common/embassy-time-timg0", "embassy-time/tick-hz-1_000_000"]

portable-atomic = ["esp-hal-common/portable-atomic"]
atomic-emulation = ["esp-hal-common/riscv-atomic-emulation"]

[profile.release]
debug = true

Expand Down
16 changes: 0 additions & 16 deletions esp32c3-hal/.cargo/config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,6 @@ runner = "espflash flash --monitor"
rustflags = [
"-C", "link-arg=-Tlinkall.x",
"-C", "force-frame-pointers",

# comment the cfgs below if you do _not_ wish to emulate atomics.
# enable the atomic codegen option for RISCV
"-C", "target-feature=+a",
# tell the core library have atomics even though it's not specified in the target definition
"--cfg", "target_has_atomic_load_store",
"--cfg", 'target_has_atomic_load_store="8"',
"--cfg", 'target_has_atomic_load_store="16"',
"--cfg", 'target_has_atomic_load_store="32"',
"--cfg", 'target_has_atomic_load_store="ptr"',
# enable cas
"--cfg", "target_has_atomic",
"--cfg", 'target_has_atomic="8"',
"--cfg", 'target_has_atomic="16"',
"--cfg", 'target_has_atomic="32"',
"--cfg", 'target_has_atomic="ptr"',
]

[build]
Expand Down
7 changes: 5 additions & 2 deletions esp32c3-hal/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,11 @@ lis3dh-async = "0.8.0"
sha2 = { version = "0.10.8", default-features = false }
smart-leds = "0.3.0"
ssd1306 = "0.8.4"
static_cell = { version = "=1.2.0", features = ["nightly"] }
static_cell = { version = "2.0.0", features = ["nightly"] }
embassy-sync = "0.3.0"

[features]
default = ["rt", "vectored", "esp-hal-common/rv-zero-rtc-bss"]
default = ["rt", "vectored", "esp-hal-common/rv-zero-rtc-bss", "portable-atomic"]
async = ["esp-hal-common/async"]
debug = ["esp-hal-common/debug"]
defmt = ["esp-hal-common/defmt", "esp-println/defmt"]
Expand All @@ -72,6 +72,9 @@ embassy = ["esp-hal-common/embassy"]
embassy-time-systick = ["esp-hal-common/embassy-time-systick", "embassy-time/tick-hz-16_000_000"]
embassy-time-timg0 = ["esp-hal-common/embassy-time-timg0", "embassy-time/tick-hz-1_000_000"]

portable-atomic = ["esp-hal-common/portable-atomic"]
atomic-emulation = ["esp-hal-common/riscv-atomic-emulation"]

[profile.release]
debug = true

Expand Down
2 changes: 1 addition & 1 deletion esp32c6-hal/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ lis3dh-async = "0.8.0"
sha2 = { version = "0.10.8", default-features = false}
smart-leds = "0.3.0"
ssd1306 = "0.8.4"
static_cell = { version = "=1.2.0", features = ["nightly"] }
static_cell = { version = "2.0.0", features = ["nightly"] }
hex-literal = "0.4.1"
elliptic-curve = {version = "0.13.6", default-features = false, features = ["sec1"] }
p192 = {version = "0.13.0", default-features = false, features = ["arithmetic"] }
Expand Down
Loading

0 comments on commit 95f24bd

Please sign in to comment.