From 4b52deaffaaacb9cd4b7e639889ae532c7e80b17 Mon Sep 17 00:00:00 2001 From: bjoernQ Date: Wed, 30 Aug 2023 15:12:22 +0200 Subject: [PATCH 1/2] Multicore aware (ESP32, ESP32-S3) --- .vscode/settings.json | 43 ++++++++++++++++++++-------- Cargo.toml | 4 ++- src/esp32.rs | 66 +++++++++++++++++++++++++++++++++++++++++++ src/esp32c2.rs | 6 ++++ src/esp32c3.rs | 6 ++++ src/esp32c6.rs | 6 ++++ src/esp32h2.rs | 6 ++++ src/esp32s2.rs | 6 ++++ src/esp32s3.rs | 66 +++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 13 +++++++-- 10 files changed, 208 insertions(+), 14 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index b157ed6..077c4ce 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -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, + } + \ No newline at end of file diff --git a/Cargo.toml b/Cargo.toml index ef7deb2..0f79cbb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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 = [] @@ -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 = [] diff --git a/src/esp32.rs b/src/esp32.rs index 208e672..786a12d 100644 --- a/src/esp32.rs +++ b/src/esp32.rs @@ -1,3 +1,5 @@ +use core::arch::asm; + use crate::maybe_with_critical_section; const ESP_ROM_SPIFLASH_READ: u32 = 0x40062ed8; @@ -274,3 +276,67 @@ pub(crate) fn esp_rom_spiflash_unlock() -> i32 { 0 }) } + +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 +} + +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, + } +} diff --git a/src/esp32c2.rs b/src/esp32c2.rs index c7c071e..2f65300 100644 --- a/src/esp32c2.rs +++ b/src/esp32c2.rs @@ -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) {} diff --git a/src/esp32c3.rs b/src/esp32c3.rs index 73a2d4c..2f6aab2 100644 --- a/src/esp32c3.rs +++ b/src/esp32c3.rs @@ -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) {} diff --git a/src/esp32c6.rs b/src/esp32c6.rs index 5255a63..a6d8ee8 100644 --- a/src/esp32c6.rs +++ b/src/esp32c6.rs @@ -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) {} diff --git a/src/esp32h2.rs b/src/esp32h2.rs index b7a1641..ff4b7ce 100644 --- a/src/esp32h2.rs +++ b/src/esp32h2.rs @@ -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) {} diff --git a/src/esp32s2.rs b/src/esp32s2.rs index 2717ae8..ab61062 100644 --- a/src/esp32s2.rs +++ b/src/esp32s2.rs @@ -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) {} diff --git a/src/esp32s3.rs b/src/esp32s3.rs index 37cfbb7..0c0ea52 100644 --- a/src/esp32s3.rs +++ b/src/esp32s3.rs @@ -1,3 +1,5 @@ +use core::arch::asm; + use crate::maybe_with_critical_section; const ESP_ROM_SPIFLASH_READ: u32 = 0x40000a20; @@ -44,3 +46,67 @@ 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 { + 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 +} + +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, + } +} diff --git a/src/lib.rs b/src/lib.rs index 4cf4eaf..00cc653 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -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")] @@ -48,11 +49,19 @@ pub mod ll; #[inline(always)] #[link_section = ".rwtext"] fn maybe_with_critical_section(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")] From adf18ac55d4a509214c7765fc17b826a302def3c Mon Sep 17 00:00:00 2001 From: bjoernQ Date: Wed, 30 Aug 2023 15:20:41 +0200 Subject: [PATCH 2/2] Mute Clippy --- src/esp32.rs | 2 ++ src/esp32s3.rs | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/esp32.rs b/src/esp32.rs index 786a12d..d0b1b4a 100644 --- a/src/esp32.rs +++ b/src/esp32.rs @@ -277,6 +277,7 @@ pub(crate) fn esp_rom_spiflash_unlock() -> i32 { }) } +#[allow(clippy::identity_op)] pub fn park_other_core() -> bool { const SW_CPU_STALL: u32 = 0x3ff480ac; const OPTIONS0: u32 = 0x3ff48000; @@ -305,6 +306,7 @@ pub fn park_other_core() -> bool { other_was_running } +#[allow(clippy::identity_op)] pub fn unpark_other_core(enable: bool) { if enable { const SW_CPU_STALL: u32 = 0x3ff480ac; diff --git a/src/esp32s3.rs b/src/esp32s3.rs index 0c0ea52..96e82bb 100644 --- a/src/esp32s3.rs +++ b/src/esp32s3.rs @@ -47,6 +47,7 @@ pub(crate) fn esp_rom_spiflash_write(dest_addr: u32, data: *const u32, len: u32) }) } +#[allow(clippy::identity_op)] pub fn park_other_core() -> bool { const SW_CPU_STALL: u32 = 0x600080bc; const OPTIONS0: u32 = 0x60008000; @@ -75,6 +76,7 @@ pub fn park_other_core() -> bool { other_was_running } +#[allow(clippy::identity_op)] pub fn unpark_other_core(enable: bool) { if enable { const SW_CPU_STALL: u32 = 0x600080bc;