From f247b4099c116979bf2bad8cb405da33858a7f52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Quentin?= Date: Thu, 23 Jan 2025 16:21:46 +0100 Subject: [PATCH] Remove `flip-link` feature, replace by flip-link option (#3001) * Fix renamed config options * Make `flip-link` feature into a config-option * Remove `psram-quad`/`psram-octal` - replaced by `psram` * Changelogs * Fix * Add `esp_config::Validator::Enumeration` * Fix HIL-tests * HIL: use octal psram for the S3 * Fix xtask * xtask * examples * Make `spi-address-workaround` only available on ESP32 * Always allow `cfg(spi_address_workaround)` * Make config-options valid for all targets --- .github/workflows/hil.yml | 6 + esp-config/src/generate.rs | 167 ++++++++++++++++-- esp-hal/CHANGELOG.md | 6 + esp-hal/Cargo.toml | 12 +- esp-hal/MIGRATING-0.23.md | 35 ++++ esp-hal/build.rs | 95 +++++----- esp-hal/ld/esp32c2/esp32c2.x | 1 + esp-hal/ld/esp32c3/esp32c3.x | 1 + esp-hal/ld/esp32c6/esp32c6.x | 4 +- esp-hal/ld/esp32h2/esp32h2.x | 2 + esp-hal/ld/sections/rwdata.x | 4 +- esp-hal/ld/sections/stack.x | 2 +- esp-hal/src/lib.rs | 6 +- esp-hal/src/soc/esp32/mod.rs | 2 +- esp-hal/src/soc/esp32s2/mod.rs | 2 +- esp-hal/src/soc/esp32s3/mod.rs | 2 +- esp-hal/src/soc/esp32s3/psram.rs | 9 +- esp-hal/src/soc/mod.rs | 8 +- esp-hal/src/soc/psram_common.rs | 2 +- esp-riscv-rt/CHANGELOG.md | 2 + esp-riscv-rt/Cargo.toml | 4 - esp-riscv-rt/src/lib.rs | 8 +- examples/src/bin/dma_extmem2mem.rs | 4 +- examples/src/bin/spi_loopback_dma_psram.rs | 5 +- hil-test/Cargo.toml | 3 +- hil-test/tests/spi_half_duplex_write_psram.rs | 2 +- qa-test/src/bin/{psram_quad.rs => psram.rs} | 5 +- qa-test/src/bin/psram_octal.rs | 58 ------ xtask/src/lib.rs | 6 +- xtask/src/main.rs | 8 +- 30 files changed, 290 insertions(+), 181 deletions(-) rename qa-test/src/bin/{psram_quad.rs => psram.rs} (88%) delete mode 100644 qa-test/src/bin/psram_octal.rs diff --git a/.github/workflows/hil.yml b/.github/workflows/hil.yml index 2541c40da72..f504f48067e 100644 --- a/.github/workflows/hil.yml +++ b/.github/workflows/hil.yml @@ -118,7 +118,13 @@ jobs: ldproxy: false version: 1.84.0.0 + # remove once we have a proper solution for target specific configs + - name: Build tests ESP32S3 + if: ${{ matrix.target.soc == 'esp32s3'}} + run: ESP_HAL_CONFIG_PSRAM_MODE="octal" cargo xtask build-tests ${{ matrix.target.soc }} + - name: Build tests + if: ${{ matrix.target.soc != 'esp32s3'}} run: cargo xtask build-tests ${{ matrix.target.soc }} - uses: actions/upload-artifact@v4 diff --git a/esp-config/src/generate.rs b/esp-config/src/generate.rs index 3a9f6711522..3088f08616a 100644 --- a/esp-config/src/generate.rs +++ b/esp-config/src/generate.rs @@ -3,13 +3,14 @@ use std::{ env, fmt::{self, Write as _}, fs, + io::Write, ops::Range, path::PathBuf, }; const DOC_TABLE_HEADER: &str = r#" -| Name | Description | Default value | -|------|-------------|---------------| +| Name | Description | Default value | Allowed value | +|------|-------------|---------------|---------------| "#; const SELECTED_TABLE_HEADER: &str = r#" @@ -155,6 +156,8 @@ pub enum Validator { PositiveInteger, /// Ensure that an integer value falls within the specified range. IntegerInRange(Range), + /// String-Enumeration. Only allows one of the given Strings. + Enumeration(Vec), /// A custom validation function to run against any supported value type. Custom(Box Result<(), Error>>), } @@ -166,11 +169,59 @@ impl Validator { Validator::NonNegativeInteger => non_negative_integer(value)?, Validator::PositiveInteger => positive_integer(value)?, Validator::IntegerInRange(range) => integer_in_range(range, value)?, + Validator::Enumeration(values) => enumeration(values, value)?, Validator::Custom(validator_fn) => validator_fn(value)?, } Ok(()) } + + fn description(&self) -> Option { + match self { + Validator::NegativeInteger => Some(String::from("Negative integer")), + Validator::NonNegativeInteger => Some(String::from("Positive integer or 0")), + Validator::PositiveInteger => Some(String::from("Positive integer")), + Validator::IntegerInRange(range) => { + Some(format!("Integer in range {}..{}", range.start, range.end)) + } + Validator::Enumeration(values) => Some(format!("Any of {:?}", values)), + Validator::Custom(_) => None, + } + } + + fn emit_cargo_extras(&self, stdout: &mut W, config_key: &str) { + match self { + Validator::Enumeration(values) => { + let config_key = snake_case(config_key); + for value in values { + writeln!( + stdout, + "cargo:rustc-check-cfg=cfg({config_key}_{})", + snake_case(value) + ) + .ok(); + } + } + _ => (), + } + } +} + +fn enumeration(values: &Vec, value: &Value) -> Result<(), Error> { + if let Value::String(value) = value { + if !values.contains(value) { + return Err(Error::validation(format!( + "Expected one of {:?}, found '{}'", + values, value + ))); + } + + Ok(()) + } else { + return Err(Error::parse( + "Validator::Enumeration can only be used with string values", + )); + } } fn negative_integer(value: &Value) -> Result<(), Error> { @@ -252,13 +303,22 @@ pub fn generate_config( crate_name: &str, config: &[(&str, &str, Value, Option)], emit_md_tables: bool, +) -> HashMap { + generate_config_internal(&mut std::io::stdout(), crate_name, config, emit_md_tables) +} + +pub fn generate_config_internal( + stdout: &mut W, + crate_name: &str, + config: &[(&str, &str, Value, Option)], + emit_md_tables: bool, ) -> HashMap { // Only rebuild if `build.rs` changed. Otherwise, Cargo will rebuild if any // other file changed. - println!("cargo:rerun-if-changed=build.rs"); + writeln!(stdout, "cargo:rerun-if-changed=build.rs").ok(); #[cfg(not(test))] - env_change_work_around(); + env_change_work_around(stdout); let mut doc_table = String::from(DOC_TABLE_HEADER); let mut selected_config = String::from(SELECTED_TABLE_HEADER); @@ -281,7 +341,7 @@ pub fn generate_config( }) .collect::>(); - let mut configs = create_config(&prefix, config, &mut doc_table); + let mut configs = create_config(stdout, &prefix, config, &mut doc_table); capture_from_env(&prefix, &mut configs); for (name, value) in configs.iter() { @@ -290,7 +350,18 @@ pub fn generate_config( } } - emit_configuration(&prefix, &configs, &mut selected_config); + let validators: HashMap = config + .iter() + .filter_map(|(name, _, _, validator)| { + if validator.is_some() { + Some((snake_case(name), validator.as_ref().unwrap())) + } else { + None + } + }) + .collect(); + + emit_configuration(stdout, &prefix, &configs, &validators, &mut selected_config); if emit_md_tables { let file_name = snake_case(crate_name); @@ -304,7 +375,7 @@ pub fn generate_config( // This can be removed when https://github.com/rust-lang/cargo/pull/14058 is merged. // Unlikely to work on projects in workspaces #[cfg(not(test))] -fn env_change_work_around() { +fn env_change_work_around(stdout: &mut W) { let mut out_dir = PathBuf::from(env::var_os("OUT_DIR").unwrap()); // We clean out_dir by removing all trailing directories, until it ends with @@ -319,37 +390,53 @@ fn env_change_work_around() { let dotcargo = out_dir.join(".cargo/"); if dotcargo.exists() { if dotcargo.join("config.toml").exists() { - println!( + writeln!( + stdout, "cargo:rerun-if-changed={}", dotcargo.join("config.toml").display() - ); + ) + .ok(); } if dotcargo.join("config").exists() { - println!( + writeln!( + stdout, "cargo:rerun-if-changed={}", dotcargo.join("config").display() - ); + ) + .ok(); } } } -fn create_config( +fn create_config( + stdout: &mut W, prefix: &str, config: &[(&str, &str, Value, Option)], doc_table: &mut String, ) -> HashMap { let mut configs = HashMap::new(); - for (name, description, default, _validator) in config { + for (name, description, default, validator) in config { let name = format!("{prefix}{}", screaming_snake_case(name)); + let allowed_values = if let Some(validator) = validator { + validator.description() + } else { + None + } + .unwrap_or(String::from("-")); + configs.insert(name.clone(), default.clone()); // Write documentation table line: let default = default.to_string(); - writeln!(doc_table, "|**{name}**|{description}|{default}|").unwrap(); + writeln!( + doc_table, + "|**{name}**|{description}|{default}|{allowed_values}" + ) + .unwrap(); // Rebuild if config environment variable changed: - println!("cargo:rerun-if-env-changed={name}"); + writeln!(stdout, "cargo:rerun-if-env-changed={name}").ok(); } configs @@ -382,25 +469,38 @@ fn capture_from_env(prefix: &str, configs: &mut HashMap) { } } -fn emit_configuration( +fn emit_configuration( + stdout: &mut W, prefix: &str, configs: &HashMap, + validators: &HashMap, selected_config: &mut String, ) { for (name, value) in configs.iter() { let cfg_name = snake_case(name.trim_start_matches(prefix)); - println!("cargo:rustc-check-cfg=cfg({cfg_name})"); + writeln!(stdout, "cargo:rustc-check-cfg=cfg({cfg_name})").ok(); if let Value::Bool(true) = value { - println!("cargo:rustc-cfg={cfg_name}"); + writeln!(stdout, "cargo:rustc-cfg={cfg_name}").ok(); + } + + if let Value::String(value) = value { + if let Some(Validator::Enumeration(_)) = validators.get(&cfg_name) { + let value = format!("{}_{}", cfg_name, snake_case(value)); + writeln!(stdout, "cargo:rustc-cfg={value}").ok(); + } } let value = value.to_string(); // Values that haven't been seen will be output here with the default value: - println!("cargo:rustc-env={}={}", name, value); + writeln!(stdout, "cargo:rustc-env={}={}", name, value).ok(); writeln!(selected_config, "|**{name}**|{value}|").unwrap(); } + + for (name, validator) in validators { + validator.emit_cargo_extras(stdout, &name); + } } fn write_config_tables(prefix: &str, doc_table: String, selected_config: String) { @@ -696,4 +796,33 @@ mod test { }, ); } + + #[test] + fn enumeration_validator() { + let mut stdout = Vec::new(); + temp_env::with_vars([("ESP_TEST_CONFIG_SOME_KEY", Some("variant-0"))], || { + generate_config_internal( + &mut stdout, + "esp-test", + &[( + "some-key", + "NA", + Value::String("variant-0".to_string()), + Some(Validator::Enumeration(vec![ + "variant-0".to_string(), + "variant-1".to_string(), + ])), + )], + false, + ); + }); + + let cargo_lines: Vec<&str> = std::str::from_utf8(&stdout).unwrap().lines().collect(); + println!("{:#?}", cargo_lines); + assert!(cargo_lines.contains(&"cargo:rustc-check-cfg=cfg(some_key)")); + assert!(cargo_lines.contains(&"cargo:rustc-env=ESP_TEST_CONFIG_SOME_KEY=variant-0")); + assert!(cargo_lines.contains(&"cargo:rustc-check-cfg=cfg(some_key_variant_0)")); + assert!(cargo_lines.contains(&"cargo:rustc-check-cfg=cfg(some_key_variant_1)")); + assert!(cargo_lines.contains(&"cargo:rustc-cfg=some_key_variant_0")); + } } diff --git a/esp-hal/CHANGELOG.md b/esp-hal/CHANGELOG.md index 1a7a510d124..47ff2831a7c 100644 --- a/esp-hal/CHANGELOG.md +++ b/esp-hal/CHANGELOG.md @@ -28,6 +28,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `Async` drivers are no longer `Send` (#2980) - GPIO drivers now take configuration structs, and their constructors are fallible (#2990) +- `flip-link` feature is now a config option +- `flip-link` feature is now a config option (`ESP_HAL_CONFIG_FLIP_LINK`) + +- `flip-link` feature is now a config option (`ESP_HAL_CONFIG_FLIP_LINK`) (#3001) + +- Removed features `psram-quad` and `psram-octal` - replaced by `psram` and the `ESP_HAL_CONFIG_PSRAM_MODE` (`quad`/`octal`) (#3001) ### Fixed diff --git a/esp-hal/Cargo.toml b/esp-hal/Cargo.toml index 43a354f7486..bc501a46e74 100644 --- a/esp-hal/Cargo.toml +++ b/esp-hal/Cargo.toml @@ -120,11 +120,6 @@ esp32s2 = ["dep:esp32s2", "portable-atomic/critical-section", "procmacros/has-ul # Target the ESP32-S3. esp32s3 = ["dep:esp32s3", "procmacros/has-ulp-core", "procmacros/rtc-slow", "usb-otg", "xtensa-lx-rt/esp32s3"] -#! ### RISC-V Exclusive Feature Flags -## Move the stack to start of RAM to get zero-cost stack overflow protection -## (ESP32-C6 and ESPS32-H2 only!). -flip-link = ["esp-riscv-rt/fix-sp"] - #! ### Trait Implementation Feature Flags ## Implement `defmt::Format` on certain types. defmt = [ @@ -145,11 +140,8 @@ defmt = [ ] #! ### PSRAM Feature Flags -## Use externally connected Quad PSRAM -quad-psram = [] - -## Use externally connected Octal RAM -octal-psram = [] +## Use externally connected PSRAM (`quad` by default, can be configured to `octal` via ESP_HAL_CONFIG_PSRAM_MODE) +psram = [] # This feature is intended for testing; you probably don't want to enable it: ci = ["defmt", "bluetooth"] diff --git a/esp-hal/MIGRATING-0.23.md b/esp-hal/MIGRATING-0.23.md index 56a857c98e1..86cb55ddb63 100644 --- a/esp-hal/MIGRATING-0.23.md +++ b/esp-hal/MIGRATING-0.23.md @@ -128,6 +128,41 @@ Use `DataMode::SingleTwoDataLines` to get the previous behavior. `Spi` now offers both, `with_mosi` and `with_sio0`. Consider using `with_sio` for half-duplex SPI except for [DataMode::SingleTwoDataLines] or for a mixed-bus. +## Removed `flip-link` Feature + +The `flip-link` feature is removed and replaced by the `ESP_HAL_CONFIG_FLIP_LINK` option. + +Cargo.toml +```diff +- esp-hal = { version = "0.23.0", features = ["flip-link"]} ++ esp-hal = "0.23.0" +``` + +config/config.toml +```diff +[env] ++ ESP_HAL_CONFIG_FLIP_LINK = "true" +``` + +## Removed `psram-quad`/`prsram-octal` Feature + +The features `psram-quad`/`prsram-octal` are replaced by a single `psram` feature and an additional config option (`ESP_HAL_CONFIG_PSRAM_MODE`). + +`ESP_HAL_CONFIG_PSRAM_MODE` defaults to `quad` and (for ESP32-S3) also allows `octal`. + +Cargo.toml +```diff +- esp-hal = { version = "0.23.0", features = ["psram-octal"]} ++ esp-hal = { version = "0.23.0", features = ["psram"]} +``` + +config/config.toml +```diff +[env] ++ ESP_HAL_CONFIG_PSRAM_MODE = "octal" +``` + + ## UART halves have their configuration split too `Uart::Config` structure now contains separate `RxConfig` and `TxConfig`: diff --git a/esp-hal/build.rs b/esp-hal/build.rs index 8e283f1c474..7e86215a69f 100644 --- a/esp-hal/build.rs +++ b/esp-hal/build.rs @@ -8,7 +8,7 @@ use std::{ }; use esp_build::assert_unique_used_features; -use esp_config::{generate_config, Value}; +use esp_config::{generate_config, Validator, Value}; use esp_metadata::{Chip, Config}; fn main() -> Result<(), Box> { @@ -25,12 +25,6 @@ fn main() -> Result<(), Box> { "esp32", "esp32c2", "esp32c3", "esp32c6", "esp32h2", "esp32s2", "esp32s3" ); - #[cfg(all( - feature = "flip-link", - not(any(feature = "esp32c6", feature = "esp32h2")) - ))] - esp_build::error!("flip-link is only available on ESP32-C6/ESP32-H2"); - // NOTE: update when adding new device support! // Determine the name of the configured device: let device_name = if cfg!(feature = "esp32") { @@ -55,15 +49,6 @@ fn main() -> Result<(), Box> { let chip = Chip::from_str(device_name)?; let config = Config::for_chip(&chip); - // Check PSRAM features are only given if the target supports PSRAM: - if !config.contains(&String::from("psram")) && cfg!(feature = "quad-psram") { - panic!("The target does not support PSRAM"); - } - - if !config.contains(&String::from("octal_psram")) && cfg!(feature = "octal-psram") { - panic!("The target does not support Octal PSRAM"); - } - // Define all necessary configuration symbols for the configured device: config.define_symbols(); @@ -73,44 +58,56 @@ fn main() -> Result<(), Box> { println!("cargo:rustc-link-search={}", out.display()); // emit config - let cfg = generate_config( - "esp_hal", - &[ - ( - "place-spi-driver-in-ram", - "Places the SPI driver in RAM for better performance", - Value::Bool(false), - None - ), - ( - "spi-address-workaround", - "(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.", - Value::Bool(true), - None - ), - ( - "place-switch-tables-in-ram", - "Places switch-tables, some lookup tables and constants related to interrupt handling into RAM - resulting in better performance but slightly more RAM consumption.", - Value::Bool(true), - None - ), - ( - "place-anon-in-ram", - "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`.", - Value::Bool(false), - None - ), - ], - true, - ); + let cfg = generate_config("esp_hal", &[ + ( + "place-spi-driver-in-ram", + "Places the SPI driver in RAM for better performance", + Value::Bool(false), + None + ), + ( + "place-switch-tables-in-ram", + "Places switch-tables, some lookup tables and constants related to interrupt handling into RAM - resulting in better performance but slightly more RAM consumption.", + Value::Bool(true), + None + ), + ( + "place-anon-in-ram", + "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`.", + Value::Bool(false), + None + ), + // ideally we should only offer this for ESP32 but the config system doesn't + // support per target configs, yet + ( + "spi-address-workaround", + "(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.", + Value::Bool(true), + None + ), + // ideally we should only offer this for ESP32-C6/ESP32-H2 but the config system doesn't support per target configs, yet + ( + "flip-link", + "(ESP32-C6/ESP32-H2 only): Move the stack to start of RAM to get zero-cost stack overflow protection.", + Value::Bool(false), + None + ), + // ideally we should only offer this for ESP32, ESP32-S2 and `octal` only for ESP32-S3 but the config system doesn't support per target configs, yet + ( + "psram-mode", + "(ESP32, ESP32-S2 and ESP32-S3 only, `octal` is only supported for ESP32-S3) SPIRAM chip mode", + Value::String(String::from("quad")), + Some(Validator::Enumeration( + vec![String::from("quad"), String::from("octal")] + )), + ) + ], 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 { @@ -253,7 +250,7 @@ fn generate_memory_extras() -> Vec { #[cfg(feature = "esp32s2")] fn generate_memory_extras() -> Vec { - let reserved_cache = if cfg!(feature = "quad-psram") { + let reserved_cache = if cfg!(feature = "psram") { "0x4000" } else { "0x2000" diff --git a/esp-hal/ld/esp32c2/esp32c2.x b/esp-hal/ld/esp32c2/esp32c2.x index a98f753ef1f..76225573343 100644 --- a/esp-hal/ld/esp32c2/esp32c2.x +++ b/esp-hal/ld/esp32c2/esp32c2.x @@ -90,3 +90,4 @@ INCLUDE "dram2.x" INCLUDE "debug.x" +_dram_origin = ORIGIN( DRAM ); diff --git a/esp-hal/ld/esp32c3/esp32c3.x b/esp-hal/ld/esp32c3/esp32c3.x index 51144d78407..4ed604f92a0 100644 --- a/esp-hal/ld/esp32c3/esp32c3.x +++ b/esp-hal/ld/esp32c3/esp32c3.x @@ -91,3 +91,4 @@ INCLUDE "dram2.x" INCLUDE "debug.x" +_dram_origin = ORIGIN( DRAM ); diff --git a/esp-hal/ld/esp32c6/esp32c6.x b/esp-hal/ld/esp32c6/esp32c6.x index 47f8de2e0ea..ac3ea162d7e 100644 --- a/esp-hal/ld/esp32c6/esp32c6.x +++ b/esp-hal/ld/esp32c6/esp32c6.x @@ -81,4 +81,6 @@ INCLUDE "stack.x" INCLUDE "dram2.x" /* End of Shared sections */ -INCLUDE "debug.x" \ No newline at end of file +INCLUDE "debug.x" + +_dram_origin = ORIGIN( RAM ); diff --git a/esp-hal/ld/esp32h2/esp32h2.x b/esp-hal/ld/esp32h2/esp32h2.x index c262159b2f1..d4ce0dbe33b 100644 --- a/esp-hal/ld/esp32h2/esp32h2.x +++ b/esp-hal/ld/esp32h2/esp32h2.x @@ -75,3 +75,5 @@ INCLUDE "dram2.x" /* End of Shared sections */ INCLUDE "debug.x" + +_dram_origin = ORIGIN( RAM ); diff --git a/esp-hal/ld/sections/rwdata.x b/esp-hal/ld/sections/rwdata.x index b00f877458d..f6accabeede 100644 --- a/esp-hal/ld/sections/rwdata.x +++ b/esp-hal/ld/sections/rwdata.x @@ -6,13 +6,13 @@ SECTIONS { _data_start = ABSOLUTE(.); . = ALIGN (4); - #IF ESP_HAL_PLACE_SWITCH_TABLES_IN_RAM + #IF ESP_HAL_CONFIG_PLACE_SWITCH_TABLES_IN_RAM *(.rodata.*_esp_hal_internal_handler*) *(.rodata..Lswitch.table.*) *(.rodata.cst*) #ENDIF - #IF ESP_HAL_PLACE_ANON_IN_RAM + #IF ESP_HAL_CONFIG_PLACE_ANON_IN_RAM *(.rodata..Lanon .rodata..Lanon.*) #ENDIF diff --git a/esp-hal/ld/sections/stack.x b/esp-hal/ld/sections/stack.x index e7e30693455..cfb3695c7a0 100644 --- a/esp-hal/ld/sections/stack.x +++ b/esp-hal/ld/sections/stack.x @@ -1,4 +1,4 @@ -#IF flip-link +#IF ESP_HAL_CONFIG_FLIP_LINK /* no Xtensa chip is supported - so we can assume RISC-V */ SECTIONS { /* must be last segment using RWDATA */ diff --git a/esp-hal/src/lib.rs b/esp-hal/src/lib.rs index feafc4f8820..af61c53ff0c 100644 --- a/esp-hal/src/lib.rs +++ b/esp-hal/src/lib.rs @@ -169,7 +169,7 @@ pub use self::soc::lp_core; pub use self::soc::peripherals; pub(crate) use self::soc::peripherals::pac; #[instability::unstable] -#[cfg(any(feature = "quad-psram", feature = "octal-psram"))] +#[cfg(feature = "psram")] pub use self::soc::psram; #[cfg(ulp_riscv_core)] #[instability::unstable] @@ -552,7 +552,7 @@ pub struct Config { /// PSRAM configuration. #[cfg(any(doc, feature = "unstable"))] #[cfg_attr(docsrs, doc(cfg(feature = "unstable")))] - #[cfg(any(feature = "quad-psram", feature = "octal-psram"))] + #[cfg(feature = "psram")] pub psram: psram::PsramConfig, } @@ -634,7 +634,7 @@ pub fn init(config: Config) -> Peripherals { crate::gpio::bind_default_interrupt_handler(); - #[cfg(any(feature = "quad-psram", feature = "octal-psram"))] + #[cfg(feature = "psram")] crate::psram::init_psram(config.psram); peripherals diff --git a/esp-hal/src/soc/esp32/mod.rs b/esp-hal/src/soc/esp32/mod.rs index 92a0b7bd9f2..7a361f24b70 100644 --- a/esp-hal/src/soc/esp32/mod.rs +++ b/esp-hal/src/soc/esp32/mod.rs @@ -11,7 +11,7 @@ use crate::rtc_cntl::SocResetReason; crate::unstable_module! { pub mod efuse; - #[cfg(feature = "quad-psram")] + #[cfg(feature = "psram")] pub mod psram; pub mod radio_clocks; pub mod trng; diff --git a/esp-hal/src/soc/esp32s2/mod.rs b/esp-hal/src/soc/esp32s2/mod.rs index 16dadc6ea90..56e629a5231 100644 --- a/esp-hal/src/soc/esp32s2/mod.rs +++ b/esp-hal/src/soc/esp32s2/mod.rs @@ -15,7 +15,7 @@ use crate::rtc_cntl::SocResetReason; crate::unstable_module! { pub mod efuse; - #[cfg(feature = "quad-psram")] + #[cfg(feature = "psram")] pub mod psram; pub mod radio_clocks; pub mod trng; diff --git a/esp-hal/src/soc/esp32s3/mod.rs b/esp-hal/src/soc/esp32s3/mod.rs index ba9700c61d6..33d0bc7664c 100644 --- a/esp-hal/src/soc/esp32s3/mod.rs +++ b/esp-hal/src/soc/esp32s3/mod.rs @@ -15,7 +15,7 @@ use crate::rtc_cntl::SocResetReason; crate::unstable_module! { pub mod efuse; - #[cfg(any(feature = "quad-psram", feature = "octal-psram"))] + #[cfg(feature = "psram")] pub mod psram; pub mod radio_clocks; pub mod trng; diff --git a/esp-hal/src/soc/esp32s3/psram.rs b/esp-hal/src/soc/esp32s3/psram.rs index cff314cc6a9..c60265a1057 100644 --- a/esp-hal/src/soc/esp32s3/psram.rs +++ b/esp-hal/src/soc/esp32s3/psram.rs @@ -18,8 +18,9 @@ //! ### Octal/Quad PSRAM //! This example shows how to use PSRAM as heap-memory via esp-alloc. //! You need an ESP32-S3 with at least 2 MB of PSRAM memory. -//! Either `Octal` or `Quad` PSRAM will be used, depending on whether -//! `octal-psram` or `quad-psram` feature is enabled. +//! Either `Octal` or `Quad` PSRAM will be used, depending on the +//! setting of `ESP_HAL_CONFIG_PSRAM_MODE`. +//! //! Notice that PSRAM example **must** be built in release mode! //! //! ```rust, no_run @@ -233,7 +234,7 @@ pub(crate) fn init_psram(config: PsramConfig) { } } -#[cfg(feature = "quad-psram")] +#[cfg(psram_mode_quad)] pub(crate) mod utils { use procmacros::ram; @@ -788,7 +789,7 @@ pub(crate) mod utils { } } -#[cfg(feature = "octal-psram")] +#[cfg(psram_mode_octal)] pub(crate) mod utils { use procmacros::ram; diff --git a/esp-hal/src/soc/mod.rs b/esp-hal/src/soc/mod.rs index 06a9c016841..3e061fe2ef5 100644 --- a/esp-hal/src/soc/mod.rs +++ b/esp-hal/src/soc/mod.rs @@ -15,7 +15,7 @@ mod implementation; mod efuse_field; -#[cfg(any(feature = "quad-psram", feature = "octal-psram"))] +#[cfg(feature = "psram")] mod psram_common; // Using static mut should be fine since we are only writing to it once during @@ -24,12 +24,12 @@ mod psram_common; // the HAL. This will access the PSRAM range, returning an empty range - which // is, at that point, true. The user has no (safe) means to allocate in PSRAM // before initializing the HAL. -#[cfg(any(feature = "quad-psram", feature = "octal-psram"))] +#[cfg(feature = "psram")] static mut MAPPED_PSRAM: MappedPsram = MappedPsram { memory_range: 0..0 }; pub(crate) fn psram_range() -> Range { cfg_if::cfg_if! { - if #[cfg(any(feature = "quad-psram", feature = "octal-psram"))] { + if #[cfg(feature = "psram")] { #[allow(static_mut_refs)] unsafe { MAPPED_PSRAM.memory_range.clone() } } else { @@ -40,7 +40,7 @@ pub(crate) fn psram_range() -> Range { const DRAM: Range = self::constants::SOC_DRAM_LOW..self::constants::SOC_DRAM_HIGH; -#[cfg(any(feature = "quad-psram", feature = "octal-psram"))] +#[cfg(feature = "psram")] pub struct MappedPsram { memory_range: Range, } diff --git a/esp-hal/src/soc/psram_common.rs b/esp-hal/src/soc/psram_common.rs index b46e67a1e25..0d6f745deab 100644 --- a/esp-hal/src/soc/psram_common.rs +++ b/esp-hal/src/soc/psram_common.rs @@ -25,7 +25,7 @@ impl PsramSize { } /// Returns the address and size of the available in external memory. -#[cfg(any(feature = "quad-psram", feature = "octal-psram"))] +#[cfg(feature = "psram")] pub fn psram_raw_parts(_psram: &crate::peripherals::PSRAM) -> (*mut u8, usize) { let range = crate::soc::psram_range(); (range.start as *mut u8, range.end - range.start) diff --git a/esp-riscv-rt/CHANGELOG.md b/esp-riscv-rt/CHANGELOG.md index d6a575c43e9..38a027f5b6d 100644 --- a/esp-riscv-rt/CHANGELOG.md +++ b/esp-riscv-rt/CHANGELOG.md @@ -13,6 +13,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Bump MSRV to 1.84 (#2951) +- Removed the `fix-sp` feature (check is always enabled) (#3001) + ### Fixed ### Removed diff --git a/esp-riscv-rt/Cargo.toml b/esp-riscv-rt/Cargo.toml index df9215a5a33..5351f0f2ab4 100644 --- a/esp-riscv-rt/Cargo.toml +++ b/esp-riscv-rt/Cargo.toml @@ -15,9 +15,6 @@ riscv = "0.12.1" riscv-rt-macros = "0.2.2" [features] -## Move the stack to the start of RAM to get zero-cost stack overflow -## protection (ESP32-C6 and ESP32-H2 only!) -fix-sp = [] ## Indicate that the device supports `mie` and `mip` instructions. has-mie-mip = [] ## Indicate that the device has RTC RAM. @@ -25,7 +22,6 @@ rtc-ram = [] # This feature is intended for testing; you probably don't want to enable it: ci = [ - "fix-sp", "has-mie-mip", "rtc-ram", ] diff --git a/esp-riscv-rt/src/lib.rs b/esp-riscv-rt/src/lib.rs index 4808cefd380..5c35b53ccb1 100644 --- a/esp-riscv-rt/src/lib.rs +++ b/esp-riscv-rt/src/lib.rs @@ -485,9 +485,6 @@ _abs_start: "#, r#" _start_trap: // Handle exceptions in vectored mode -"#, -#[cfg(feature="fix-sp")] -r#" // move SP to some save place if it's pointing below the RAM // otherwise we won't be able to do anything reasonable // (since we don't have a working stack) @@ -495,7 +492,7 @@ r#" // most probably we will just print something and halt in this case // we actually can't do anything else csrw mscratch, t0 - la t0, _stack_end + la t0, _dram_origin bge sp, t0, 1f // use the reserved exception cause 14 to signal we detected a stack overflow @@ -511,8 +508,7 @@ r#" 1: csrr t0, mscratch // now SP is in RAM - continue -"#, -r#" + addi sp, sp, -40*4 sw ra, 0(sp) la ra, _start_trap_rust_hal /* Load the HAL trap handler */ diff --git a/examples/src/bin/dma_extmem2mem.rs b/examples/src/bin/dma_extmem2mem.rs index 37abe60a9c4..5811ccfd145 100644 --- a/examples/src/bin/dma_extmem2mem.rs +++ b/examples/src/bin/dma_extmem2mem.rs @@ -1,6 +1,8 @@ //! Uses DMA to copy psram to internal memory. +//! +//! If your module is octal PSRAM then you need to set `ESP_HAL_CONFIG_PSRAM_MODE` to `octal`. -//% FEATURES: esp-hal/log esp-hal/octal-psram aligned esp-hal/unstable +//% FEATURES: esp-hal/log esp-hal/psram aligned esp-hal/unstable //% CHIPS: esp32s3 #![no_std] diff --git a/examples/src/bin/spi_loopback_dma_psram.rs b/examples/src/bin/spi_loopback_dma_psram.rs index fc023c42e75..3729698b0d3 100644 --- a/examples/src/bin/spi_loopback_dma_psram.rs +++ b/examples/src/bin/spi_loopback_dma_psram.rs @@ -13,10 +13,9 @@ //! Connect MISO and MOSI pins to see the outgoing data is read as incoming //! data. //! -//! If your module is quad PSRAM then you need to change the `psram` feature in the -//! in the features line below to `quad-psram`. +//! If your module is octal PSRAM then you need to set `ESP_HAL_CONFIG_PSRAM_MODE` to `octal`. -//% FEATURES: esp-hal/log esp-hal/octal-psram esp-hal/unstable +//% FEATURES: esp-hal/log esp-hal/psram esp-hal/unstable //% CHIPS: esp32s3 #![no_std] diff --git a/hil-test/Cargo.toml b/hil-test/Cargo.toml index 61c3716040f..9f679509347 100644 --- a/hil-test/Cargo.toml +++ b/hil-test/Cargo.toml @@ -294,8 +294,7 @@ esp32s3 = [ embassy = [ "dep:esp-hal-embassy", ] -octal-psram = ["esp-hal/octal-psram", "esp-alloc"] -quad-psram = ["esp-hal/quad-psram", "esp-alloc"] +psram = ["esp-hal/psram", "esp-alloc"] # https://doc.rust-lang.org/cargo/reference/profiles.html#test # Test and bench profiles inherit from dev and release respectively. diff --git a/hil-test/tests/spi_half_duplex_write_psram.rs b/hil-test/tests/spi_half_duplex_write_psram.rs index 26e27b714ec..11dcca8f085 100644 --- a/hil-test/tests/spi_half_duplex_write_psram.rs +++ b/hil-test/tests/spi_half_duplex_write_psram.rs @@ -1,7 +1,7 @@ //! SPI Half Duplex Write Test //% CHIPS: esp32s3 -//% FEATURES: unstable octal-psram +//% FEATURES: unstable psram #![no_std] #![no_main] diff --git a/qa-test/src/bin/psram_quad.rs b/qa-test/src/bin/psram.rs similarity index 88% rename from qa-test/src/bin/psram_quad.rs rename to qa-test/src/bin/psram.rs index 7a49d063472..0c2926f6660 100644 --- a/qa-test/src/bin/psram_quad.rs +++ b/qa-test/src/bin/psram.rs @@ -1,9 +1,12 @@ //! This shows how to use PSRAM as heap-memory via esp-alloc //! //! You need an ESP32, ESP32-S2 or ESP32-S3 with at least 2 MB of PSRAM memory. +//! +//! On ESP32-S3 you might want to set `ESP_HAL_CONFIG_PSRAM_MODE` to `octal` if +//! the device comes with octal-SPIRAM //% CHIPS: esp32 esp32s2 esp32s3 -//% FEATURES: esp-hal/quad-psram esp-alloc/internal-heap-stats +//% FEATURES: esp-hal/psram esp-alloc/internal-heap-stats esp-hal/log #![no_std] #![no_main] diff --git a/qa-test/src/bin/psram_octal.rs b/qa-test/src/bin/psram_octal.rs deleted file mode 100644 index 84a61839673..00000000000 --- a/qa-test/src/bin/psram_octal.rs +++ /dev/null @@ -1,58 +0,0 @@ -//! This shows how to use PSRAM as heap-memory via esp-alloc -//! -//! You need an ESP32-S3 with at least 2 MB of PSRAM memory. - -//% CHIPS: esp32s3 -//% FEATURES: esp-hal/octal-psram - -#![no_std] -#![no_main] - -extern crate alloc; - -use alloc::{string::String, vec::Vec}; - -use esp_alloc as _; -use esp_backtrace as _; -use esp_hal::{main, psram}; -use esp_println::println; - -fn init_psram_heap(start: *mut u8, size: usize) { - unsafe { - esp_alloc::HEAP.add_region(esp_alloc::HeapRegion::new( - start, - size, - esp_alloc::MemoryCapability::External.into(), - )); - } -} - -#[cfg(is_not_release)] -compile_error!("PSRAM example must be built in release mode!"); - -#[main] -fn main() -> ! { - esp_println::logger::init_logger_from_env(); - let peripherals = esp_hal::init(esp_hal::Config::default()); - - let (start, size) = psram::psram_raw_parts(&peripherals.PSRAM); - init_psram_heap(start, size); - - println!("Going to access PSRAM"); - let mut large_vec: Vec = Vec::with_capacity(500 * 1024 / 4); - - for i in 0..(500 * 1024 / 4) { - large_vec.push((i & 0xff) as u32); - } - - println!("vec size = {} bytes", large_vec.len() * 4); - println!("vec address = {:p}", large_vec.as_ptr()); - println!("vec[..100] = {:?}", &large_vec[..100]); - - let string = String::from("A string allocated in PSRAM"); - println!("'{}' allocated at {:p}", &string, string.as_ptr()); - - println!("done"); - - loop {} -} diff --git a/xtask/src/lib.rs b/xtask/src/lib.rs index 0667dfece2e..95b3ae5d370 100644 --- a/xtask/src/lib.rs +++ b/xtask/src/lib.rs @@ -187,9 +187,9 @@ fn apply_feature_rules(package: &Package, config: &Config) -> Vec { features.push("unstable".to_owned()); features.push("ci".to_owned()); match chip_name.as_str() { - "esp32" => features.push("quad-psram".to_owned()), - "esp32s2" => features.push("quad-psram".to_owned()), - "esp32s3" => features.push("quad-psram".to_owned()), + "esp32" => features.push("psram".to_owned()), + "esp32s2" => features.push("psram".to_owned()), + "esp32s3" => features.push("psram".to_owned()), _ => {} }; } diff --git a/xtask/src/main.rs b/xtask/src/main.rs index 1ecac248404..6d3a975ac63 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -705,11 +705,9 @@ fn lint_packages(workspace: &Path, args: LintPackagesArgs) -> Result<()> { features.push_str(",bluetooth") } if device.contains("psram") { - // TODO this doesn't test octal psram as it would require a separate build - features.push_str(",quad-psram") - } - if matches!(chip, Chip::Esp32c6 | Chip::Esp32h2) { - features.push_str(",flip-link") + // TODO this doesn't test octal psram (since `ESP_HAL_CONFIG_PSRAM_MODE` + // defaults to `quad`) as it would require a separate build + features.push_str(",psram") } lint_package(