Skip to content
This repository has been archived by the owner on May 27, 2024. It is now read-only.

Multicore aware (ESP32, ESP32-S3) #29

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 32 additions & 11 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,12 +1,33 @@
{
// "editor.formatOnSave": true,

"rust-analyzer.server.extraEnv": {
"CARGO_TARGET_DIR": "./target_ra"
},

"rust-analyzer.cargo.features": [
"esp32","low-level"
],
"rust-analyzer.cargo.target": "xtensa-esp32-none-elf",
}
{
"rust-analyzer.cargo.features": [
"esp32"
],
"rust-analyzer.check.overrideCommand": [
"cargo",
"check",
"--examples",
"--bins",
"--lib",
"--message-format=json",
"--no-default-features",
"--features",
"esp32",
],
"rust-analyzer.check.allTargets": false,
"rust-analyzer.cargo.buildScripts.invocationLocation": "root",
"rust-analyzer.check.invocationLocation": "root",
"rust-analyzer.cargo.buildScripts.overrideCommand": [
"cargo",
"check",
"--examples",
"--bins",
"--lib",
"--message-format=json",
"--no-default-features",
"--features",
"esp32",
],
"rust-analyzer.showUnlinkedFileNotification": false,
}

4 changes: 3 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ name = "low_level"
required-features = ["low-level"]

[features]
default = ["critical-section", "storage"]
default = ["critical-section", "multicore-aware", "storage"]
critical-section = ["dep:critical-section"]
# ReadStorage/Storage traits
storage = []
Expand All @@ -84,6 +84,8 @@ esp32s2 = []
esp32s3 = []
# Enable flash emulation to run tests
emulation = []
# Park the other core on multicore targets
multicore-aware = []

# this feature is reserved for very specific use-cases - usually you don't want to use this!
low-level = []
68 changes: 68 additions & 0 deletions src/esp32.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use core::arch::asm;

use crate::maybe_with_critical_section;

const ESP_ROM_SPIFLASH_READ: u32 = 0x40062ed8;
Expand Down Expand Up @@ -274,3 +276,69 @@ pub(crate) fn esp_rom_spiflash_unlock() -> i32 {
0
})
}

#[allow(clippy::identity_op)]
pub fn park_other_core() -> bool {
const SW_CPU_STALL: u32 = 0x3ff480ac;
const OPTIONS0: u32 = 0x3ff48000;

let sw_cpu_stall = SW_CPU_STALL as *mut u32;
let options0 = OPTIONS0 as *mut u32;

let current = get_current_core();
let other_was_running;

match current {
0 => unsafe {
other_was_running = (options0.read_volatile() & 0b11) == 0;
sw_cpu_stall
.write_volatile(sw_cpu_stall.read_volatile() & !(0b111111 << 20) | (0x21 << 20));
options0.write_volatile(options0.read_volatile() & !(0b11) | 0b10);
},
_ => unsafe {
other_was_running = (options0.read_volatile() & 0b1100) == 0;
sw_cpu_stall
.write_volatile(sw_cpu_stall.read_volatile() & !(0b111111 << 26) | (0x21 << 26));
options0.write_volatile(options0.read_volatile() & !(0b1100) | 0b1000);
},
}

other_was_running
}

#[allow(clippy::identity_op)]
pub fn unpark_other_core(enable: bool) {
if enable {
const SW_CPU_STALL: u32 = 0x3ff480ac;
const OPTIONS0: u32 = 0x3ff48000;

let sw_cpu_stall = SW_CPU_STALL as *mut u32;
let options0 = OPTIONS0 as *mut u32;

let current = get_current_core();

match current {
0 => unsafe {
sw_cpu_stall
.write_volatile(sw_cpu_stall.read_volatile() & !(0b111111 << 20) | (0x0 << 20));
options0.write_volatile(options0.read_volatile() & !(0b11) | 0b00);
},
_ => unsafe {
sw_cpu_stall
.write_volatile(sw_cpu_stall.read_volatile() & !(0b111111 << 26) | (0x0 << 26));
options0.write_volatile(options0.read_volatile() & !(0b1100) | 0b0000);
},
}
}
}

#[inline]
fn get_current_core() -> u8 {
let mut x: u32;
unsafe { asm!("rsr.prid {0}", out(reg) x, options(nostack)) };

match ((x >> 13) & 1) != 0 {
false => 0,
true => 1,
}
}
6 changes: 6 additions & 0 deletions src/esp32c2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,9 @@ pub(crate) fn esp_rom_spiflash_write(dest_addr: u32, data: *const u32, len: u32)
esp_rom_spiflash_write(dest_addr, data, len)
})
}

pub fn park_other_core() -> bool {
false
}

pub fn unpark_other_core(_enable: bool) {}
6 changes: 6 additions & 0 deletions src/esp32c3.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,9 @@ pub(crate) fn esp_rom_spiflash_write(dest_addr: u32, data: *const u32, len: u32)
esp_rom_spiflash_write(dest_addr, data, len)
})
}

