diff --git a/esp-hal/CHANGELOG.md b/esp-hal/CHANGELOG.md index e9674a94694..1bbf978e845 100644 --- a/esp-hal/CHANGELOG.md +++ b/esp-hal/CHANGELOG.md @@ -8,8 +8,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] ### Added -- Add burst transfer support to DMA buffers (#2236) +- A new config option `PLACE_SWITCH_TABLES_IN_RAM` to improve performance (especially for interrupts) at the cost of slightly more RAM usage (#2331) +- A new config option `PLACE_ANON_IN_RAM` to improve performance (especially for interrupts) at the cost of RAM usage (#2331) +- Add burst transfer support to DMA buffers (#2236) - `AnyPin` now implements `From>`. (#2326) ### Changed diff --git a/esp-hal/build.rs b/esp-hal/build.rs index 65644c7272a..c507a97bd13 100644 --- a/esp-hal/build.rs +++ b/esp-hal/build.rs @@ -69,19 +69,53 @@ fn main() -> Result<(), Box> { // Define all necessary configuration symbols for the configured device: config.define_symbols(); - #[allow(unused_mut)] - let mut config_symbols = config.all().collect::>(); - #[cfg(feature = "flip-link")] - config_symbols.push("flip-link"); - // Place all linker scripts in `OUT_DIR`, and instruct Cargo how to find these // files: let out = PathBuf::from(env::var_os("OUT_DIR").unwrap()); println!("cargo:rustc-link-search={}", out.display()); + // emit config + let cfg = generate_config( + "esp_hal", + &[ + ( + "place-spi-driver-in-ram", + Value::Bool(false), + "Places the SPI driver in RAM for better performance", + ), + ( + "spi-address-workaround", + Value::Bool(true), + "(ESP32 only) Enables a workaround for the issue where SPI in half-duplex mode incorrectly transmits the address on a single line if the data buffer is empty.", + ), + ( + "place-switch-tables-in-ram", + Value::Bool(true), + "Places switch-tables, some lookup tables and constants related to interrupt handling into RAM - resulting in better performance but slightly more RAM consumption.", + ), + ( + "place-anon-in-ram", + Value::Bool(false), + "Places anonymous symbols into RAM - resulting in better performance at the cost of significant more RAM consumption. Best to be combined with `place-switch-tables-in-ram`.", + ), + ], + true, + ); + // RISC-V and Xtensa devices each require some special handling and processing // of linker scripts: + #[allow(unused_mut)] + let mut config_symbols = config.all().collect::>(); + #[cfg(feature = "flip-link")] + config_symbols.push("flip-link"); + + for (key, value) in &cfg { + if let Value::Bool(true) = value { + config_symbols.push(key); + } + } + if cfg!(feature = "esp32") || cfg!(feature = "esp32s2") || cfg!(feature = "esp32s3") { // Xtensa devices: @@ -125,24 +159,6 @@ fn main() -> Result<(), Box> { copy_dir_all(&config_symbols, "ld/sections", &out)?; copy_dir_all(&config_symbols, format!("ld/{device_name}"), &out)?; - // emit config - generate_config( - "esp_hal", - &[ - ( - "place-spi-driver-in-ram", - Value::Bool(false), - "Places the SPI driver in RAM for better performance", - ), - ( - "spi-address-workaround", - Value::Bool(true), - "(ESP32 only) Enables a workaround for the issue where SPI in half-duplex mode incorrectly transmits the address on a single line if the data buffer is empty.", - ), - ], - true, - ); - Ok(()) } diff --git a/esp-hal/ld/esp32/esp32.x b/esp-hal/ld/esp32/esp32.x index 5d9ffec825a..a61c7579408 100644 --- a/esp-hal/ld/esp32/esp32.x +++ b/esp-hal/ld/esp32/esp32.x @@ -19,10 +19,10 @@ INCLUDE "fixups/rtc_fast_rwdata_dummy.x" /* END ESP32 fixups */ /* Shared sections - ordering matters */ -INCLUDE "text.x" -INCLUDE "rodata.x" INCLUDE "rwtext.x" +INCLUDE "text.x" INCLUDE "rwdata.x" +INCLUDE "rodata.x" INCLUDE "rtc_fast.x" INCLUDE "rtc_slow.x" INCLUDE "stack.x" diff --git a/esp-hal/ld/esp32c2/esp32c2.x b/esp-hal/ld/esp32c2/esp32c2.x index 8324eb4c31e..a98f753ef1f 100644 --- a/esp-hal/ld/esp32c2/esp32c2.x +++ b/esp-hal/ld/esp32c2/esp32c2.x @@ -80,10 +80,10 @@ PROVIDE(__global_pointer$ = _data_start + 0x800); /* end of esp32c2 fixups */ /* Shared sections - ordering matters */ -INCLUDE "text.x" -INCLUDE "rodata.x" INCLUDE "rwtext.x" +INCLUDE "text.x" INCLUDE "rwdata.x" +INCLUDE "rodata.x" INCLUDE "stack.x" INCLUDE "dram2.x" /* End of Shared sections */ diff --git a/esp-hal/ld/esp32c3/esp32c3.x b/esp-hal/ld/esp32c3/esp32c3.x index 4d83f420e98..51144d78407 100644 --- a/esp-hal/ld/esp32c3/esp32c3.x +++ b/esp-hal/ld/esp32c3/esp32c3.x @@ -80,10 +80,10 @@ PROVIDE(__global_pointer$ = _data_start + 0x800); /* end of esp32c3 fixups */ /* Shared sections - ordering matters */ -INCLUDE "text.x" -INCLUDE "rodata.x" INCLUDE "rwtext.x" +INCLUDE "text.x" INCLUDE "rwdata.x" +INCLUDE "rodata.x" INCLUDE "rtc_fast.x" INCLUDE "stack.x" INCLUDE "dram2.x" diff --git a/esp-hal/ld/esp32c6/esp32c6.x b/esp-hal/ld/esp32c6/esp32c6.x index 4a3cc337aa3..47f8de2e0ea 100644 --- a/esp-hal/ld/esp32c6/esp32c6.x +++ b/esp-hal/ld/esp32c6/esp32c6.x @@ -72,10 +72,10 @@ INSERT BEFORE .rodata; /* end of esp32c6 fixups */ /* Shared sections - ordering matters */ -INCLUDE "text.x" INCLUDE "rwtext.x" -INCLUDE "rodata.x" +INCLUDE "text.x" INCLUDE "rwdata.x" +INCLUDE "rodata.x" INCLUDE "rtc_fast.x" INCLUDE "stack.x" INCLUDE "dram2.x" diff --git a/esp-hal/ld/esp32h2/esp32h2.x b/esp-hal/ld/esp32h2/esp32h2.x index 635338e1c24..c262159b2f1 100644 --- a/esp-hal/ld/esp32h2/esp32h2.x +++ b/esp-hal/ld/esp32h2/esp32h2.x @@ -65,10 +65,10 @@ SECTIONS { INSERT BEFORE .rodata; /* Shared sections - ordering matters */ -INCLUDE "text.x" INCLUDE "rwtext.x" -INCLUDE "rodata.x" +INCLUDE "text.x" INCLUDE "rwdata.x" +INCLUDE "rodata.x" INCLUDE "rtc_fast.x" INCLUDE "stack.x" INCLUDE "dram2.x" diff --git a/esp-hal/ld/esp32s2/esp32s2.x b/esp-hal/ld/esp32s2/esp32s2.x index 29602c0695f..d7be0cbcd31 100644 --- a/esp-hal/ld/esp32s2/esp32s2.x +++ b/esp-hal/ld/esp32s2/esp32s2.x @@ -27,10 +27,10 @@ INCLUDE "fixups/rtc_fast_rwdata_dummy.x" /* End of fixups for esp32s2 */ /* Shared sections - ordering matters */ -INCLUDE "text.x" -INCLUDE "rodata.x" INCLUDE "rwtext.x" +INCLUDE "text.x" INCLUDE "rwdata.x" +INCLUDE "rodata.x" INCLUDE "rtc_fast.x" INCLUDE "rtc_slow.x" INCLUDE "stack.x" diff --git a/esp-hal/ld/esp32s3/esp32s3.x b/esp-hal/ld/esp32s3/esp32s3.x index 6f333cc8042..a9f130ee005 100644 --- a/esp-hal/ld/esp32s3/esp32s3.x +++ b/esp-hal/ld/esp32s3/esp32s3.x @@ -41,10 +41,10 @@ INCLUDE "fixups/rodata_dummy.x" /* End of ESP32S3 fixups */ /* Shared sections - ordering matters */ -INCLUDE "text.x" -INCLUDE "rodata.x" INCLUDE "rwtext.x" +INCLUDE "text.x" INCLUDE "rwdata.x" +INCLUDE "rodata.x" INCLUDE "rtc_fast.x" INCLUDE "rtc_slow.x" INCLUDE "stack.x" diff --git a/esp-hal/ld/sections/rwdata.x b/esp-hal/ld/sections/rwdata.x index 590a2eb3ecf..b00f877458d 100644 --- a/esp-hal/ld/sections/rwdata.x +++ b/esp-hal/ld/sections/rwdata.x @@ -5,6 +5,17 @@ SECTIONS { { _data_start = ABSOLUTE(.); . = ALIGN (4); + + #IF ESP_HAL_PLACE_SWITCH_TABLES_IN_RAM + *(.rodata.*_esp_hal_internal_handler*) + *(.rodata..Lswitch.table.*) + *(.rodata.cst*) + #ENDIF + + #IF ESP_HAL_PLACE_ANON_IN_RAM + *(.rodata..Lanon .rodata..Lanon.*) + #ENDIF + *(.sdata .sdata.* .sdata2 .sdata2.*); *(.data .data.*); *(.data1) diff --git a/esp-hal/ld/sections/rwtext.x b/esp-hal/ld/sections/rwtext.x index 64535416ee0..aca9385b5b0 100644 --- a/esp-hal/ld/sections/rwtext.x +++ b/esp-hal/ld/sections/rwtext.x @@ -1,5 +1,3 @@ - - SECTIONS { .rwtext : ALIGN(4) { diff --git a/esp-hal/src/gpio/mod.rs b/esp-hal/src/gpio/mod.rs index 0580a8e340c..843c2608e41 100644 --- a/esp-hal/src/gpio/mod.rs +++ b/esp-hal/src/gpio/mod.rs @@ -2459,6 +2459,7 @@ mod asynch { use super::*; + #[ram] pub(super) static PIN_WAKERS: [AtomicWaker; NUM_PINS] = [const { AtomicWaker::new() }; NUM_PINS]; diff --git a/esp-hal/src/interrupt/riscv.rs b/esp-hal/src/interrupt/riscv.rs index f21a44bc07a..151fa622471 100644 --- a/esp-hal/src/interrupt/riscv.rs +++ b/esp-hal/src/interrupt/riscv.rs @@ -168,7 +168,8 @@ impl Priority { } /// The interrupts reserved by the HAL -pub const RESERVED_INTERRUPTS: &[usize] = INTERRUPT_TO_PRIORITY; +#[cfg_attr(place_switch_tables_in_ram, link_section = ".rwtext")] +pub static RESERVED_INTERRUPTS: &[usize] = INTERRUPT_TO_PRIORITY; /// # Safety /// @@ -549,14 +550,18 @@ mod classic { use super::{CpuInterrupt, InterruptKind, Priority}; use crate::Cpu; - pub(super) const DISABLED_CPU_INTERRUPT: u32 = 0; + #[cfg_attr(place_switch_tables_in_ram, link_section = ".rwtext")] + pub(super) static DISABLED_CPU_INTERRUPT: u32 = 0; - pub(super) const EXTERNAL_INTERRUPT_OFFSET: u32 = 0; + #[cfg_attr(place_switch_tables_in_ram, link_section = ".rwtext")] + pub(super) static EXTERNAL_INTERRUPT_OFFSET: u32 = 0; - pub(super) const PRIORITY_TO_INTERRUPT: &[usize] = + #[cfg_attr(place_switch_tables_in_ram, link_section = ".rwtext")] + pub(super) static PRIORITY_TO_INTERRUPT: &[usize] = &[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]; - pub(super) const INTERRUPT_TO_PRIORITY: &[usize] = + #[cfg_attr(place_switch_tables_in_ram, link_section = ".rwtext")] + pub(super) static INTERRUPT_TO_PRIORITY: &[usize] = &[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]; /// Enable a CPU interrupt @@ -667,17 +672,21 @@ mod plic { use super::{CpuInterrupt, InterruptKind, Priority}; use crate::Cpu; - pub(super) const DISABLED_CPU_INTERRUPT: u32 = 31; + #[cfg_attr(place_switch_tables_in_ram, link_section = ".rwtext")] + pub(super) static DISABLED_CPU_INTERRUPT: u32 = 31; - pub(super) const EXTERNAL_INTERRUPT_OFFSET: u32 = 0; + #[cfg_attr(place_switch_tables_in_ram, link_section = ".rwtext")] + pub(super) static EXTERNAL_INTERRUPT_OFFSET: u32 = 0; // don't use interrupts reserved for CLIC (0,3,4,7) // for some reason also CPU interrupt 8 doesn't work by default since it's // disabled after reset - so don't use that, too - pub(super) const PRIORITY_TO_INTERRUPT: &[usize] = + #[cfg_attr(place_switch_tables_in_ram, link_section = ".rwtext")] + pub(super) static PRIORITY_TO_INTERRUPT: &[usize] = &[1, 2, 5, 6, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]; - pub(super) const INTERRUPT_TO_PRIORITY: &[usize] = &[ + #[cfg_attr(place_switch_tables_in_ram, link_section = ".rwtext")] + pub(super) static INTERRUPT_TO_PRIORITY: &[usize] = &[ 1, 2, 0, 0, 3, 4, 0, 0, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, ]; diff --git a/esp-hal/src/interrupt/xtensa.rs b/esp-hal/src/interrupt/xtensa.rs index 844388baed2..5ed4138c440 100644 --- a/esp-hal/src/interrupt/xtensa.rs +++ b/esp-hal/src/interrupt/xtensa.rs @@ -95,7 +95,8 @@ pub enum CpuInterrupt { } /// The interrupts reserved by the HAL -pub const RESERVED_INTERRUPTS: &[usize] = &[ +#[cfg_attr(place_switch_tables_in_ram, link_section = ".rwtext")] +pub static RESERVED_INTERRUPTS: &[usize] = &[ CpuInterrupt::Interrupt1LevelPriority1 as _, CpuInterrupt::Interrupt19LevelPriority2 as _, CpuInterrupt::Interrupt23LevelPriority3 as _, @@ -447,7 +448,8 @@ mod vectored { } // TODO use CpuInterrupt::LevelX.mask() // TODO make it const - const CPU_INTERRUPT_LEVELS: [u32; 8] = [ + #[cfg_attr(place_switch_tables_in_ram, link_section = ".rwtext")] + static CPU_INTERRUPT_LEVELS: [u32; 8] = [ 0b_0000_0000_0000_0000_0000_0000_0000_0000, // Dummy level 0 0b_0000_0000_0000_0110_0011_0111_1111_1111, // Level_1 0b_0000_0000_0011_1000_0000_0000_0000_0000, // Level 2 @@ -457,8 +459,10 @@ mod vectored { 0b_0000_0000_0000_0000_0000_0000_0000_0000, // Level 6 0b_0000_0000_0000_0000_0100_0000_0000_0000, // Level 7 ]; - const CPU_INTERRUPT_INTERNAL: u32 = 0b_0010_0000_0000_0001_1000_1000_1100_0000; - const CPU_INTERRUPT_EDGE: u32 = 0b_0111_0000_0100_0000_0000_1100_1000_0000; + #[cfg_attr(place_switch_tables_in_ram, link_section = ".rwtext")] + static CPU_INTERRUPT_INTERNAL: u32 = 0b_0010_0000_0000_0001_1000_1000_1100_0000; + #[cfg_attr(place_switch_tables_in_ram, link_section = ".rwtext")] + static CPU_INTERRUPT_EDGE: u32 = 0b_0111_0000_0100_0000_0000_1100_1000_0000; #[inline] fn cpu_interrupt_nr_to_cpu_interrupt_handler( @@ -558,7 +562,8 @@ mod vectored { #[cfg(esp32)] mod chip_specific { use super::*; - pub const INTERRUPT_EDGE: InterruptStatus = InterruptStatus::from( + #[cfg_attr(place_switch_tables_in_ram, link_section = ".rwtext")] + pub static INTERRUPT_EDGE: InterruptStatus = InterruptStatus::from( 0b0000_0000_0000_0000_0000_0000_0000_0000, 0b1111_1100_0000_0000_0000_0000_0000_0000, 0b0000_0000_0000_0000_0000_0000_0000_0011, @@ -583,7 +588,8 @@ mod vectored { #[cfg(esp32s2)] mod chip_specific { use super::*; - pub const INTERRUPT_EDGE: InterruptStatus = InterruptStatus::from( + #[cfg_attr(place_switch_tables_in_ram, link_section = ".rwtext")] + pub static INTERRUPT_EDGE: InterruptStatus = InterruptStatus::from( 0b0000_0000_0000_0000_0000_0000_0000_0000, 0b1100_0000_0000_0000_0000_0000_0000_0000, 0b0000_0000_0000_0000_0000_0011_1011_1111, @@ -611,7 +617,8 @@ mod vectored { #[cfg(esp32s3)] mod chip_specific { use super::*; - pub const INTERRUPT_EDGE: InterruptStatus = InterruptStatus::empty(); + #[cfg_attr(place_switch_tables_in_ram, link_section = ".rwtext")] + pub static INTERRUPT_EDGE: InterruptStatus = InterruptStatus::empty(); #[inline] pub fn interrupt_is_edge(_interrupt: Interrupt) -> bool { false