pub fn park_other_core() -> bool {
false
}

pub fn unpark_other_core(_enable: bool) {}
6 changes: 6 additions & 0 deletions src/esp32c6.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,9 @@ pub(crate) fn esp_rom_spiflash_write(dest_addr: u32, data: *const u32, len: u32)
esp_rom_spiflash_write(dest_addr, data, len)
})
}

pub fn park_other_core() -> bool {
false
}

pub fn unpark_other_core(_enable: bool) {}
6 changes: 6 additions & 0 deletions src/esp32h2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,9 @@ pub(crate) fn esp_rom_spiflash_write(dest_addr: u32, data: *const u32, len: u32)
esp_rom_spiflash_write(dest_addr, data, len)
})
}

pub fn park_other_core() -> bool {
false
}

pub fn unpark_other_core(_enable: bool) {}
6 changes: 6 additions & 0 deletions src/esp32s2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,9 @@ pub(crate) fn esp_rom_spiflash_write(dest_addr: u32, data: *const u32, len: u32)
esp_rom_spiflash_write(dest_addr, data, len)
})
}

pub fn park_other_core() -> bool {
false
}

pub fn unpark_other_core(_enable: bool) {}
68 changes: 68 additions & 0 deletions src/esp32s3.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use core::arch::asm;

use crate::maybe_with_critical_section;

const ESP_ROM_SPIFLASH_READ: u32 = 0x40000a20;
Expand Down Expand Up @@ -44,3 +46,69 @@ pub(crate) fn esp_rom_spiflash_write(dest_addr: u32, data: *const u32, len: u32)
esp_rom_spiflash_write(dest_addr, data, len)
})
}

#[allow(clippy::identity_op)]
pub fn park_other_core() -> bool {
const SW_CPU_STALL: u32 = 0x600080bc;
const OPTIONS0: u32 = 0x60008000;

let sw_cpu_stall = SW_CPU_STALL as *mut u32;
let options0 = OPTIONS0 as *mut u32;

let current = get_current_core();
let other_was_running;

match current {
0 => unsafe {
other_was_running = (options0.read_volatile() & 0b11) == 0;
sw_cpu_stall
.write_volatile(sw_cpu_stall.read_volatile() & !(0b111111 << 20) | (0x21 << 20));
options0.write_volatile(options0.read_volatile() & !(0b11) | 0b10);
},
_ => unsafe {
other_was_running = (options0.read_volatile() & 0b1100) == 0;
sw_cpu_stall
.write_volatile(sw_cpu_stall.read_volatile() & !(0b111111 << 26) | (0x21 << 26));
options0.write_volatile(options0.read_volatile() & !(0b1100) | 0b1000);
},
}

other_was_running
}

#[allow(clippy::identity_op)]
pub fn unpark_other_core(enable: bool) {
if enable {
const SW_CPU_STALL: u32 = 0x600080bc;
const OPTIONS0: u32 = 0x60008000;

let sw_cpu_stall = SW_CPU_STALL as *mut u32;
let options0 = OPTIONS0 as *mut u32;

let current = get_current_core();

match current {
0 => unsafe {
sw_cpu_stall
.write_volatile(sw_cpu_stall.read_volatile() & !(0b111111 << 20) | (0x0 << 20));
options0.write_volatile(options0.read_volatile() & !(0b11) | 0b00);
},
_ => unsafe {
sw_cpu_stall
.write_volatile(sw_cpu_stall.read_volatile() & !(0b111111 << 26) | (0x0 << 26));
options0.write_volatile(options0.read_volatile() & !(0b1100) | 0b0000);
},
}
}
}

#[inline]
fn get_current_core() -> u8 {
let mut x: u32;
unsafe { asm!("rsr.prid {0}", out(reg) x, options(nostack)) };

match ((x >> 13) & 1) != 0 {
false => 0,
true => 1,
}
}
13 changes: 11 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#![cfg_attr(not(all(test, feature = "emulation")), no_std)]
#![cfg_attr(target_arch = "xtensa", feature(asm_experimental_arch))]

#[cfg(not(feature = "emulation"))]
#[cfg_attr(feature = "esp32c2", path = "esp32c2.rs")]
Expand Down Expand Up @@ -48,11 +49,19 @@ pub mod ll;
#[inline(always)]
#[link_section = ".rwtext"]
fn maybe_with_critical_section<R>(f: impl FnOnce() -> R) -> R {
#[cfg(feature = "multicore-aware")]
let was_running = chip_specific::park_other_core();

#[cfg(feature = "critical-section")]
return critical_section::with(|_| f());
let res = critical_section::with(|_| f());

#[cfg(not(feature = "critical-section"))]
f()
let res = f();

#[cfg(feature = "multicore-aware")]
chip_specific::unpark_other_core(was_running);

res
}

#[cfg(feature = "emulation")]
Expand Down
Loading