diff --git a/Cargo.toml b/Cargo.toml index 4d9381fb6..a7c4172d7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,4 +21,7 @@ exclude = [ "extras/esp-wifishark", "extras/ieee802154-sniffer", "hil-test", + "xtensa-lx", + "xtensa-lx-rt", + "xtensa-lx-rt/procmacros", ] diff --git a/xtask/src/lib.rs b/xtask/src/lib.rs index fd035ef2a..126f24a58 100644 --- a/xtask/src/lib.rs +++ b/xtask/src/lib.rs @@ -48,6 +48,8 @@ pub enum Package { EspWifi, Examples, HilTest, + XtensaLx, + XtensaLxRt, } #[derive(Debug, Clone, Copy, PartialEq, Eq, Display, EnumIter, ValueEnum, serde::Serialize)] diff --git a/xtask/src/main.rs b/xtask/src/main.rs index bc8eae358..a3f4739ca 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -126,7 +126,11 @@ struct GenerateEfuseFieldsArgs { } #[derive(Debug, Args)] -struct LintPackagesArgs {} +struct LintPackagesArgs { + /// Package(s) to target. + #[arg(value_enum, default_values_t = Package::iter())] + packages: Vec, +} #[derive(Debug, Args)] struct RunElfArgs { @@ -449,8 +453,8 @@ fn fmt_packages(workspace: &Path, args: FmtPackagesArgs) -> Result<()> { Ok(()) } -fn lint_packages(workspace: &Path, _args: LintPackagesArgs) -> Result<()> { - let mut packages = Package::iter().collect::>(); +fn lint_packages(workspace: &Path, args: LintPackagesArgs) -> Result<()> { + let mut packages = args.packages; packages.sort(); for package in packages { @@ -538,6 +542,19 @@ fn lint_packages(workspace: &Path, _args: LintPackagesArgs) -> Result<()> { ], )?, + Package::XtensaLxRt => { + for chip in [Chip::Esp32, Chip::Esp32s2, Chip::Esp32s3] { + lint_package( + &path, + &[ + "-Zbuild-std=core", + &format!("--target=xtensa-{chip}-none-elf"), + &format!("--features={chip}"), + ], + )? + } + } + // We will *not* check the following packages with `clippy`; this // may or may not change in the future: Package::Examples | Package::HilTest => {} diff --git a/xtensa-lx-rt/Cargo.toml b/xtensa-lx-rt/Cargo.toml new file mode 100644 index 000000000..ea79107f5 --- /dev/null +++ b/xtensa-lx-rt/Cargo.toml @@ -0,0 +1,43 @@ +[package] +name = "xtensa-lx-rt" +version = "0.16.0" +edition = "2021" +rust-version = "1.65" +description = "Minimal startup/runtime for Xtensa LX CPUs" +repository = "https://github.com/esp-rs/esp-hal" +license = "MIT OR Apache-2.0" +keywords = ["xtensa", "lx", "register", "peripheral"] +categories = ["embedded", "hardware-support", "no-std"] + +[package.metadata.docs.rs] +features = ["esp32"] + +[dependencies] +bare-metal = "1.0.0" +document-features = "0.2.8" +macros = { version = "0.2.1", package = "xtensa-lx-rt-proc-macros", path = "./procmacros" } +r0 = "1.0.0" +xtensa-lx = { version = "0.9.0", path = "../xtensa-lx" } + +[build-dependencies] +anyhow = "1.0.86" +enum-as-inner = "0.6.0" +minijinja = "2.0.3" +serde = { version = "1.0.204", features = ["derive"] } +strum = { version = "0.26.3", features = ["derive"] } +toml = "0.8.10" + +[features] +## Save and restore float registers for exceptions +float-save-restore = [] + +#! ### Chip Support Feature Flags +## Target the ESP32 +esp32 = [] +## Target the ESP32-S2 +esp32s2 = [] +## Target the ESP32-S3 +esp32s3 = [] + +[lints.rust] +unexpected_cfgs = "allow" diff --git a/xtensa-lx-rt/README.md b/xtensa-lx-rt/README.md new file mode 100644 index 000000000..20c742d71 --- /dev/null +++ b/xtensa-lx-rt/README.md @@ -0,0 +1,39 @@ +# `xtensa-lx-rt` + +[![Crates.io](https://img.shields.io/crates/v/xtensa-lx-rt?labelColor=1C2C2E&color=C96329&logo=Rust&style=flat-square)](https://crates.io/crates/xtensa-lx-rt) +[![docs.rs](https://img.shields.io/docsrs/xtensa-lx-rt?labelColor=1C2C2E&color=C96329&logo=rust&style=flat-square)](https://docs.rs/xtensa-lx-rt) +![Crates.io](https://img.shields.io/crates/l/xtensa-lx-rt?labelColor=1C2C2E&style=flat-square) +[![Matrix](https://img.shields.io/matrix/esp-rs:matrix.org?label=join%20matrix&labelColor=1C2C2E&color=BEC5C9&logo=matrix&style=flat-square)](https://matrix.to/#/#esp-rs:matrix.org) + +Minimal runtime/startup for Xtensa LX processors. This crate currently supports the following CPU's: + +| Feature | Supported CPUs | +| --------- | ---------------- | +| `esp32` | ESP32 (_LX6_) | +| `esp32s2` | ESP32-S2 (_LX7_) | +| `esp32s3` | ESP32-S3 (_LX7_) | + +## I get linker errors when I build for debug + +Xtensa only provides a small code space for exceptions to fit inside, when building an unoptimized build the code size of a exception handler may exceed that size, causing a linker error. To fix this, you should always optimize this crate, even in debug builds. Adding the following to your projects `Cargo.toml` should do the trick. + +```toml +[profile.dev.package.xtensa-lx-rt] +opt-level = 'z' +``` + +## License + +Licensed under either of + +- Apache License, Version 2.0 ([LICENSE-APACHE](../LICENSE-APACHE) or + http://www.apache.org/licenses/LICENSE-2.0) +- MIT license ([LICENSE-MIT](../LICENSE-MIT) or http://opensource.org/licenses/MIT) + +at your option. + +### Contribution + +Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the +work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any +additional terms or conditions. diff --git a/xtensa-lx-rt/build.rs b/xtensa-lx-rt/build.rs new file mode 100644 index 000000000..20748844c --- /dev/null +++ b/xtensa-lx-rt/build.rs @@ -0,0 +1,243 @@ +use std::{ + collections::{HashMap, HashSet}, + env, + fs::{self, File}, + io::Write, + path::{Path, PathBuf}, +}; + +use anyhow::Result; +use enum_as_inner::EnumAsInner; +use minijinja::{context, Environment}; +use serde::Deserialize; +use strum::{Display, EnumIter, EnumString}; + +/// The chips which are present in the xtensa-overlays repository +/// +/// When `.to_string()` is called on a variant, the resulting string is the path +/// to the chip's corresponding directory. +#[derive(Debug, Clone, Copy, PartialEq, Display, EnumIter, Deserialize)] +enum Chip { + #[strum(to_string = "xtensa_esp32")] + Esp32, + #[strum(to_string = "xtensa_esp32s2")] + Esp32s2, + #[strum(to_string = "xtensa_esp32s3")] + Esp32s3, +} + +/// The valid interrupt types declared in the `core-isa.h` headers +#[derive(Debug, Clone, Copy, PartialEq, EnumString, Deserialize)] +enum InterruptType { + #[strum(serialize = "XTHAL_INTTYPE_EXTERN_EDGE")] + ExternEdge, + #[strum(serialize = "XTHAL_INTTYPE_EXTERN_LEVEL")] + ExternLevel, + #[strum(serialize = "XTHAL_INTTYPE_NMI")] + Nmi, + #[strum(serialize = "XTHAL_INTTYPE_PROFILING")] + Profiling, + #[strum(serialize = "XTHAL_INTTYPE_SOFTWARE")] + Software, + #[strum(serialize = "XTHAL_INTTYPE_TIMER")] + Timer, + #[strum(serialize = "XTHAL_TIMER_UNCONFIGURED")] + TimerUnconfigured, +} + +/// The allowable value types for definitions +#[derive(Debug, Clone, PartialEq, EnumAsInner, Deserialize)] +enum Value { + Integer(i64), + Interrupt(InterruptType), + String(String), +} + +fn main() -> Result<()> { + let out = &PathBuf::from(env::var_os("OUT_DIR").unwrap()); + + // Put the linker script somewhere the linker can find it + println!("cargo:rustc-link-search={}", out.display()); + + File::create(out.join("link.x"))?.write_all(include_bytes!("xtensa.in.x"))?; + + handle_esp32()?; + + // Only re-run the build script when xtensa.in.x is changed, + // instead of when any part of the source code changes. + println!("cargo:rerun-if-changed=xtensa.in.x"); + + Ok(()) +} + +fn handle_esp32() -> Result<()> { + let out = &PathBuf::from(env::var_os("OUT_DIR").unwrap()); + + let rustflags = env::var_os("CARGO_ENCODED_RUSTFLAGS") + .unwrap() + .into_string() + .unwrap(); + + let mut features_to_disable: HashSet = HashSet::new(); + + // Users can pass -Ctarget-feature to the compiler multiple times, so we have to + // handle that + let target_flags = rustflags + .split(0x1f as char) + .filter(|s| s.starts_with("target-feature=")) + .filter_map(|s| s.strip_prefix("target-feature=")); + for tf in target_flags { + tf.split(',') + .map(|s| s.trim()) + .filter(|s| s.starts_with('-')) + .filter_map(|s| s.strip_prefix('-')) + .filter_map(rustc_feature_to_xchal_have) + .for_each(|s| { + features_to_disable.insert(s.to_owned()); + }) + } + + let chip = match ( + cfg!(feature = "esp32"), + cfg!(feature = "esp32s2"), + cfg!(feature = "esp32s3"), + ) { + (true, false, false) => Chip::Esp32, + (false, true, false) => Chip::Esp32s2, + (false, false, true) => Chip::Esp32s3, + _ => panic!("Either the esp32, esp32s2, esp32s3 feature must be enabled"), + }; + + let isa_toml = fs::read_to_string(format!("config/{chip}.toml"))?; + let isa_config: HashMap = toml::from_str(&isa_toml)?; + + inject_cfgs(&isa_config, &features_to_disable); + inject_cpu_cfgs(&isa_config); + generate_exception_x(out, &isa_config)?; + generate_interrupt_level_masks(out, &isa_config)?; + + Ok(()) +} + +fn generate_interrupt_level_masks(out: &Path, isa_config: &HashMap) -> Result<()> { + let exception_source_template = include_str!("interrupt_level_masks.rs.jinja"); + + let mut env = Environment::new(); + env.add_template("interrupt_level_masks.rs", exception_source_template)?; + + let template = env.get_template("interrupt_level_masks.rs").unwrap(); + let exception_source = template.render(context! { + XCHAL_INTLEVEL1_MASK => isa_config.get("XCHAL_INTLEVEL1_MASK").unwrap().as_integer(), + XCHAL_INTLEVEL2_MASK => isa_config.get("XCHAL_INTLEVEL2_MASK").unwrap().as_integer(), + XCHAL_INTLEVEL3_MASK => isa_config.get("XCHAL_INTLEVEL3_MASK").unwrap().as_integer(), + XCHAL_INTLEVEL4_MASK => isa_config.get("XCHAL_INTLEVEL4_MASK").unwrap().as_integer(), + XCHAL_INTLEVEL5_MASK => isa_config.get("XCHAL_INTLEVEL5_MASK").unwrap().as_integer(), + XCHAL_INTLEVEL6_MASK => isa_config.get("XCHAL_INTLEVEL6_MASK").unwrap().as_integer(), + XCHAL_INTLEVEL7_MASK => isa_config.get("XCHAL_INTLEVEL7_MASK").unwrap().as_integer(), + })?; + + File::create(out.join("interrupt_level_masks.rs"))?.write_all(exception_source.as_bytes())?; + + Ok(()) +} + +fn generate_exception_x(out: &Path, isa_config: &HashMap) -> Result<()> { + let exception_source_template = include_str!("exception-esp32.x.jinja"); + + let mut env = Environment::new(); + env.add_template("exception.x", exception_source_template)?; + + let template = env.get_template("exception.x")?; + let exception_source = template.render( + context! { + XCHAL_WINDOW_OF4_VECOFS => isa_config.get("XCHAL_WINDOW_OF4_VECOFS").unwrap().as_integer(), + XCHAL_WINDOW_UF4_VECOFS => isa_config.get("XCHAL_WINDOW_UF4_VECOFS").unwrap().as_integer(), + XCHAL_WINDOW_OF8_VECOFS => isa_config.get("XCHAL_WINDOW_OF8_VECOFS").unwrap().as_integer(), + XCHAL_WINDOW_UF8_VECOFS => isa_config.get("XCHAL_WINDOW_UF8_VECOFS").unwrap().as_integer(), + XCHAL_WINDOW_OF12_VECOFS => isa_config.get("XCHAL_WINDOW_OF12_VECOFS").unwrap().as_integer(), + XCHAL_WINDOW_UF12_VECOFS => isa_config.get("XCHAL_WINDOW_UF12_VECOFS").unwrap().as_integer(), + XCHAL_INTLEVEL2_VECOFS => isa_config.get("XCHAL_INTLEVEL2_VECOFS").unwrap().as_integer(), + XCHAL_INTLEVEL3_VECOFS => isa_config.get("XCHAL_INTLEVEL3_VECOFS").unwrap().as_integer(), + XCHAL_INTLEVEL4_VECOFS => isa_config.get("XCHAL_INTLEVEL4_VECOFS").unwrap().as_integer(), + XCHAL_INTLEVEL5_VECOFS => isa_config.get("XCHAL_INTLEVEL5_VECOFS").unwrap().as_integer(), + XCHAL_INTLEVEL6_VECOFS => isa_config.get("XCHAL_INTLEVEL6_VECOFS").unwrap().as_integer(), + XCHAL_NMI_VECOFS => isa_config.get("XCHAL_NMI_VECOFS").unwrap().as_integer(), + XCHAL_KERNEL_VECOFS => isa_config.get("XCHAL_KERNEL_VECOFS").unwrap().as_integer(), + XCHAL_USER_VECOFS => isa_config.get("XCHAL_USER_VECOFS").unwrap().as_integer(), + XCHAL_DOUBLEEXC_VECOFS => isa_config.get("XCHAL_DOUBLEEXC_VECOFS").unwrap().as_integer(), + } + )?; + + File::create(out.join("exception.x"))?.write_all(exception_source.as_bytes())?; + + Ok(()) +} + +fn inject_cfgs(isa_config: &HashMap, disabled_features: &HashSet) { + for (key, value) in isa_config { + if key.starts_with("XCHAL_HAVE") + && *value.as_integer().unwrap_or(&0) != 0 + && !disabled_features.contains(key) + { + println!("cargo:rustc-cfg={}", key); + } + } +} + +fn inject_cpu_cfgs(isa_config: &HashMap) { + for (key, value) in isa_config { + if (key.starts_with("XCHAL_TIMER") + || key.starts_with("XCHAL_PROFILING") + || key.starts_with("XCHAL_NMI")) + && value.as_integer().is_some() + { + let mut s = String::from(key.trim_end_matches("_INTERRUPT")); + let first = s.chars().position(|c| c == '_').unwrap() + 1; + s.insert_str(first, "HAVE_"); + println!("cargo:rustc-cfg={}", s); + } + } + if let Some(value) = isa_config + .get("XCHAL_INTTYPE_MASK_SOFTWARE") + .and_then(|v| v.as_integer()) + { + for i in 0..value.count_ones() { + println!("cargo:rustc-cfg=XCHAL_HAVE_SOFTWARE{}", i); + } + } +} + +fn rustc_feature_to_xchal_have(s: &str) -> Option<&str> { + // List of rustc features taken from here: + // https://github.com/esp-rs/rust/blob/84ecb3f010525cb1b2e7d4da306099c2eaa3e6cd/compiler/rustc_codegen_ssa/src/target_features.rs#L278 + // unlikely to change + Some(match s { + "fp" => "XCHAL_HAVE_FP", + "windowed" => "XCHAL_HAVE_WINDOWED", + "bool" => "XCHAL_HAVE_BOOLEANS", + "loop" => "XCHAL_HAVE_LOOPS", + "sext" => "XCHAL_HAVE_SEXT", + "nsa" => "XCHAL_HAVE_NSA", + "mul32" => "XCHAL_HAVE_MUL32", + "mul32high" => "XCHAL_HAVE_MUL32_HIGH", + "div32" => "XCHAL_HAVE_DIV32", + "mac16" => "XCHAL_HAVE_MAC16", + "dfpaccel" => "XCHAL_HAVE_DFP", + "s32c1i" => "XCHAL_HAVE_S32C1I", + "threadptr" => "XCHAL_HAVE_THREADPTR", + "extendedl32r" => "XCHAL_HAVE_ABSOLUTE_LITERALS", + "debug" => "XCHAL_HAVE_DEBUG", + "exception" => "XCHAL_HAVE_EXCEPTIONS", + "highpriinterrupts" => "XCHAL_HAVE_HIGHPRI_INTERRUPTS", + "coprocessor" => "XCHAL_HAVE_CP", + "interrupt" => "XCHAL_HAVE_INTERRUPTS", + "rvector" => "XCHAL_HAVE_VECTOR_SELECT", + "prid" => "XCHAL_HAVE_PRID", + "regprotect" => "XCHAL_HAVE_MIMIC_CACHEATTR", + "miscsr" => return None, // XCHAL_NUM_MISC_REGS + "timerint" => return None, // XCHAL_NUM_TIMERS + "atomctl" => return None, + "memctl" => return None, + _ => return None, + }) +} diff --git a/xtensa-lx-rt/config/xtensa_esp32.toml b/xtensa-lx-rt/config/xtensa_esp32.toml new file mode 100644 index 000000000..0d719ddde --- /dev/null +++ b/xtensa-lx-rt/config/xtensa_esp32.toml @@ -0,0 +1,1337 @@ +[XCHAL_RESET_VECTOR1_PADDR] +Integer = 1073742848 + +[XCHAL_HAVE_DCACHE_DYN_WAYS] +Integer = 0 + +[XCHAL_HAVE_DFPU_SINGLE_ONLY] +Integer = 1 + +[XCHAL_DATARAM0_ECC_PARITY] +Integer = 0 + +[XCHAL_HAVE_HIFI3] +Integer = 0 + +[XCHAL_EXTINT13_NUM] +Integer = 18 + +[XCHAL_HAVE_CP] +Integer = 1 + +[XCHAL_INT20_TYPE] +Interrupt = "ExternLevel" + +[XCHAL_INSTROM0_SIZE] +Integer = 4194304 + +[XCHAL_INTTYPE_MASK_EXTERN_EDGE] +Integer = 1346372608 + +[XCHAL_HAVE_XLT_CACHEATTR] +Integer = 0 + +[XCHAL_INT17_LEVEL] +Integer = 1 + +[XCHAL_INTLEVEL3_ANDBELOW_MASK] +Integer = 687783935 + +[XCHAL_INT8_LEVEL] +Integer = 1 + +[XCHAL_SW_VERSION] +Integer = 1100003 + +[XCHAL_HAVE_IMEM_LOADSTORE] +Integer = 1 + +[XCHAL_NUM_WRITEBUFFER_ENTRIES] +Integer = 4 + +[XCHAL_HAVE_FUSION_FP] +Integer = 0 + +[XCHAL_HW_VERSION] +Integer = 260003 + +[XCHAL_DATA_PIPE_DELAY] +Integer = 2 + +[XCHAL_HAVE_FULL_RESET] +Integer = 1 + +[XCHAL_DATARAM0_VADDR] +Integer = 1073217536 + +[XCHAL_INT24_LEVEL] +Integer = 4 + +[XCHAL_HAVE_FP_SQRT] +Integer = 1 + +[XCHAL_NUM_INSTRAM] +Integer = 2 + +[XCHAL_HAVE_DFP_accel] +Integer = 1 + +[XCHAL_INT4_TYPE] +Interrupt = "ExternLevel" + +[XCHAL_INT9_TYPE] +Interrupt = "ExternLevel" + +[XCHAL_EXTINT7_NUM] +Integer = 9 + +[XCHAL_EXTINT16_NUM] +Integer = 21 + +[XCHAL_INT13_EXTNUM] +Integer = 10 + +[XCHAL_HAVE_VECTOR_SELECT] +Integer = 1 + +[XCHAL_PREFETCH_BLOCK_ENTRIES] +Integer = 0 + +[XCHAL_PREFETCH_CASTOUT_LINES] +Integer = 0 + +[XCHAL_INT28_TYPE] +Interrupt = "ExternEdge" + +[XCHAL_INT0_EXTNUM] +Integer = 0 + +[XCHAL_BUILD_UNIQUE_ID] +Integer = 392854 + +[XCHAL_HAVE_DCACHE_TEST] +Integer = 0 + +[XCHAL_INTLEVEL1_MASK] +Integer = 407551 + +[XCHAL_HAVE_DEBUG_EXTERN_INT] +Integer = 1 + +[XCHAL_HAVE_DFP_RECIP] +Integer = 0 + +[XCHAL_EXTINT8_NUM] +Integer = 10 + +[XCHAL_INTLEVEL3_MASK] +Integer = 683706368 + +[XCHAL_DCACHE_ACCESS_SIZE] +Integer = 1 + +[XCHAL_INT3_LEVEL] +Integer = 1 + +[XCHAL_INT8_TYPE] +Interrupt = "ExternLevel" + +[XCHAL_INT3_EXTNUM] +Integer = 3 + +[XCHAL_INTLEVEL2_MASK] +Integer = 3670016 + +[XCHAL_INT11_TYPE] +Interrupt = "Profiling" + +[XCHAL_HAVE_BOOTLOADER] +Integer = 0 + +[XCHAL_VECBASE_RESET_VADDR] +Integer = 1073741824 + +[XCHAL_INTLEVEL3_VECTOR_PADDR] +Integer = 1073742272 + +[XCHAL_INTLEVEL4_VECOFS] +Integer = 512 + +[XCHAL_DOUBLEEXC_VECTOR_PADDR] +Integer = 1073742784 + +[XCHAL_INTTYPE_MASK_TIMER] +Integer = 98368 + +[XCHAL_XEA_VERSION] +Integer = 2 + +[XCHAL_EXTINT24_NUM] +Integer = 30 + +[XCHAL_USER_VECOFS] +Integer = 832 + +[XCHAL_HAVE_OCD] +Integer = 1 + +[XCHAL_INTLEVEL2_VECTOR_PADDR] +Integer = 1073742208 + +[XCHAL_HW_REL_LX6] +Integer = 1 + +[XCHAL_NUM_XLMI] +Integer = 1 + +[XCHAL_HAVE_HIGHPRI_INTERRUPTS] +Integer = 1 + +[XCHAL_INT29_LEVEL] +Integer = 3 + +[XCHAL_INT28_LEVEL] +Integer = 4 + +[XCHAL_EXTINT19_NUM] +Integer = 24 + +[XCHAL_TIMER3_INTERRUPT] +Interrupt = "TimerUnconfigured" + +[XCHAL_RESET_VECTOR_VADDR] +Integer = 1073742848 + +[XCHAL_HAVE_HIFI_MINI] +Integer = 0 + +[XCHAL_INTLEVEL3_VECTOR_VADDR] +Integer = 1073742272 + +[XCHAL_INTLEVEL5_VECOFS] +Integer = 576 + +[XCHAL_HAVE_TAP_MASTER] +Integer = 0 + +[XCHAL_INT9_EXTNUM] +Integer = 7 + +[XCHAL_EXTINT25_NUM] +Integer = 31 + +[XCHAL_INT14_LEVEL] +Integer = 7 + +[XCHAL_INT30_TYPE] +Interrupt = "ExternEdge" + +[XCHAL_INSTRAM0_VADDR] +Integer = 1073741824 + +[XCHAL_INT14_TYPE] +Interrupt = "Nmi" + +[XCHAL_ICACHE_ACCESS_SIZE] +Integer = 1 + +[XCHAL_HAVE_SPECULATION] +Integer = 0 + +[XCHAL_INT20_LEVEL] +Integer = 2 + +[XCHAL_HAVE_VECTRALX] +Integer = 0 + +[XCHAL_DATARAM0_BANKS] +Integer = 1 + +[XCHAL_INT27_TYPE] +Interrupt = "ExternLevel" + +[XCHAL_HW_VERSION_MINOR] +Integer = 3 + +[XCHAL_CP_MAXCFG] +Integer = 8 + +[XCHAL_ICACHE_ECC_PARITY] +Integer = 0 + +[XCHAL_INSTRAM0_ECC_PARITY] +Integer = 0 + +[XCHAL_INT14_EXTNUM] +Integer = 11 + +[XCHAL_INT18_EXTNUM] +Integer = 13 + +[XCHAL_RESET_VECTOR0_VADDR] +Integer = 1342177280 + +[XCHAL_USER_VECTOR_VADDR] +Integer = 1073742656 + +[XCHAL_TRAX_TIME_WIDTH] +Integer = 0 + +[XCHAL_DCACHE_IS_COHERENT] +Integer = 0 + +[XCHAL_INT22_TYPE] +Interrupt = "ExternEdge" + +[XCHAL_HAVE_DFP_ACCEL] +Integer = 1 + +[XCHAL_NUM_LOADSTORE_UNITS] +Integer = 1 + +[XCHAL_HAVE_BSP3_TRANSPOSE] +Integer = 0 + +[XCHAL_DEBUG_VECTOR_PADDR] +Integer = 1073742464 + +[XCHAL_DATARAM1_VADDR] +Integer = 1065353216 + +[XCHAL_HAVE_SSP16] +Integer = 0 + +[XCHAL_INSTRAM1_SIZE] +Integer = 4194304 + +[XCHAL_PREFETCH_ENTRIES] +Integer = 0 + +[XCHAL_INT26_LEVEL] +Integer = 5 + +[XCHAL_INTLEVEL7_VECTOR_PADDR] +Integer = 1073742528 + +[XCHAL_INTTYPE_MASK_SOFTWARE] +Integer = 536871040 + +[XCHAL_HAVE_BE] +Integer = 0 + +[XCHAL_HAVE_PREDICTED_BRANCHES] +Integer = 0 + +[XCHAL_ICACHE_LINEWIDTH] +Integer = 2 + +[XCHAL_CLOCK_GATING_GLOBAL] +Integer = 1 + +[XCHAL_HAVE_ABS] +Integer = 1 + +[XCHAL_HAVE_FUSION] +Integer = 0 + +[XCHAL_HAVE_PIF] +Integer = 1 + +[XCHAL_INSTRAM1_VADDR] +Integer = 1077936128 + +[XCHAL_HAVE_DFP] +Integer = 0 + +[XCHAL_HAVE_GRIVPEP] +Integer = 0 + +[XCHAL_NUM_MISC_REGS] +Integer = 4 + +[XCHAL_ICACHE_LINESIZE] +Integer = 4 + +[XCHAL_INTLEVEL4_MASK] +Integer = 1392508928 + +[XCHAL_INT18_TYPE] +Interrupt = "ExternLevel" + +[XCHAL_XLMI0_ECC_PARITY] +Integer = 0 + +[XCHAL_INT29_TYPE] +Interrupt = "Software" + +[XCHAL_HAVE_DEBUG] +Integer = 1 + +[XCHAL_INTLEVEL1_ANDBELOW_MASK] +Integer = 407551 + +[XCHAL_INTTYPE_MASK_NMI] +Integer = 16384 + +[XCHAL_HAVE_TURBO16] +Integer = 0 + +[XCHAL_TIMER0_INTERRUPT] +Integer = 6 + +[XCHAL_INT25_LEVEL] +Integer = 4 + +[XCHAL_INT3_TYPE] +Interrupt = "ExternLevel" + +[XCHAL_EXTINT10_NUM] +Integer = 13 + +[XCHAL_EXTINT18_NUM] +Integer = 23 + +[XCHAL_INT5_EXTNUM] +Integer = 5 + +[XCHAL_HAVE_THREADPTR] +Integer = 1 + +[XCHAL_INT31_EXTNUM] +Integer = 25 + +[XCHAL_RESET_VECTOR_PADDR] +Integer = 1073742848 + +[XCHAL_DOUBLEEXC_VECTOR_VADDR] +Integer = 1073742784 + +[XCHAL_INTLEVEL4_VECTOR_PADDR] +Integer = 1073742336 + +[XCHAL_INT22_LEVEL] +Integer = 3 + +[XCHAL_HW_MAX_VERSION_MAJOR] +Integer = 2600 + +[XCHAL_INT30_EXTNUM] +Integer = 24 + +[XCHAL_INT25_EXTNUM] +Integer = 20 + +[XCHAL_HAVE_FUSION_BITOPS] +Integer = 0 + +[XCHAL_DATARAM1_PADDR] +Integer = 1065353216 + +[XCHAL_DATARAM0_SIZE] +Integer = 524288 + +[XCHAL_INTLEVEL2_ANDBELOW_MASK] +Integer = 4077567 + +[XCHAL_INT6_TYPE] +Interrupt = "Timer" + +[XCHAL_INT23_TYPE] +Interrupt = "ExternLevel" + +[XCHAL_HAVE_FUSION_LFSR_CRC] +Integer = 0 + +[XCHAL_INT5_LEVEL] +Integer = 1 + +[XCHAL_HAVE_BBE16_RSQRT] +Integer = 0 + +[XCHAL_CA_BITS] +Integer = 4 + +[XCHAL_HAVE_CALL4AND12] +Integer = 1 + +[XCHAL_HAVE_GRIVPEP_HISTOGRAM] +Integer = 0 + +[XCHAL_INTTYPE_MASK_EXTERN_LEVEL] +Integer = 2411606847 + +[XCHAL_EXTINT20_NUM] +Integer = 25 + +[XCHAL_DCACHE_ECC_PARITY] +Integer = 0 + +[XCHAL_NUM_DATAROM] +Integer = 1 + +[XCHAL_INTLEVEL7_ANDBELOW_MASK] +Integer = 4294967295 + +[XCHAL_NMI_INTERRUPT] +Integer = 14 + +[XCHAL_INT2_EXTNUM] +Integer = 2 + +[XCHAL_HAVE_XEAX] +Integer = 0 + +[XCHAL_ICACHE_SETWIDTH] +Integer = 0 + +[XCHAL_INSTRAM1_PADDR] +Integer = 1077936128 + +[XCHAL_HW_MIN_VERSION_MINOR] +Integer = 3 + +[XCHAL_INT13_LEVEL] +Integer = 1 + +[XCHAL_TIMER1_INTERRUPT] +Integer = 15 + +[XCHAL_EXTINT23_NUM] +Integer = 28 + +[XCHAL_INT12_EXTNUM] +Integer = 9 + +[XCHAL_INT27_EXTNUM] +Integer = 22 + +[XCHAL_WINDOW_UF4_VECOFS] +Integer = 64 + +[XCHAL_WINDOW_VECTORS_PADDR] +Integer = 1073741824 + +[XCHAL_HAVE_MUL32_HIGH] +Integer = 1 + +[XCHAL_UNALIGNED_STORE_HW] +Integer = 1 + +[XCHAL_INTLEVEL5_VECTOR_VADDR] +Integer = 1073742400 + +[XCHAL_EXTINT11_NUM] +Integer = 14 + +[XCHAL_INTLEVEL6_VECOFS] +Integer = 640 + +[XCHAL_EXTINT1_NUM] +Integer = 1 + +[XCHAL_HAVE_ADDX] +Integer = 1 + +[XCHAL_HAVE_FUSION_SOFTDEMAP] +Integer = 0 + +[XCHAL_HAVE_BSP3] +Integer = 0 + +[XCHAL_HAVE_PIF_WR_RESP] +Integer = 0 + +[XCHAL_NUM_PERF_COUNTERS] +Integer = 2 + +[XCHAL_HAVE_FP_RSQRT] +Integer = 1 + +[XCHAL_MMU_RING_BITS] +Integer = 0 + +[XCHAL_HW_MIN_VERSION] +Integer = 260003 + +[XCHAL_HAVE_HIFIPRO] +Integer = 0 + +[XCHAL_INT0_LEVEL] +Integer = 1 + +[XCHAL_HAVE_IDENTITY_MAP] +Integer = 1 + +[XCHAL_INT8_EXTNUM] +Integer = 6 + +[XCHAL_INT10_EXTNUM] +Integer = 8 + +[XCHAL_INT15_TYPE] +Interrupt = "Timer" + +[XCHAL_EXTINT5_NUM] +Integer = 5 + +[XCHAL_HAVE_EXCEPTIONS] +Integer = 1 + +[XCHAL_NUM_DATARAM] +Integer = 2 + +[XCHAL_HAVE_PSO] +Integer = 0 + +[XCHAL_HW_MIN_VERSION_MAJOR] +Integer = 2600 + +[XCHAL_DATARAM1_ECC_PARITY] +Integer = 0 + +[XCHAL_HAVE_FP_DIV] +Integer = 1 + +[XCHAL_INT16_TYPE] +Interrupt = "Timer" + +[XCHAL_EXTINT4_NUM] +Integer = 4 + +[XCHAL_WINDOW_OF4_VECOFS] +Integer = 0 + +[XCHAL_INTLEVEL4_VECTOR_VADDR] +Integer = 1073742336 + +[XCHAL_HAVE_USER_DPFPU] +Integer = 0 + +[XCHAL_UNALIGNED_LOAD_EXCEPTION] +Integer = 0 + +[XCHAL_INST_FETCH_WIDTH] +Integer = 4 + +[XCHAL_HAVE_VECTORFPU2005] +Integer = 0 + +[XCHAL_INT20_EXTNUM] +Integer = 15 + +[XCHAL_KERNEL_VECTOR_VADDR] +Integer = 1073742592 + +[XCHAL_INT21_TYPE] +Interrupt = "ExternLevel" + +[XCHAL_WINDOW_OF8_VECOFS] +Integer = 128 + +[XCHAL_DATAROM0_SIZE] +Integer = 4194304 + +[XCHAL_HAVE_ABSOLUTE_LITERALS] +Integer = 0 + +[XCHAL_ICACHE_SIZE] +Integer = 0 + +[XCHAL_DCACHE_SIZE] +Integer = 0 + +[XCHAL_DATARAM0_PADDR] +Integer = 1073217536 + +[XCHAL_INT0_TYPE] +Interrupt = "ExternLevel" + +[XCHAL_CLOCK_GATING_FUNCUNIT] +Integer = 1 + +[XCHAL_KERNEL_VECTOR_PADDR] +Integer = 1073742592 + +[XCHAL_NUM_INTLEVELS] +Integer = 6 + +[XCHAL_HAVE_ICACHE_TEST] +Integer = 0 + +[XCHAL_INTLEVEL5_VECTOR_PADDR] +Integer = 1073742400 + +[XCHAL_DEBUG_VECOFS] +Integer = 640 + +[XCHAL_NMI_VECOFS] +Integer = 704 + +[XCHAL_HAVE_OCD_DIR_ARRAY] +Integer = 0 + +[XCHAL_HAVE_TLBS] +Integer = 1 + +[XCHAL_NMILEVEL] +Integer = 7 + +[XCHAL_HAVE_S32C1I] +Integer = 1 + +[XCHAL_INSTRAM1_ECC_PARITY] +Integer = 0 + +[XCHAL_TRAX_MEM_SHAREABLE] +Integer = 1 + +[XCHAL_HAVE_PIF_REQ_ATTR] +Integer = 0 + +[XCHAL_DATA_WIDTH] +Integer = 4 + +[XCHAL_INT24_EXTNUM] +Integer = 19 + +[XCHAL_INTLEVEL7_VECOFS] +Integer = 704 + +[XCHAL_EXTINT3_NUM] +Integer = 3 + +[XCHAL_EXTINT0_NUM] +Integer = 0 + +[XCHAL_TRAX_ATB_WIDTH] +Integer = 32 + +[XCHAL_DATARAM1_BANKS] +Integer = 1 + +[XCHAL_HAVE_MIMIC_CACHEATTR] +Integer = 1 + +[XCHAL_INT11_LEVEL] +Integer = 3 + +[XCHAL_INT22_EXTNUM] +Integer = 17 + +[XCHAL_HAVE_MUL32] +Integer = 1 + +[XCHAL_HAVE_MX] +Integer = 0 + +[XCHAL_NUM_URAM] +Integer = 0 + +[XCHAL_HAVE_DEPBITS] +Integer = 0 + +[XCHAL_HW_MAX_VERSION_MINOR] +Integer = 3 + +[XCHAL_DEBUGLEVEL] +Integer = 6 + +[XCHAL_EXTINT2_NUM] +Integer = 2 + +[XCHAL_EXTINT12_NUM] +Integer = 17 + +[XCHAL_EXTINT15_NUM] +Integer = 20 + +[XCHAL_HAVE_HIFI4_VFPU] +Integer = 0 + +[XCHAL_HAVE_MAC16] +Integer = 1 + +[XCHAL_HAVE_AXI] +Integer = 0 + +[XCHAL_NUM_AREGS] +Integer = 64 + +[XCHAL_HAVE_CONNXD2_DUALLSFLIX] +Integer = 0 + +[XCHAL_INT16_LEVEL] +Integer = 5 + +[XCHAL_EXTINT17_NUM] +Integer = 22 + +[XCHAL_INT26_EXTNUM] +Integer = 21 + +[XCHAL_HAVE_MEM_ECC_PARITY] +Integer = 0 + +[XCHAL_INT21_LEVEL] +Integer = 2 + +[XCHAL_RESET_VECTOR1_VADDR] +Integer = 1073742848 + +[XCHAL_HAVE_CACHE_BLOCKOPS] +Integer = 0 + +[XCHAL_WINDOW_VECTORS_VADDR] +Integer = 1073741824 + +[XCHAL_INTLEVEL2_VECTOR_VADDR] +Integer = 1073742208 + +[XCHAL_NMI_VECTOR_PADDR] +Integer = 1073742528 + +[XCHAL_HAVE_VECTRA1] +Integer = 0 + +[XCHAL_DCACHE_SETWIDTH] +Integer = 0 + +[XCHAL_HAVE_PREFETCH] +Integer = 0 + +[XCHAL_INT4_LEVEL] +Integer = 1 + +[XCHAL_INT12_LEVEL] +Integer = 1 + +[XCHAL_LOOP_BUFFER_SIZE] +Integer = 256 + +[XCHAL_WINDOW_UF12_VECOFS] +Integer = 320 + +[XCHAL_NUM_INTERRUPTS_LOG2] +Integer = 5 + +[XCHAL_INT7_TYPE] +Interrupt = "Software" + +[XCHAL_HAVE_USER_SPFPU] +Integer = 0 + +[XCHAL_INTLEVEL6_VECTOR_PADDR] +Integer = 1073742464 + +[XCHAL_INT4_EXTNUM] +Integer = 4 + +[XCHAL_HAVE_PSO_FULL_RETENTION] +Integer = 0 + +[XCHAL_HAVE_XEA2] +Integer = 1 + +[XCHAL_HAVE_PTP_MMU] +Integer = 0 + +[XCHAL_HAVE_FUSION_CONVENC] +Integer = 0 + +[XCHAL_HW_REL_LX6_0_3] +Integer = 1 + +[XCHAL_HAVE_ICACHE_DYN_WAYS] +Integer = 0 + +[XCHAL_INTLEVEL6_MASK] +Integer = 0 + +[XCHAL_HAVE_FUSION_16BIT_BASEBAND] +Integer = 0 + +[XCHAL_HAVE_BBE16_DESPREAD] +Integer = 0 + +[XCHAL_XLMI0_VADDR] +Integer = 1072693248 + +[XCHAL_INT15_LEVEL] +Integer = 3 + +[XCHAL_INT12_TYPE] +Interrupt = "ExternLevel" + +[XCHAL_INTLEVEL7_NUM] +Integer = 14 + +[XCHAL_INT5_TYPE] +Interrupt = "ExternLevel" + +[XCHAL_INT26_TYPE] +Interrupt = "ExternLevel" + +[XCHAL_INTTYPE_MASK_WRITE_ERROR] +Integer = 0 + +[XCHAL_HAVE_DEBUG_JTAG] +Integer = 1 + +[XCHAL_HAVE_WINDOWED] +Integer = 1 + +[XCHAL_HAVE_MP_RUNSTALL] +Integer = 0 + +[XCHAL_NUM_INSTROM] +Integer = 1 + +[XCHAL_DATAROM0_BANKS] +Integer = 1 + +[XCHAL_HAVE_NMI] +Integer = 1 + +[XCHAL_HAVE_HALT] +Integer = 0 + +[XCHAL_NUM_IBREAK] +Integer = 2 + +[XCHAL_TRAX_MEM_SIZE] +Integer = 16384 + +[XCHAL_HW_CONFIGID0] +Integer = 3267166206 + +[XCHAL_INT17_TYPE] +Interrupt = "ExternLevel" + +[XCHAL_PROFILING_INTERRUPT] +Integer = 11 + +[XCHAL_EXTINT22_NUM] +Integer = 27 + +[XCHAL_HW_CONFIGID1] +Integer = 482737814 + +[XCHAL_NUM_INTERRUPTS] +Integer = 32 + +[XCHAL_INT23_LEVEL] +Integer = 3 + +[XCHAL_DCACHE_LINE_LOCKABLE] +Integer = 0 + +[XCHAL_INT21_EXTNUM] +Integer = 16 + +[XCHAL_EXTINT9_NUM] +Integer = 12 + +[XCHAL_NMI_VECTOR_VADDR] +Integer = 1073742528 + +[XCHAL_UNALIGNED_STORE_EXCEPTION] +Integer = 0 + +[XCHAL_HW_VERSION_MAJOR] +Integer = 2600 + +[XCHAL_HAVE_FUSION_AES] +Integer = 0 + +[XCHAL_HAVE_TRAX] +Integer = 1 + +[XCHAL_HAVE_DFP_SQRT] +Integer = 0 + +[XCHAL_HAVE_DENSITY] +Integer = 1 + +[XCHAL_HAVE_MP_INTERRUPTS] +Integer = 0 + +[XCHAL_DATAROM0_ECC_PARITY] +Integer = 0 + +[XCHAL_INT27_LEVEL] +Integer = 3 + +[XCHAL_INT19_EXTNUM] +Integer = 14 + +[XCHAL_VECBASE_RESET_PADDR] +Integer = 1073741824 + +[XCHAL_INT1_EXTNUM] +Integer = 1 + +[XCHAL_HAVE_DEBUG_APB] +Integer = 1 + +[XCHAL_INTLEVEL5_ANDBELOW_MASK] +Integer = 4294950911 + +[XCHAL_INT31_TYPE] +Interrupt = "ExternLevel" + +[XCHAL_INT28_EXTNUM] +Integer = 23 + +[XCHAL_NUM_DBREAK] +Integer = 2 + +[XCHAL_CORE_ID] +String = "esp32_v3_49_prod" + +[XCHAL_HAVE_EXTERN_REGS] +Integer = 1 + +[XCHAL_HAVE_RELEASE_SYNC] +Integer = 1 + +[XCHAL_NUM_EXTINTERRUPTS] +Integer = 26 + +[XCHAL_INT1_TYPE] +Interrupt = "ExternLevel" + +[XCHAL_HAVE_MUL16] +Integer = 1 + +[XCHAL_XLMI0_PADDR] +Integer = 1072693248 + +[XCHAL_INT19_LEVEL] +Integer = 2 + +[XCHAL_NUM_AREGS_LOG2] +Integer = 6 + +[XCHAL_INTLEVEL6_ANDBELOW_MASK] +Integer = 4294950911 + +[XCHAL_INTLEVEL5_MASK] +Integer = 2214658048 + +[XCHAL_EXTINT21_NUM] +Integer = 26 + +[XCHAL_HAVE_BBE16] +Integer = 0 + +[XCHAL_HAVE_HIFI4] +Integer = 0 + +[XCHAL_RESET_VECBASE_OVERLAP] +Integer = 0 + +[XCHAL_HAVE_BBENEP] +Integer = 0 + +[XCHAL_DOUBLEEXC_VECOFS] +Integer = 960 + +[XCHAL_MAX_INSTRUCTION_SIZE] +Integer = 3 + +[XCHAL_DATARAM1_SIZE] +Integer = 4194304 + +[XCHAL_NUM_TIMERS] +Integer = 3 + +[XCHAL_INTLEVEL2_VECOFS] +Integer = 384 + +[XCHAL_ICACHE_WAYS] +Integer = 1 + +[XCHAL_INTLEVEL7_VECTOR_VADDR] +Integer = 1073742528 + +[XCHAL_INT30_LEVEL] +Integer = 4 + +[XCHAL_HAVE_DEBUG_ERI] +Integer = 1 + +[XCHAL_HAVE_DFP_RSQRT] +Integer = 0 + +[XCHAL_INSTRAM0_PADDR] +Integer = 1073741824 + +[XCHAL_INT24_TYPE] +Interrupt = "ExternLevel" + +[XCHAL_HAVE_XEA1] +Integer = 0 + +[XCHAL_HAVE_CONNXD2] +Integer = 0 + +[XCHAL_INT9_LEVEL] +Integer = 1 + +[XCHAL_INT31_LEVEL] +Integer = 5 + +[XCHAL_HAVE_FP] +Integer = 1 + +[XCHAL_INTTYPE_MASK_UNCONFIGURED] +Integer = 0 + +[XCHAL_RESET_VECTOR0_PADDR] +Integer = 1342177280 + +[XCHAL_HW_VERSION_NAME] +String = "LX6.0.3" + +[XCHAL_INTLEVEL6_VECTOR_VADDR] +Integer = 1073742464 + +[XCHAL_HAVE_SPANNING_WAY] +Integer = 1 + +[XCHAL_MMU_RINGS] +Integer = 1 + +[XCHAL_HAVE_DIV32] +Integer = 1 + +[XCHAL_KERNEL_VECOFS] +Integer = 768 + +[XCHAL_HAVE_SSP16_VITERBI] +Integer = 0 + +[XCHAL_HAVE_BBP16] +Integer = 0 + +[XCHAL_HW_REL_LX6_0] +Integer = 1 + +[XCHAL_HW_CONFIGID_RELIABLE] +Integer = 1 + +[XCHAL_HAVE_L32R] +Integer = 1 + +[XCHAL_DATAROM0_VADDR] +Integer = 1061158912 + +[XCHAL_HAVE_INTERRUPTS] +Integer = 1 + +[XCHAL_INT1_LEVEL] +Integer = 1 + +[XCHAL_INT6_LEVEL] +Integer = 1 + +[XCHAL_INT10_TYPE] +Interrupt = "ExternEdge" + +[XCHAL_INTTYPE_MASK_PROFILING] +Integer = 2048 + +[XCHAL_EXCM_LEVEL] +Integer = 3 + +[XCHAL_HAVE_DFPU_SINGLE_DOUBLE] +Integer = 0 + +[XCHAL_DCACHE_WAYS] +Integer = 1 + +[XCHAL_INSTROM0_PADDR] +Integer = 1082130432 + +[XCHAL_INT10_LEVEL] +Integer = 1 + +[XCHAL_INTLEVEL3_VECOFS] +Integer = 448 + +[XCHAL_ICACHE_LINE_LOCKABLE] +Integer = 0 + +[XCHAL_HAVE_FLIX3] +Integer = 0 + +[XCHAL_HAVE_CCOUNT] +Integer = 1 + +[XCHAL_SPANNING_WAY] +Integer = 0 + +[XCHAL_HAVE_FUSION_LOW_POWER] +Integer = 0 + +[XCHAL_INT7_LEVEL] +Integer = 1 + +[XCHAL_EXTINT14_NUM] +Integer = 19 + +[XCHAL_HAVE_FUSION_AVS] +Integer = 0 + +[XCHAL_INT17_EXTNUM] +Integer = 12 + +[XCHAL_INT19_TYPE] +Interrupt = "ExternLevel" + +[XCHAL_NUM_CONTEXTS] +Integer = 1 + +[XCHAL_HAVE_HIFI2EP] +Integer = 0 + +[XCHAL_HAVE_PDX4] +Integer = 0 + +[XCHAL_INT23_EXTNUM] +Integer = 18 + +[XCHAL_DCACHE_IS_WRITEBACK] +Integer = 0 + +[XCHAL_INTLEVEL7_MASK] +Integer = 16384 + +[XCHAL_USER_VECTOR_PADDR] +Integer = 1073742656 + +[XCHAL_INTLEVEL4_ANDBELOW_MASK] +Integer = 2080292863 + +[XCHAL_DATAROM0_PADDR] +Integer = 1061158912 + +[XCHAL_UNALIGNED_LOAD_HW] +Integer = 1 + +[XCHAL_HAVE_WIDE_BRANCHES] +Integer = 0 + +[XCHAL_EXTINT6_NUM] +Integer = 8 + +[XCHAL_HAVE_MINMAX] +Integer = 1 + +[XCHAL_HAVE_OCD_LS32DDR] +Integer = 1 + +[XCHAL_XLMI0_SIZE] +Integer = 524288 + +[XCHAL_WINDOW_UF8_VECOFS] +Integer = 192 + +[XCHAL_MMU_ASID_BITS] +Integer = 0 + +[XCHAL_HAVE_BBE16_VECDIV] +Integer = 0 + +[XCHAL_HAVE_DFP_DIV] +Integer = 0 + +[XCHAL_HAVE_FUSION_VITERBI] +Integer = 0 + +[XCHAL_HAVE_PRID] +Integer = 1 + +[XCHAL_HAVE_HIFI3_VFPU] +Integer = 0 + +[XCHAL_HAVE_BOOLEANS] +Integer = 1 + +[XCHAL_INSTROM0_ECC_PARITY] +Integer = 0 + +[XCHAL_HAVE_FP_RECIP] +Integer = 1 + +[XCHAL_INT2_LEVEL] +Integer = 1 + +[XCHAL_INT13_TYPE] +Interrupt = "ExternLevel" + +[XCHAL_HAVE_PREFETCH_L1] +Integer = 0 + +[XCHAL_TIMER2_INTERRUPT] +Integer = 16 + +[XCHAL_HAVE_PSO_CDM] +Integer = 0 + +[XCHAL_DCACHE_BANKS] +Integer = 0 + +[XCHAL_HAVE_SEXT] +Integer = 1 + +[XCHAL_INSTRAM0_SIZE] +Integer = 4194304 + +[XCHAL_HAVE_CLAMPS] +Integer = 1 + +[XCHAL_DCACHE_LINESIZE] +Integer = 4 + +[XCHAL_INT2_TYPE] +Interrupt = "ExternLevel" + +[XCHAL_HAVE_VECBASE] +Integer = 1 + +[XCHAL_HAVE_NSA] +Integer = 1 + +[XCHAL_INSTROM0_VADDR] +Integer = 1082130432 + +[XCHAL_WINDOW_OF12_VECOFS] +Integer = 256 + +[XCHAL_DEBUG_VECTOR_VADDR] +Integer = 1073742464 + +[XCHAL_HAVE_HIFI2] +Integer = 0 + +[XCHAL_HAVE_CONST16] +Integer = 0 + +[XCHAL_INT18_LEVEL] +Integer = 1 + +[XCHAL_DCACHE_LINEWIDTH] +Integer = 2 + +[XCHAL_INT25_TYPE] +Interrupt = "ExternLevel" + +[XCHAL_HAVE_LOOPS] +Integer = 1 + +[XCHAL_HW_MAX_VERSION] +Integer = 260003 + +[XCHAL_HAVE_CACHEATTR] +Integer = 0 diff --git a/xtensa-lx-rt/config/xtensa_esp32s2.toml b/xtensa-lx-rt/config/xtensa_esp32s2.toml new file mode 100644 index 000000000..76be1e2ef --- /dev/null +++ b/xtensa-lx-rt/config/xtensa_esp32s2.toml @@ -0,0 +1,1475 @@ +[XCHAL_DATARAM1_SIZE] +Integer = 4194304 + +[XCHAL_INT5_TYPE] +Interrupt = "ExternLevel" + +[XCHAL_INTLEVEL6_VECTOR_PADDR] +Integer = 1073742464 + +[XCHAL_INTTYPE_MASK_WRITE_ERROR] +Integer = 0 + +[XCHAL_HAVE_PREFETCH] +Integer = 0 + +[XCHAL_INTLEVEL3_MASK] +Integer = 683706368 + +[XCHAL_EXTINT21_NUM] +Integer = 26 + +[XCHAL_RESET_VECTOR0_PADDR] +Integer = 1342177280 + +[XCHAL_INSTRAM1_VADDR] +Integer = 1077936128 + +[XCHAL_EXTINT4_NUM] +Integer = 4 + +[XCHAL_EXTINT19_NUM] +Integer = 24 + +[XCHAL_XLMI0_PADDR] +Integer = 1061158912 + +[XCHAL_INT7_TYPE] +Interrupt = "Software" + +[XCHAL_HAVE_FP] +Integer = 0 + +[XCHAL_EXTINT6_NUM] +Integer = 8 + +[XCHAL_EXTINT18_NUM] +Integer = 23 + +[XCHAL_DATAROM0_BANKS] +Integer = 1 + +[XCHAL_INT11_LEVEL] +Integer = 3 + +[XCHAL_RESET_VECTOR_PADDR] +Integer = 1073742848 + +[XCHAL_HAVE_PDX16] +Integer = 0 + +[XCHAL_INTLEVEL7_ANDBELOW_MASK] +Integer = 4294967295 + +[XCHAL_EXTINT2_NUM] +Integer = 2 + +[XCHAL_MPU_BG_CACHEADRDIS] +Integer = 0 + +[XCHAL_MPU_BACKGROUND_ENTRIES] +Integer = 0 + +[XCHAL_INT22_TYPE] +Interrupt = "ExternEdge" + +[XCHAL_RESET_VECTOR1_VADDR] +Integer = 1073742848 + +[XCHAL_INTLEVEL2_VECTOR_PADDR] +Integer = 1073742208 + +[XCHAL_HAVE_RELEASE_SYNC] +Integer = 1 + +[XCHAL_VISION_SIMD16] +Integer = 0 + +[XCHAL_HAVE_PREDICTED_BRANCHES] +Integer = 0 + +[XCHAL_MMU_RINGS] +Integer = 1 + +[XCHAL_HAVE_PTP_MMU] +Integer = 0 + +[XCHAL_EXTINT14_NUM] +Integer = 19 + +[XCHAL_INTLEVEL7_MASK] +Integer = 16384 + +[XCHAL_INT8_EXTNUM] +Integer = 6 + +[XCHAL_DATAROM0_VADDR] +Integer = 1056964608 + +[XCHAL_NUM_INTERRUPTS] +Integer = 32 + +[XCHAL_HAVE_MIMIC_CACHEATTR] +Integer = 1 + +[XCHAL_INTLEVEL3_VECOFS] +Integer = 448 + +[XCHAL_RESET_VECTOR_VADDR] +Integer = 1073742848 + +[XCHAL_HAVE_MUL32_HIGH] +Integer = 1 + +[XCHAL_MPU_ALIGN] +Integer = 0 + +[XCHAL_HAVE_CACHE_BLOCKOPS] +Integer = 0 + +[XCHAL_HAVE_PIF_WR_RESP] +Integer = 0 + +[XCHAL_DCACHE_ACCESS_SIZE] +Integer = 1 + +[XCHAL_DOUBLEEXC_VECOFS] +Integer = 960 + +[XCHAL_INT30_EXTNUM] +Integer = 24 + +[XCHAL_SW_VERSION] +Integer = 1200009 + +[XCHAL_INT4_LEVEL] +Integer = 1 + +[XCHAL_INT20_LEVEL] +Integer = 2 + +[XCHAL_MPU_ALIGN_BITS] +Integer = 0 + +[XCHAL_INTLEVEL5_VECOFS] +Integer = 576 + +[XCHAL_HAVE_BBENEP_SP_VFPU] +Integer = 0 + +[XCHAL_INT14_EXTNUM] +Integer = 11 + +[XCHAL_INT30_LEVEL] +Integer = 4 + +[XCHAL_INT1_LEVEL] +Integer = 1 + +[XCHAL_DOUBLEEXC_VECTOR_PADDR] +Integer = 1073742784 + +[XCHAL_HAVE_HIFI2EP] +Integer = 0 + +[XCHAL_INT27_EXTNUM] +Integer = 22 + +[XCHAL_HAVE_USER_DPFPU] +Integer = 0 + +[XCHAL_HAVE_SSP16] +Integer = 0 + +[XCHAL_HAVE_HIFI4_VFPU] +Integer = 0 + +[XCHAL_HAVE_MUL32] +Integer = 1 + +[XCHAL_EXTINT20_NUM] +Integer = 25 + +[XCHAL_INT9_EXTNUM] +Integer = 7 + +[XCHAL_INTLEVEL7_VECOFS] +Integer = 704 + +[XCHAL_HAVE_CONST16] +Integer = 0 + +[XCHAL_ICACHE_LINESIZE] +Integer = 4 + +[XCHAL_HAVE_TURBO16] +Integer = 0 + +[XCHAL_HAVE_MAC16] +Integer = 0 + +[XCHAL_HAVE_DCACHE_TEST] +Integer = 0 + +[XCHAL_EXTINT0_NUM] +Integer = 0 + +[XCHAL_WINDOW_OF12_VECOFS] +Integer = 256 + +[XCHAL_DCACHE_BANKS] +Integer = 0 + +[XCHAL_INT11_TYPE] +Interrupt = "Profiling" + +[XCHAL_UNALIGNED_LOAD_EXCEPTION] +Integer = 0 + +[XCHAL_INT19_EXTNUM] +Integer = 14 + +[XCHAL_CLOCK_GATING_GLOBAL] +Integer = 0 + +[XCHAL_XLMI0_ECC_PARITY] +Integer = 0 + +[XCHAL_EXTINT13_NUM] +Integer = 18 + +[XCHAL_RESET_VECTOR1_PADDR] +Integer = 1073742848 + +[XCHAL_INSTROM0_VADDR] +Integer = 1082130432 + +[XCHAL_NUM_PERF_COUNTERS] +Integer = 2 + +[XCHAL_HAVE_BBE16] +Integer = 0 + +[XCHAL_ICACHE_LINEWIDTH] +Integer = 2 + +[XCHAL_HAVE_DIV32] +Integer = 1 + +[XCHAL_NUM_AREGS] +Integer = 64 + +[XCHAL_INT3_TYPE] +Interrupt = "ExternLevel" + +[XCHAL_INT12_LEVEL] +Integer = 1 + +[XCHAL_INT18_EXTNUM] +Integer = 13 + +[XCHAL_HAVE_CACHEATTR] +Integer = 0 + +[XCHAL_MPU_ALIGN_REQ] +Integer = 1 + +[XCHAL_HAVE_PREFETCH_L1] +Integer = 0 + +[XCHAL_HAVE_HIFI4] +Integer = 0 + +[XCHAL_HAVE_HIFI2] +Integer = 0 + +[XCHAL_NUM_EXTINTERRUPTS] +Integer = 26 + +[XCHAL_USER_VECTOR_PADDR] +Integer = 1073742656 + +[XCHAL_HAVE_DFP_DIV] +Integer = 0 + +[XCHAL_INTLEVEL2_MASK] +Integer = 3670016 + +[XCHAL_HAVE_TAP_MASTER] +Integer = 0 + +[XCHAL_ICACHE_SETWIDTH] +Integer = 0 + +[XCHAL_HAVE_FUSION_VITERBI] +Integer = 0 + +[XCHAL_HW_VERSION_MAJOR] +Integer = 2700 + +[XCHAL_INT9_LEVEL] +Integer = 1 + +[XCHAL_NMI_VECOFS] +Integer = 704 + +[XCHAL_TRAX_MEM_SIZE] +Integer = 16384 + +[XCHAL_INSTRAM0_HAVE_IDMA] +Integer = 0 + +[XCHAL_EXTINT22_NUM] +Integer = 27 + +[XCHAL_HAVE_PDX4] +Integer = 0 + +[XCHAL_HAVE_FP_RECIP] +Integer = 0 + +[XCHAL_DCACHE_SIZE] +Integer = 0 + +[XCHAL_INT30_TYPE] +Interrupt = "ExternEdge" + +[XCHAL_INT15_TYPE] +Interrupt = "Timer" + +[XCHAL_XEA_VERSION] +Integer = 2 + +[XCHAL_HAVE_HALT] +Integer = 0 + +[XCHAL_TRAX_MEM_SHAREABLE] +Integer = 1 + +[XCHAL_MPU_ENTRIES] +Integer = 0 + +[XCHAL_DATARAM0_BANKS] +Integer = 1 + +[XCHAL_HW_REL_LX7_0_9] +Integer = 1 + +[XCHAL_HAVE_HIFI3] +Integer = 0 + +[XCHAL_VISION_QUAD_MAC_TYPE] +Integer = 0 + +[XCHAL_INT6_TYPE] +Interrupt = "Timer" + +[XCHAL_HAVE_HIFI3Z_VFPU] +Integer = 0 + +[XCHAL_HAVE_XLT_CACHEATTR] +Integer = 0 + +[XCHAL_HAVE_IDMA_TRANSPOSE] +Integer = 0 + +[XCHAL_WINDOW_OF8_VECOFS] +Integer = 128 + +[XCHAL_CP_MAXCFG] +Integer = 8 + +[XCHAL_HAVE_ACELITE] +Integer = 0 + +[XCHAL_DATAROM0_SIZE] +Integer = 4194304 + +[XCHAL_INTLEVEL5_MASK] +Integer = 2214658048 + +[XCHAL_HAVE_CCOUNT] +Integer = 1 + +[XCHAL_DCACHE_IS_WRITEBACK] +Integer = 0 + +[XCHAL_HW_VERSION] +Integer = 270009 + +[XCHAL_INTLEVEL5_VECTOR_PADDR] +Integer = 1073742400 + +[XCHAL_INT27_TYPE] +Interrupt = "ExternLevel" + +[XCHAL_INT13_LEVEL] +Integer = 1 + +[XCHAL_HAVE_ICACHE_TEST] +Integer = 0 + +[XCHAL_INTLEVEL4_VECOFS] +Integer = 512 + +[XCHAL_HAVE_FUSION] +Integer = 0 + +[XCHAL_INT1_EXTNUM] +Integer = 1 + +[XCHAL_INTLEVEL2_VECTOR_VADDR] +Integer = 1073742208 + +[XCHAL_DCACHE_LINESIZE] +Integer = 4 + +[XCHAL_HAVE_PSO_FULL_RETENTION] +Integer = 0 + +[XCHAL_HAVE_CONNXD2_DUALLSFLIX] +Integer = 0 + +[XCHAL_INSTRAM0_VADDR] +Integer = 1073741824 + +[XCHAL_NUM_INSTROM] +Integer = 1 + +[XCHAL_EXCM_LEVEL] +Integer = 3 + +[XCHAL_INTTYPE_MASK_EXTERN_LEVEL] +Integer = 2411606847 + +[XCHAL_RESET_VECBASE_OVERLAP] +Integer = 0 + +[XCHAL_DATA_WIDTH] +Integer = 4 + +[XCHAL_EXTINT23_NUM] +Integer = 28 + +[XCHAL_TRAX_ATB_WIDTH] +Integer = 0 + +[XCHAL_HW_REL_LX7] +Integer = 1 + +[XCHAL_DATARAM0_ECC_PARITY] +Integer = 0 + +[XCHAL_EXTINT5_NUM] +Integer = 5 + +[XCHAL_INT31_LEVEL] +Integer = 5 + +[XCHAL_HAVE_VISION_HISTOGRAM] +Integer = 0 + +[XCHAL_INT14_TYPE] +Interrupt = "Nmi" + +[XCHAL_HAVE_MP_RUNSTALL] +Integer = 0 + +[XCHAL_DEBUG_VECTOR_PADDR] +Integer = 1073742464 + +[XCHAL_NMI_VECTOR_VADDR] +Integer = 1073742528 + +[XCHAL_HAVE_WINDOWED] +Integer = 1 + +[XCHAL_INT4_TYPE] +Interrupt = "ExternLevel" + +[XCHAL_HAVE_DFP_ACCEL] +Integer = 0 + +[XCHAL_HW_VERSION_MINOR] +Integer = 9 + +[XCHAL_HW_MAX_VERSION] +Integer = 270009 + +[XCHAL_HAVE_AXI_ECC] +Integer = 0 + +[XCHAL_UNALIGNED_LOAD_HW] +Integer = 1 + +[XCHAL_MMU_RING_BITS] +Integer = 0 + +[XCHAL_INT5_EXTNUM] +Integer = 5 + +[XCHAL_HW_MIN_VERSION] +Integer = 270009 + +[XCHAL_TRAX_TIME_WIDTH] +Integer = 0 + +[XCHAL_HAVE_DFPU_SINGLE_ONLY] +Integer = 0 + +[XCHAL_SPANNING_WAY] +Integer = 0 + +[XCHAL_RESET_VECTOR0_VADDR] +Integer = 1342177280 + +[XCHAL_INTTYPE_MASK_SOFTWARE] +Integer = 536871040 + +[XCHAL_INT17_TYPE] +Interrupt = "ExternLevel" + +[XCHAL_INTTYPE_MASK_IDMA_ERR] +Integer = 0 + +[XCHAL_EXTINT17_NUM] +Integer = 22 + +[XCHAL_USER_VECTOR_VADDR] +Integer = 1073742656 + +[XCHAL_HAVE_DEBUG_ERI] +Integer = 1 + +[XCHAL_HAVE_DENSITY] +Integer = 1 + +[XCHAL_DEBUG_VECTOR_VADDR] +Integer = 1073742464 + +[XCHAL_INT25_LEVEL] +Integer = 4 + +[XCHAL_WINDOW_UF4_VECOFS] +Integer = 64 + +[XCHAL_NUM_DATARAM] +Integer = 2 + +[XCHAL_HAVE_DFP_RSQRT] +Integer = 0 + +[XCHAL_HAVE_AXI] +Integer = 0 + +[XCHAL_INT2_LEVEL] +Integer = 1 + +[XCHAL_INT19_TYPE] +Interrupt = "ExternLevel" + +[XCHAL_DATARAM0_VADDR] +Integer = 1069547520 + +[XCHAL_HAVE_BOOTLOADER] +Integer = 0 + +[XCHAL_HAVE_OCD_LS32DDR] +Integer = 1 + +[XCHAL_HAVE_FLIX3] +Integer = 0 + +[XCHAL_NUM_DATAROM] +Integer = 1 + +[XCHAL_INSTRAM1_PADDR] +Integer = 1077936128 + +[XCHAL_PROFILING_INTERRUPT] +Integer = 11 + +[XCHAL_INT28_EXTNUM] +Integer = 23 + +[XCHAL_NUM_TIMERS] +Integer = 3 + +[XCHAL_EXTINT9_NUM] +Integer = 12 + +[XCHAL_INTLEVEL7_VECTOR_VADDR] +Integer = 1073742528 + +[XCHAL_INT22_EXTNUM] +Integer = 17 + +[XCHAL_INT23_TYPE] +Interrupt = "ExternLevel" + +[XCHAL_INT25_TYPE] +Interrupt = "ExternLevel" + +[XCHAL_INTTYPE_MASK_PROFILING] +Integer = 2048 + +[XCHAL_HAVE_THREADPTR] +Integer = 1 + +[XCHAL_VISION_TYPE] +Integer = 0 + +[XCHAL_EXTINT15_NUM] +Integer = 20 + +[XCHAL_HAVE_BE] +Integer = 0 + +[XCHAL_HAVE_SPECULATION] +Integer = 0 + +[XCHAL_DATARAM1_PADDR] +Integer = 1065353216 + +[XCHAL_INTTYPE_MASK_TIMER] +Integer = 98368 + +[XCHAL_INT29_LEVEL] +Integer = 3 + +[XCHAL_DCACHE_IS_COHERENT] +Integer = 0 + +[XCHAL_HAVE_BBE16_DESPREAD] +Integer = 0 + +[XCHAL_INSTRAM0_PADDR] +Integer = 1073741824 + +[XCHAL_TIMER2_INTERRUPT] +Integer = 16 + +[XCHAL_HAVE_FUSION_16BIT_BASEBAND] +Integer = 0 + +[XCHAL_ICACHE_ACCESS_SIZE] +Integer = 1 + +[XCHAL_INT21_LEVEL] +Integer = 2 + +[XCHAL_INTLEVEL3_VECTOR_VADDR] +Integer = 1073742272 + +[XCHAL_HAVE_HIFIPRO] +Integer = 0 + +[XCHAL_HAVE_SPANNING_WAY] +Integer = 1 + +[XCHAL_DATARAM1_HAVE_IDMA] +Integer = 0 + +[XCHAL_INT31_TYPE] +Interrupt = "ExternLevel" + +[XCHAL_HAVE_FUSION_LFSR_CRC] +Integer = 0 + +[XCHAL_HAVE_FUSIONG_DP_VFPU] +Integer = 0 + +[XCHAL_MAX_INSTRUCTION_SIZE] +Integer = 3 + +[XCHAL_INT0_LEVEL] +Integer = 1 + +[XCHAL_HW_CONFIGID_RELIABLE] +Integer = 1 + +[XCHAL_HAVE_DFP_accel] +Integer = 0 + +[XCHAL_HAVE_MINMAX] +Integer = 1 + +[XCHAL_HAVE_VECBASE] +Integer = 1 + +[XCHAL_WINDOW_VECTORS_VADDR] +Integer = 1073741824 + +[XCHAL_INTLEVEL5_ANDBELOW_MASK] +Integer = 4294950911 + +[XCHAL_INT15_LEVEL] +Integer = 3 + +[XCHAL_INT18_TYPE] +Interrupt = "ExternLevel" + +[XCHAL_HAVE_WIDE_BRANCHES] +Integer = 0 + +[XCHAL_EXTINT3_NUM] +Integer = 3 + +[XCHAL_ICACHE_LINE_LOCKABLE] +Integer = 0 + +[XCHAL_DATARAM0_HAVE_IDMA] +Integer = 0 + +[XCHAL_INSTROM0_PADDR] +Integer = 1082130432 + +[XCHAL_DATARAM1_VADDR] +Integer = 1065353216 + +[XCHAL_HAVE_BBENEP] +Integer = 0 + +[XCHAL_INTLEVEL1_ANDBELOW_MASK] +Integer = 407551 + +[XCHAL_EXTINT11_NUM] +Integer = 14 + +[XCHAL_DOUBLEEXC_VECTOR_VADDR] +Integer = 1073742784 + +[XCHAL_HAVE_PDX] +Integer = 0 + +[XCHAL_HAVE_EXTERN_REGS] +Integer = 1 + +[XCHAL_HAVE_DATARAM0] +Integer = 1 + +[XCHAL_ICACHE_WAYS] +Integer = 1 + +[XCHAL_INT26_LEVEL] +Integer = 5 + +[XCHAL_INT20_TYPE] +Interrupt = "ExternLevel" + +[XCHAL_INSTRAM1_SIZE] +Integer = 4194304 + +[XCHAL_HAVE_XEA1] +Integer = 0 + +[XCHAL_EXTINT16_NUM] +Integer = 21 + +[XCHAL_HAVE_ABS] +Integer = 1 + +[XCHAL_INT28_LEVEL] +Integer = 4 + +[XCHAL_WINDOW_OF4_VECOFS] +Integer = 0 + +[XCHAL_HAVE_HIGHPRI_INTERRUPTS] +Integer = 1 + +[XCHAL_HAVE_BSP3] +Integer = 0 + +[XCHAL_INT22_LEVEL] +Integer = 3 + +[XCHAL_HAVE_FUSIONG3] +Integer = 0 + +[XCHAL_HAVE_ICACHE_DYN_WAYS] +Integer = 0 + +[XCHAL_INTLEVEL1_MASK] +Integer = 407551 + +[XCHAL_NUM_XLMI] +Integer = 1 + +[XCHAL_HAVE_FP_SQRT] +Integer = 0 + +[XCHAL_INTLEVEL2_VECOFS] +Integer = 384 + +[XCHAL_DATARAM1_ECC_PARITY] +Integer = 0 + +[XCHAL_INT6_LEVEL] +Integer = 1 + +[XCHAL_NMI_VECTOR_PADDR] +Integer = 1073742528 + +[XCHAL_HAVE_PDX8] +Integer = 0 + +[XCHAL_HAVE_FP_RSQRT] +Integer = 0 + +[XCHAL_HAVE_MUL16] +Integer = 1 + +[XCHAL_DATARAM0_SIZE] +Integer = 4194304 + +[XCHAL_HAVE_DEBUG_JTAG] +Integer = 1 + +[XCHAL_INTLEVEL3_VECTOR_PADDR] +Integer = 1073742272 + +[XCHAL_INTLEVEL3_ANDBELOW_MASK] +Integer = 687783935 + +[XCHAL_HAVE_MPU] +Integer = 0 + +[XCHAL_INT7_LEVEL] +Integer = 1 + +[XCHAL_HAVE_FUSIONG6] +Integer = 0 + +[XCHAL_HW_REL_LX7_0] +Integer = 1 + +[XCHAL_INT24_TYPE] +Interrupt = "ExternLevel" + +[XCHAL_HAVE_VISION_HP_VFPU] +Integer = 0 + +[XCHAL_INTLEVEL6_VECOFS] +Integer = 640 + +[XCHAL_DEBUGLEVEL] +Integer = 6 + +[XCHAL_INTTYPE_MASK_GS_ERR] +Integer = 0 + +[XCHAL_ICACHE_SIZE] +Integer = 0 + +[XCHAL_CLOCK_GATING_FUNCUNIT] +Integer = 0 + +[XCHAL_HAVE_HIFI5_VFPU] +Integer = 0 + +[XCHAL_INT16_LEVEL] +Integer = 5 + +[XCHAL_HAVE_DFPU_SINGLE_DOUBLE] +Integer = 0 + +[XCHAL_HAVE_S32C1I] +Integer = 0 + +[XCHAL_INT10_TYPE] +Interrupt = "ExternEdge" + +[XCHAL_HAVE_MEM_ECC_PARITY] +Integer = 0 + +[XCHAL_NUM_DBREAK] +Integer = 2 + +[XCHAL_DATAROM0_ECC_PARITY] +Integer = 0 + +[XCHAL_INTLEVEL7_NUM] +Integer = 14 + +[XCHAL_INT3_LEVEL] +Integer = 1 + +[XCHAL_HAVE_HIFI3Z] +Integer = 0 + +[XCHAL_HAVE_GRIVPEP_HISTOGRAM] +Integer = 0 + +[XCHAL_HW_MIN_VERSION_MAJOR] +Integer = 2700 + +[XCHAL_INT17_LEVEL] +Integer = 1 + +[XCHAL_HAVE_DEBUG] +Integer = 1 + +[XCHAL_UNALIGNED_STORE_EXCEPTION] +Integer = 0 + +[XCHAL_HAVE_VISION_SP_VFPU] +Integer = 0 + +[XCHAL_HAVE_NMI] +Integer = 1 + +[XCHAL_INT2_EXTNUM] +Integer = 2 + +[XCHAL_HAVE_FUSION_FP] +Integer = 0 + +[XCHAL_HAVE_VECTORFPU2005] +Integer = 0 + +[XCHAL_NMI_INTERRUPT] +Integer = 14 + +[XCHAL_HAVE_IMEM_LOADSTORE] +Integer = 1 + +[XCHAL_INTLEVEL4_ANDBELOW_MASK] +Integer = 2080292863 + +[XCHAL_EXTINT10_NUM] +Integer = 13 + +[XCHAL_INT10_LEVEL] +Integer = 1 + +[XCHAL_HAVE_ADDX] +Integer = 1 + +[XCHAL_HAVE_HIFI5] +Integer = 0 + +[XCHAL_NUM_INTERRUPTS_LOG2] +Integer = 5 + +[XCHAL_EXTINT24_NUM] +Integer = 30 + +[XCHAL_HW_MAX_VERSION_MAJOR] +Integer = 2700 + +[XCHAL_EXTINT7_NUM] +Integer = 9 + +[XCHAL_INT3_EXTNUM] +Integer = 3 + +[XCHAL_INT27_LEVEL] +Integer = 3 + +[XCHAL_HAVE_VECTOR_SELECT] +Integer = 1 + +[XCHAL_INT20_EXTNUM] +Integer = 15 + +[XCHAL_HAVE_CLAMPS] +Integer = 1 + +[XCHAL_EXTINT8_NUM] +Integer = 10 + +[XCHAL_LOOP_BUFFER_SIZE] +Integer = 0 + +[XCHAL_HAVE_DFP] +Integer = 0 + +[XCHAL_DCACHE_ECC_PARITY] +Integer = 0 + +[XCHAL_NUM_URAM] +Integer = 0 + +[XCHAL_INT4_EXTNUM] +Integer = 4 + +[XCHAL_INTLEVEL6_ANDBELOW_MASK] +Integer = 4294950911 + +[XCHAL_HW_CONFIGID1] +Integer = 575113137 + +[XCHAL_HAVE_DEPBITS] +Integer = 0 + +[XCHAL_INTTYPE_MASK_IDMA_DONE] +Integer = 0 + +[XCHAL_FUSIONG_SIMD32] +Integer = 0 + +[XCHAL_HAVE_L32R] +Integer = 1 + +[XCHAL_INT24_LEVEL] +Integer = 4 + +[XCHAL_HW_VERSION_NAME] +String = "LX7.0.9" + +[XCHAL_INT12_EXTNUM] +Integer = 9 + +[XCHAL_HAVE_HIFI_MINI] +Integer = 0 + +[XCHAL_INT29_TYPE] +Interrupt = "Software" + +[XCHAL_INST_FETCH_WIDTH] +Integer = 4 + +[XCHAL_HAVE_BBE16_VECDIV] +Integer = 0 + +[XCHAL_XLMI0_SIZE] +Integer = 4194304 + +[XCHAL_INT1_TYPE] +Interrupt = "ExternLevel" + +[XCHAL_INSTROM0_ECC_PARITY] +Integer = 0 + +[XCHAL_ICACHE_ECC_PARITY] +Integer = 0 + +[XCHAL_INTTYPE_MASK_UNCONFIGURED] +Integer = 0 + +[XCHAL_NUM_MISC_REGS] +Integer = 4 + +[XCHAL_HAVE_VECTRALX] +Integer = 0 + +[XCHAL_KERNEL_VECTOR_VADDR] +Integer = 1073742592 + +[XCHAL_INT10_EXTNUM] +Integer = 8 + +[XCHAL_HAVE_BSP3_TRANSPOSE] +Integer = 0 + +[XCHAL_PREFETCH_CASTOUT_LINES] +Integer = 0 + +[XCHAL_HAVE_XEA2] +Integer = 1 + +[XCHAL_HAVE_OCD] +Integer = 1 + +[XCHAL_DATA_PIPE_DELAY] +Integer = 2 + +[XCHAL_HAVE_INSTRAM0] +Integer = 1 + +[XCHAL_BUILD_UNIQUE_ID] +Integer = 493489 + +[XCHAL_NMILEVEL] +Integer = 7 + +[XCHAL_HAVE_CONNXD2] +Integer = 0 + +[XCHAL_INT0_EXTNUM] +Integer = 0 + +[XCHAL_DCACHE_LINE_LOCKABLE] +Integer = 0 + +[XCHAL_HAVE_PSO] +Integer = 0 + +[XCHAL_HW_MIN_VERSION_MINOR] +Integer = 9 + +[XCHAL_INT26_TYPE] +Interrupt = "ExternLevel" + +[XCHAL_HAVE_PSO_CDM] +Integer = 0 + +[XCHAL_VECBASE_RESET_PADDR] +Integer = 1073741824 + +[XCHAL_HAVE_VECTRA1] +Integer = 0 + +[XCHAL_PDX_SIMD32] +Integer = 0 + +[XCHAL_NUM_AREGS_LOG2] +Integer = 6 + +[XCHAL_HAVE_ABSOLUTE_LITERALS] +Integer = 0 + +[XCHAL_HAVE_DCACHE_DYN_WAYS] +Integer = 0 + +[XCHAL_NUM_IBREAK] +Integer = 2 + +[XCHAL_DCACHE_SETWIDTH] +Integer = 0 + +[XCHAL_EXTINT1_NUM] +Integer = 1 + +[XCHAL_WINDOW_UF8_VECOFS] +Integer = 192 + +[XCHAL_INT19_LEVEL] +Integer = 2 + +[XCHAL_HAVE_FUSION_AVS] +Integer = 0 + +[XCHAL_INT5_LEVEL] +Integer = 1 + +[XCHAL_HW_CONFIGID0] +Integer = 3270310654 + +[XCHAL_HAVE_FULL_RESET] +Integer = 1 + +[XCHAL_INT14_LEVEL] +Integer = 7 + +[XCHAL_INSTRAM1_HAVE_IDMA] +Integer = 0 + +[XCHAL_NUM_CONTEXTS] +Integer = 1 + +[XCHAL_HAVE_MX] +Integer = 0 + +[XCHAL_XLMI0_VADDR] +Integer = 1061158912 + +[XCHAL_HAVE_EXCLUSIVE] +Integer = 0 + +[XCHAL_HAVE_DEBUG_APB] +Integer = 0 + +[XCHAL_HAVE_VISION] +Integer = 0 + +[XCHAL_HAVE_INTERRUPTS] +Integer = 1 + +[XCHAL_INTTYPE_MASK_EXTERN_EDGE] +Integer = 1346372608 + +[XCHAL_HAVE_FUSIONG] +Integer = 0 + +[XCHAL_INTLEVEL6_MASK] +Integer = 0 + +[XCHAL_INT25_EXTNUM] +Integer = 20 + +[XCHAL_INT2_TYPE] +Interrupt = "ExternLevel" + +[XCHAL_HAVE_PIF] +Integer = 1 + +[XCHAL_HAVE_DEBUG_EXTERN_INT] +Integer = 1 + +[XCHAL_NUM_LOADSTORE_UNITS] +Integer = 1 + +[XCHAL_INTLEVEL6_VECTOR_VADDR] +Integer = 1073742464 + +[XCHAL_HAVE_FP_DIV] +Integer = 0 + +[XCHAL_HAVE_DFP_SQRT] +Integer = 0 + +[XCHAL_HAVE_TRAX] +Integer = 1 + +[XCHAL_HAVE_OCD_DIR_ARRAY] +Integer = 0 + +[XCHAL_INTLEVEL2_ANDBELOW_MASK] +Integer = 4077567 + +[XCHAL_HAVE_XEAX] +Integer = 0 + +[XCHAL_UNALIGNED_STORE_HW] +Integer = 1 + +[XCHAL_CORE_ID] +String = "esp_core_722_f" + +[XCHAL_INT12_TYPE] +Interrupt = "ExternLevel" + +[XCHAL_HAVE_TLBS] +Integer = 1 + +[XCHAL_NUM_INTLEVELS] +Integer = 6 + +[XCHAL_HAVE_NSA] +Integer = 1 + +[XCHAL_WINDOW_VECTORS_PADDR] +Integer = 1073741824 + +[XCHAL_PREFETCH_ENTRIES] +Integer = 0 + +[XCHAL_INT8_TYPE] +Interrupt = "ExternLevel" + +[XCHAL_TIMER1_INTERRUPT] +Integer = 15 + +[XCHAL_INT24_EXTNUM] +Integer = 19 + +[XCHAL_INT21_TYPE] +Interrupt = "ExternLevel" + +[XCHAL_KERNEL_VECTOR_PADDR] +Integer = 1073742592 + +[XCHAL_HAVE_LOOPS] +Integer = 0 + +[XCHAL_INT23_EXTNUM] +Integer = 18 + +[XCHAL_NUM_WRITEBUFFER_ENTRIES] +Integer = 4 + +[XCHAL_HAVE_PIF_REQ_ATTR] +Integer = 1 + +[XCHAL_INTLEVEL4_MASK] +Integer = 1392508928 + +[XCHAL_MMU_ASID_BITS] +Integer = 0 + +[XCHAL_INT28_TYPE] +Interrupt = "ExternEdge" + +[XCHAL_HAVE_USER_SPFPU] +Integer = 0 + +[XCHAL_HAVE_FUSION_LOW_POWER] +Integer = 0 + +[XCHAL_HAVE_SSP16_VITERBI] +Integer = 0 + +[XCHAL_HAVE_INSTRAM1] +Integer = 1 + +[XCHAL_INSTRAM1_ECC_PARITY] +Integer = 0 + +[XCHAL_HAVE_IDMA] +Integer = 0 + +[XCHAL_HAVE_FUSION_AES] +Integer = 0 + +[XCHAL_INTTYPE_MASK_NMI] +Integer = 16384 + +[XCHAL_HAVE_FUSIONG_SP_VFPU] +Integer = 0 + +[XCHAL_HAVE_GRIVPEP] +Integer = 0 + +[XCHAL_HAVE_CALL4AND12] +Integer = 1 + +[XCHAL_INTLEVEL4_VECTOR_PADDR] +Integer = 1073742336 + +[XCHAL_INT0_TYPE] +Interrupt = "ExternLevel" + +[XCHAL_DATARAM1_BANKS] +Integer = 1 + +[XCHAL_INTLEVEL4_VECTOR_VADDR] +Integer = 1073742336 + +[XCHAL_HAVE_CP] +Integer = 1 + +[XCHAL_PREFETCH_BLOCK_ENTRIES] +Integer = 0 + +[XCHAL_DEBUG_VECOFS] +Integer = 640 + +[XCHAL_INT23_LEVEL] +Integer = 3 + +[XCHAL_TIMER0_INTERRUPT] +Integer = 6 + +[XCHAL_HAVE_VISIONC] +Integer = 0 + +[XCHAL_DATARAM0_PADDR] +Integer = 1069547520 + +[XCHAL_VECBASE_RESET_VADDR] +Integer = 1073741824 + +[XCHAL_HAVE_IDENTITY_MAP] +Integer = 1 + +[XCHAL_HAVE_PRID] +Integer = 1 + +[XCHAL_NUM_INSTRAM] +Integer = 2 + +[XCHAL_INT17_EXTNUM] +Integer = 12 + +[XCHAL_TIMER3_INTERRUPT] +Interrupt = "TimerUnconfigured" + +[XCHAL_INT21_EXTNUM] +Integer = 16 + +[XCHAL_DCACHE_WAYS] +Integer = 1 + +[XCHAL_HAVE_SEXT] +Integer = 1 + +[XCHAL_INSTRAM0_ECC_PARITY] +Integer = 0 + +[XCHAL_INT26_EXTNUM] +Integer = 21 + +[XCHAL_KERNEL_VECOFS] +Integer = 768 + +[XCHAL_INT31_EXTNUM] +Integer = 25 + +[XCHAL_EXTINT12_NUM] +Integer = 17 + +[XCHAL_HAVE_BBP16] +Integer = 0 + +[XCHAL_INT13_EXTNUM] +Integer = 10 + +[XCHAL_INT16_TYPE] +Interrupt = "Timer" + +[XCHAL_DATAROM0_PADDR] +Integer = 1056964608 + +[XCHAL_WINDOW_UF12_VECOFS] +Integer = 320 + +[XCHAL_INTLEVEL7_VECTOR_PADDR] +Integer = 1073742528 + +[XCHAL_INTLEVEL5_VECTOR_VADDR] +Integer = 1073742400 + +[XCHAL_HAVE_FUSION_CONVENC] +Integer = 0 + +[XCHAL_HAVE_HIFI3_VFPU] +Integer = 0 + +[XCHAL_DCACHE_LINEWIDTH] +Integer = 2 + +[XCHAL_CA_BITS] +Integer = 4 + +[XCHAL_HAVE_EXCEPTIONS] +Integer = 1 + +[XCHAL_HAVE_DATARAM1] +Integer = 1 + +[XCHAL_INSTRAM0_SIZE] +Integer = 4194304 + +[XCHAL_HAVE_MP_INTERRUPTS] +Integer = 0 + +[XCHAL_HAVE_FUSION_SOFTDEMAP] +Integer = 0 + +[XCHAL_EXTINT25_NUM] +Integer = 31 + +[XCHAL_USER_VECOFS] +Integer = 832 + +[XCHAL_INSTROM0_SIZE] +Integer = 4194304 + +[XCHAL_HAVE_BOOLEANS] +Integer = 0 + +[XCHAL_HAVE_FUSION_BITOPS] +Integer = 0 + +[XCHAL_INT8_LEVEL] +Integer = 1 + +[XCHAL_HAVE_DFP_RECIP] +Integer = 0 + +[XCHAL_INT13_TYPE] +Interrupt = "ExternLevel" + +[XCHAL_HAVE_BBE16_RSQRT] +Integer = 0 + +[XCHAL_HW_MAX_VERSION_MINOR] +Integer = 9 + +[XCHAL_INT9_TYPE] +Interrupt = "ExternLevel" + +[XCHAL_INT18_LEVEL] +Integer = 1 diff --git a/xtensa-lx-rt/config/xtensa_esp32s3.toml b/xtensa-lx-rt/config/xtensa_esp32s3.toml new file mode 100644 index 000000000..73cc317ed --- /dev/null +++ b/xtensa-lx-rt/config/xtensa_esp32s3.toml @@ -0,0 +1,1409 @@ +[XCHAL_INTLEVEL7_VECTOR_VADDR] +Integer = 1073742528 + +[XCHAL_HAVE_EXTERN_REGS] +Integer = 1 + +[XCHAL_WINDOW_VECTORS_PADDR] +Integer = 1073741824 + +[XCHAL_HAVE_MX] +Integer = 0 + +[XCHAL_HAVE_FP_RSQRT] +Integer = 1 + +[XCHAL_UNALIGNED_STORE_HW] +Integer = 1 + +[XCHAL_INTLEVEL6_MASK] +Integer = 0 + +[XCHAL_VECBASE_RESET_PADDR] +Integer = 1073741824 + +[XCHAL_KERNEL_VECTOR_PADDR] +Integer = 1073742592 + +[XCHAL_HAVE_MPU] +Integer = 0 + +[XCHAL_NUM_INSTRAM] +Integer = 1 + +[XCHAL_INT2_LEVEL] +Integer = 1 + +[XCHAL_INTTYPE_MASK_PROFILING] +Integer = 2048 + +[XCHAL_INT28_EXTNUM] +Integer = 23 + +[XCHAL_HAVE_HIFI4] +Integer = 0 + +[XCHAL_HAVE_USER_DPFPU] +Integer = 0 + +[XCHAL_HAVE_HIFI5_VFPU] +Integer = 0 + +[XCHAL_DCACHE_LINE_LOCKABLE] +Integer = 0 + +[XCHAL_HAVE_VISION_HISTOGRAM] +Integer = 0 + +[XCHAL_HAVE_L32R] +Integer = 1 + +[XCHAL_HAVE_BBE16] +Integer = 0 + +[XCHAL_TIMER0_INTERRUPT] +Integer = 6 + +[XCHAL_EXTINT12_NUM] +Integer = 17 + +[XCHAL_TIMER2_INTERRUPT] +Integer = 16 + +[XCHAL_EXTINT23_NUM] +Integer = 28 + +[XCHAL_MPU_ALIGN_REQ] +Integer = 1 + +[XCHAL_NMI_VECOFS] +Integer = 704 + +[XCHAL_HW_VERSION_MAJOR] +Integer = 2700 + +[XCHAL_INT30_LEVEL] +Integer = 4 + +[XCHAL_EXTINT14_NUM] +Integer = 19 + +[XCHAL_HAVE_DEBUG_ERI] +Integer = 1 + +[XCHAL_HAVE_DFPU_SINGLE_ONLY] +Integer = 1 + +[XCHAL_INTLEVEL3_VECTOR_VADDR] +Integer = 1073742272 + +[XCHAL_INTLEVEL7_VECOFS] +Integer = 704 + +[XCHAL_HAVE_MEM_ECC_PARITY] +Integer = 0 + +[XCHAL_WINDOW_UF8_VECOFS] +Integer = 192 + +[XCHAL_SPANNING_WAY] +Integer = 0 + +[XCHAL_INT3_TYPE] +Interrupt = "ExternLevel" + +[XCHAL_INT26_LEVEL] +Integer = 5 + +[XCHAL_INT4_LEVEL] +Integer = 1 + +[XCHAL_HAVE_FP_DIV] +Integer = 1 + +[XCHAL_INTLEVEL2_MASK] +Integer = 3670016 + +[XCHAL_EXTINT13_NUM] +Integer = 18 + +[XCHAL_INT13_LEVEL] +Integer = 1 + +[XCHAL_HAVE_CLAMPS] +Integer = 1 + +[XCHAL_INT31_TYPE] +Interrupt = "ExternLevel" + +[XCHAL_EXTINT0_NUM] +Integer = 0 + +[XCHAL_HAVE_PDX16] +Integer = 0 + +[XCHAL_INT30_TYPE] +Interrupt = "ExternEdge" + +[XCHAL_HAVE_IDMA_TRANSPOSE] +Integer = 0 + +[XCHAL_HAVE_WIDE_BRANCHES] +Integer = 0 + +[XCHAL_HAVE_DFP_ACCEL] +Integer = 0 + +[XCHAL_HAVE_CCOUNT] +Integer = 1 + +[XCHAL_CORE_ID] +String = "LX7_ESP32_S3_MP" + +[XCHAL_HAVE_HALT] +Integer = 0 + +[XCHAL_INT13_EXTNUM] +Integer = 10 + +[XCHAL_HW_REL_LX7_0_12] +Integer = 1 + +[XCHAL_INT16_TYPE] +Interrupt = "Timer" + +[XCHAL_HAVE_CONST16] +Integer = 0 + +[XCHAL_HAVE_SPECULATION] +Integer = 0 + +[XCHAL_NUM_CONTEXTS] +Integer = 1 + +[XCHAL_INTLEVEL5_MASK] +Integer = 2214658048 + +[XCHAL_HAVE_MAC16] +Integer = 1 + +[XCHAL_DEBUGLEVEL] +Integer = 6 + +[XCHAL_TRAX_ATB_WIDTH] +Integer = 0 + +[XCHAL_HAVE_HIFI3Z_VFPU] +Integer = 0 + +[XCHAL_INTLEVEL4_VECTOR_VADDR] +Integer = 1073742336 + +[XCHAL_INT5_TYPE] +Interrupt = "ExternLevel" + +[XCHAL_INT9_EXTNUM] +Integer = 7 + +[XCHAL_INT11_TYPE] +Interrupt = "Profiling" + +[XCHAL_HAVE_HIFI2] +Integer = 0 + +[XCHAL_HAVE_IMEM_LOADSTORE] +Integer = 1 + +[XCHAL_HAVE_CACHE_BLOCKOPS] +Integer = 0 + +[XCHAL_HAVE_ICACHE_TEST] +Integer = 0 + +[XCHAL_INTLEVEL7_VECTOR_PADDR] +Integer = 1073742528 + +[XCHAL_TRAX_TIME_WIDTH] +Integer = 0 + +[XCHAL_EXTINT9_NUM] +Integer = 12 + +[XCHAL_INT4_EXTNUM] +Integer = 4 + +[XCHAL_HAVE_PRID] +Integer = 1 + +[XCHAL_INT27_LEVEL] +Integer = 3 + +[XCHAL_DATARAM0_VADDR] +Integer = 1006632960 + +[XCHAL_EXTINT19_NUM] +Integer = 24 + +[XCHAL_ICACHE_LINE_LOCKABLE] +Integer = 0 + +[XCHAL_HAVE_HIFI5_NN_MAC] +Integer = 0 + +[XCHAL_DCACHE_LINESIZE] +Integer = 16 + +[XCHAL_HAVE_ADDX] +Integer = 1 + +[XCHAL_HAVE_AXI_ECC] +Integer = 0 + +[XCHAL_INT25_TYPE] +Interrupt = "ExternLevel" + +[XCHAL_HAVE_HIFI3Z] +Integer = 0 + +[XCHAL_HAVE_PSO_CDM] +Integer = 0 + +[XCHAL_MMU_RING_BITS] +Integer = 0 + +[XCHAL_HAVE_INTERRUPTS] +Integer = 1 + +[XCHAL_EXTINT15_NUM] +Integer = 20 + +[XCHAL_HAVE_SSP16_VITERBI] +Integer = 0 + +[XCHAL_INTLEVEL6_VECOFS] +Integer = 640 + +[XCHAL_HAVE_FUSIONG6] +Integer = 0 + +[XCHAL_TRAX_MEM_SIZE] +Integer = 16384 + +[XCHAL_INTLEVEL6_VECTOR_VADDR] +Integer = 1073742464 + +[XCHAL_NUM_MISC_REGS] +Integer = 4 + +[XCHAL_INT2_TYPE] +Interrupt = "ExternLevel" + +[XCHAL_HAVE_MIMIC_CACHEATTR] +Integer = 1 + +[XCHAL_HAVE_HIFI2EP] +Integer = 0 + +[XCHAL_HAVE_MP_INTERRUPTS] +Integer = 0 + +[XCHAL_WINDOW_UF4_VECOFS] +Integer = 64 + +[XCHAL_NUM_AREGS_LOG2] +Integer = 6 + +[XCHAL_INT1_TYPE] +Interrupt = "ExternLevel" + +[XCHAL_HAVE_XLT_CACHEATTR] +Integer = 0 + +[XCHAL_INT19_LEVEL] +Integer = 2 + +[XCHAL_INTLEVEL3_VECTOR_PADDR] +Integer = 1073742272 + +[XCHAL_DATA_PIPE_DELAY] +Integer = 1 + +[XCHAL_INTLEVEL2_VECTOR_PADDR] +Integer = 1073742208 + +[XCHAL_MPU_ALIGN] +Integer = 0 + +[XCHAL_HAVE_FUSION_LFSR_CRC] +Integer = 0 + +[XCHAL_INT23_TYPE] +Interrupt = "ExternLevel" + +[XCHAL_CLOCK_GATING_GLOBAL] +Integer = 1 + +[XCHAL_INT12_EXTNUM] +Integer = 9 + +[XCHAL_INTTYPE_MASK_EXTERN_LEVEL] +Integer = 2411606847 + +[XCHAL_EXTINT5_NUM] +Integer = 5 + +[XCHAL_HAVE_VISION] +Integer = 0 + +[XCHAL_DOUBLEEXC_VECTOR_VADDR] +Integer = 1073742784 + +[XCHAL_NMI_INTERRUPT] +Integer = 14 + +[XCHAL_EXTINT7_NUM] +Integer = 9 + +[XCHAL_EXTINT22_NUM] +Integer = 27 + +[XCHAL_HAVE_XEAX] +Integer = 0 + +[XCHAL_INTLEVEL5_VECTOR_VADDR] +Integer = 1073742400 + +[XCHAL_INTTYPE_MASK_IDMA_DONE] +Integer = 0 + +[XCHAL_NUM_URAM] +Integer = 0 + +[XCHAL_INT1_LEVEL] +Integer = 1 + +[XCHAL_HAVE_DFP] +Integer = 0 + +[XCHAL_INT8_EXTNUM] +Integer = 6 + +[XCHAL_HAVE_SSP16] +Integer = 0 + +[XCHAL_HW_CONFIGID1] +Integer = 587796255 + +[XCHAL_HAVE_MUL32] +Integer = 1 + +[XCHAL_DATARAM0_SIZE] +Integer = 67108864 + +[XCHAL_DCACHE_WAYS] +Integer = 1 + +[XCHAL_HAVE_EXCLUSIVE] +Integer = 0 + +[XCHAL_HAVE_MINMAX] +Integer = 1 + +[XCHAL_INT27_EXTNUM] +Integer = 22 + +[XCHAL_INT15_LEVEL] +Integer = 3 + +[XCHAL_INTLEVEL3_VECOFS] +Integer = 448 + +[XCHAL_HAVE_FP_SQRT] +Integer = 1 + +[XCHAL_HAVE_ACELITE] +Integer = 0 + +[XCHAL_HAVE_BE] +Integer = 0 + +[XCHAL_INTLEVEL1_MASK] +Integer = 407551 + +[XCHAL_KERNEL_VECTOR_VADDR] +Integer = 1073742592 + +[XCHAL_INT12_LEVEL] +Integer = 1 + +[XCHAL_ICACHE_SIZE] +Integer = 0 + +[XCHAL_HW_MIN_VERSION_MAJOR] +Integer = 2700 + +[XCHAL_HAVE_HIFI3] +Integer = 0 + +[XCHAL_USER_VECTOR_VADDR] +Integer = 1073742656 + +[XCHAL_HW_VERSION_MINOR] +Integer = 12 + +[XCHAL_INT17_TYPE] +Interrupt = "ExternLevel" + +[XCHAL_DCACHE_ECC_PARITY] +Integer = 0 + +[XCHAL_INT20_LEVEL] +Integer = 2 + +[XCHAL_INTLEVEL5_VECTOR_PADDR] +Integer = 1073742400 + +[XCHAL_HAVE_HIFI_MINI] +Integer = 0 + +[XCHAL_HW_MAX_VERSION_MAJOR] +Integer = 2700 + +[XCHAL_DATARAM0_HAVE_IDMA] +Integer = 0 + +[XCHAL_WINDOW_OF12_VECOFS] +Integer = 256 + +[XCHAL_HAVE_VECTRALX] +Integer = 0 + +[XCHAL_DCACHE_IS_COHERENT] +Integer = 0 + +[XCHAL_INT24_TYPE] +Interrupt = "ExternLevel" + +[XCHAL_INTLEVEL1_ANDBELOW_MASK] +Integer = 407551 + +[XCHAL_HAVE_BBENEP] +Integer = 0 + +[XCHAL_NUM_DATAROM] +Integer = 0 + +[XCHAL_NUM_DATARAM] +Integer = 1 + +[XCHAL_HAVE_FULL_RESET] +Integer = 1 + +[XCHAL_HW_MAX_VERSION] +Integer = 270012 + +[XCHAL_EXTINT11_NUM] +Integer = 14 + +[XCHAL_INT5_EXTNUM] +Integer = 5 + +[XCHAL_VISION_SIMD16] +Integer = 0 + +[XCHAL_INT19_EXTNUM] +Integer = 14 + +[XCHAL_NUM_INSTROM] +Integer = 0 + +[XCHAL_HAVE_CP] +Integer = 1 + +[XCHAL_NUM_TIMERS] +Integer = 3 + +[XCHAL_ICACHE_ECC_WIDTH] +Integer = 1 + +[XCHAL_ICACHE_LINEWIDTH] +Integer = 2 + +[XCHAL_INSTRAM0_SIZE] +Integer = 67108864 + +[XCHAL_HW_VERSION_NAME] +String = "LX7.0.12" + +[XCHAL_HAVE_XEA2] +Integer = 1 + +[XCHAL_INTLEVEL7_ANDBELOW_MASK] +Integer = 4294967295 + +[XCHAL_INT16_LEVEL] +Integer = 5 + +[XCHAL_INT9_TYPE] +Interrupt = "ExternLevel" + +[XCHAL_HAVE_BSP3_TRANSPOSE] +Integer = 0 + +[XCHAL_INT6_TYPE] +Interrupt = "Timer" + +[XCHAL_INT7_LEVEL] +Integer = 1 + +[XCHAL_NUM_PERF_COUNTERS] +Integer = 2 + +[XCHAL_INT0_EXTNUM] +Integer = 0 + +[XCHAL_TRAX_MEM_SHAREABLE] +Integer = 1 + +[XCHAL_INT30_EXTNUM] +Integer = 24 + +[XCHAL_EXCM_LEVEL] +Integer = 3 + +[XCHAL_INT3_LEVEL] +Integer = 1 + +[XCHAL_HAVE_DFPU_SINGLE_DOUBLE] +Integer = 0 + +[XCHAL_HAVE_BBE16_DESPREAD] +Integer = 0 + +[XCHAL_INT24_EXTNUM] +Integer = 19 + +[XCHAL_EXTINT17_NUM] +Integer = 22 + +[XCHAL_HAVE_IDMA] +Integer = 0 + +[XCHAL_HAVE_DFP_accel] +Integer = 0 + +[XCHAL_HAVE_DEBUG_JTAG] +Integer = 1 + +[XCHAL_INT18_TYPE] +Interrupt = "ExternLevel" + +[XCHAL_DCACHE_ECC_WIDTH] +Integer = 1 + +[XCHAL_INT10_LEVEL] +Integer = 1 + +[XCHAL_MPU_ALIGN_BITS] +Integer = 0 + +[XCHAL_HAVE_PIF_REQ_ATTR] +Integer = 1 + +[XCHAL_INT9_LEVEL] +Integer = 1 + +[XCHAL_INTLEVEL3_MASK] +Integer = 683706368 + +[XCHAL_NUM_INTERRUPTS] +Integer = 32 + +[XCHAL_HAVE_AXI] +Integer = 0 + +[XCHAL_INT19_TYPE] +Interrupt = "ExternLevel" + +[XCHAL_INT23_EXTNUM] +Integer = 18 + +[XCHAL_HAVE_DEPBITS] +Integer = 0 + +[XCHAL_HAVE_NSA] +Integer = 1 + +[XCHAL_HAVE_CONNXD2_DUALLSFLIX] +Integer = 0 + +[XCHAL_XEA_VERSION] +Integer = 2 + +[XCHAL_INTLEVEL7_NUM] +Integer = 14 + +[XCHAL_INT15_TYPE] +Interrupt = "Timer" + +[XCHAL_INSTRAM0_HAVE_IDMA] +Integer = 0 + +[XCHAL_INTLEVEL3_ANDBELOW_MASK] +Integer = 687783935 + +[XCHAL_INT10_EXTNUM] +Integer = 8 + +[XCHAL_HAVE_PREFETCH] +Integer = 0 + +[XCHAL_INT4_TYPE] +Interrupt = "ExternLevel" + +[XCHAL_HAVE_DCACHE_TEST] +Integer = 0 + +[XCHAL_INT22_LEVEL] +Integer = 3 + +[XCHAL_ICACHE_ECC_PARITY] +Integer = 0 + +[XCHAL_INTTYPE_MASK_TIMER] +Integer = 98368 + +[XCHAL_INTTYPE_MASK_SOFTWARE] +Integer = 536871040 + +[XCHAL_HAVE_FP_RECIP] +Integer = 1 + +[XCHAL_INTTYPE_MASK_EXTERN_EDGE] +Integer = 1346372608 + +[XCHAL_EXTINT20_NUM] +Integer = 25 + +[XCHAL_MAX_INSTRUCTION_SIZE] +Integer = 4 + +[XCHAL_HAVE_PTP_MMU] +Integer = 0 + +[XCHAL_HAVE_VECTRA1] +Integer = 0 + +[XCHAL_WINDOW_VECTORS_VADDR] +Integer = 1073741824 + +[XCHAL_HAVE_FUSION_VITERBI] +Integer = 0 + +[XCHAL_INTLEVEL5_ANDBELOW_MASK] +Integer = 4294950911 + +[XCHAL_HAVE_FUSIONG_SP_VFPU] +Integer = 0 + +[XCHAL_HAVE_CACHEATTR] +Integer = 0 + +[XCHAL_INT8_TYPE] +Interrupt = "ExternLevel" + +[XCHAL_INT11_LEVEL] +Integer = 3 + +[XCHAL_HAVE_FUSION_BITOPS] +Integer = 0 + +[XCHAL_HAVE_FUSION_LOW_POWER] +Integer = 0 + +[XCHAL_VISION_QUAD_MAC_TYPE] +Integer = 0 + +[XCHAL_INT21_LEVEL] +Integer = 2 + +[XCHAL_INTLEVEL4_ANDBELOW_MASK] +Integer = 2080292863 + +[XCHAL_UNALIGNED_LOAD_EXCEPTION] +Integer = 0 + +[XCHAL_HAVE_FUSION_CONVENC] +Integer = 0 + +[XCHAL_HAVE_SEXT] +Integer = 1 + +[XCHAL_HAVE_DATARAM0] +Integer = 1 + +[XCHAL_HAVE_FUSION] +Integer = 0 + +[XCHAL_HAVE_PREFETCH_L1] +Integer = 0 + +[XCHAL_INT29_LEVEL] +Integer = 3 + +[XCHAL_HAVE_MUL16] +Integer = 1 + +[XCHAL_HAVE_FLIX3] +Integer = 0 + +[XCHAL_UNALIGNED_LOAD_HW] +Integer = 1 + +[XCHAL_NUM_INTERRUPTS_LOG2] +Integer = 5 + +[XCHAL_HAVE_EXCEPTIONS] +Integer = 1 + +[XCHAL_HAVE_FUSIONG_DP_VFPU] +Integer = 0 + +[XCHAL_HW_CONFIGID_RELIABLE] +Integer = 1 + +[XCHAL_INT14_EXTNUM] +Integer = 11 + +[XCHAL_NMI_VECTOR_VADDR] +Integer = 1073742528 + +[XCHAL_HW_REL_LX7] +Integer = 1 + +[XCHAL_INT28_LEVEL] +Integer = 4 + +[XCHAL_HAVE_SPANNING_WAY] +Integer = 1 + +[XCHAL_HAVE_OCD] +Integer = 1 + +[XCHAL_HAVE_OCD_DIR_ARRAY] +Integer = 0 + +[XCHAL_INTLEVEL4_VECOFS] +Integer = 512 + +[XCHAL_DATARAM0_BANKS] +Integer = 1 + +[XCHAL_HW_MAX_VERSION_MINOR] +Integer = 12 + +[XCHAL_HAVE_ICACHE_DYN_WAYS] +Integer = 0 + +[XCHAL_DCACHE_BANKS] +Integer = 0 + +[XCHAL_INT21_TYPE] +Interrupt = "ExternLevel" + +[XCHAL_HAVE_TAP_MASTER] +Integer = 0 + +[XCHAL_HAVE_DEBUG_APB] +Integer = 0 + +[XCHAL_HAVE_VECBASE] +Integer = 1 + +[XCHAL_INT21_EXTNUM] +Integer = 16 + +[XCHAL_PREFETCH_CASTOUT_LINES] +Integer = 0 + +[XCHAL_HAVE_DIV32] +Integer = 1 + +[XCHAL_DATA_WIDTH] +Integer = 16 + +[XCHAL_EXTINT18_NUM] +Integer = 23 + +[XCHAL_WINDOW_OF4_VECOFS] +Integer = 0 + +[XCHAL_HAVE_HIFI5] +Integer = 0 + +[XCHAL_INSTRAM0_PADDR] +Integer = 1073741824 + +[XCHAL_PREFETCH_ENTRIES] +Integer = 0 + +[XCHAL_INTLEVEL2_ANDBELOW_MASK] +Integer = 4077567 + +[XCHAL_HAVE_USER_SPFPU] +Integer = 0 + +[XCHAL_INT12_TYPE] +Interrupt = "ExternLevel" + +[XCHAL_MPU_ENTRIES] +Integer = 0 + +[XCHAL_HW_VERSION] +Integer = 270012 + +[XCHAL_HAVE_PIF_WR_RESP] +Integer = 0 + +[XCHAL_INT29_TYPE] +Interrupt = "Software" + +[XCHAL_ICACHE_SETWIDTH] +Integer = 0 + +[XCHAL_DATARAM0_PADDR] +Integer = 1006632960 + +[XCHAL_INT20_EXTNUM] +Integer = 15 + +[XCHAL_HAVE_HIGHPRI_INTERRUPTS] +Integer = 1 + +[XCHAL_HAVE_DENSITY] +Integer = 1 + +[XCHAL_INT26_EXTNUM] +Integer = 21 + +[XCHAL_LOOP_BUFFER_SIZE] +Integer = 256 + +[XCHAL_HAVE_FUSION_AVS] +Integer = 0 + +[XCHAL_INTTYPE_MASK_IDMA_ERR] +Integer = 0 + +[XCHAL_EXTINT25_NUM] +Integer = 31 + +[XCHAL_HAVE_BBE16_VECDIV] +Integer = 0 + +[XCHAL_DEBUG_VECTOR_PADDR] +Integer = 1073742464 + +[XCHAL_HAVE_TLBS] +Integer = 1 + +[XCHAL_EXTINT1_NUM] +Integer = 1 + +[XCHAL_MPU_BACKGROUND_ENTRIES] +Integer = 0 + +[XCHAL_NUM_INTLEVELS] +Integer = 6 + +[XCHAL_HAVE_FUSIONG] +Integer = 0 + +[XCHAL_INT0_TYPE] +Interrupt = "ExternLevel" + +[XCHAL_HAVE_PDX4] +Integer = 0 + +[XCHAL_INT23_LEVEL] +Integer = 3 + +[XCHAL_RESET_VECTOR0_PADDR] +Integer = 1342177280 + +[XCHAL_INT17_EXTNUM] +Integer = 12 + +[XCHAL_HAVE_ABS] +Integer = 1 + +[XCHAL_INST_FETCH_WIDTH] +Integer = 4 + +[XCHAL_DCACHE_LINEWIDTH] +Integer = 4 + +[XCHAL_ICACHE_ACCESS_SIZE] +Integer = 1 + +[XCHAL_INT14_TYPE] +Interrupt = "Nmi" + +[XCHAL_HAVE_PREDICTED_BRANCHES] +Integer = 0 + +[XCHAL_CA_BITS] +Integer = 4 + +[XCHAL_INTTYPE_MASK_WRITE_ERROR] +Integer = 0 + +[XCHAL_HAVE_DEBUG_EXTERN_INT] +Integer = 1 + +[XCHAL_HAVE_DCACHE_DYN_WAYS] +Integer = 0 + +[XCHAL_NUM_XLMI] +Integer = 0 + +[XCHAL_EXTINT4_NUM] +Integer = 4 + +[XCHAL_HAVE_DFP_RECIP] +Integer = 0 + +[XCHAL_INT1_EXTNUM] +Integer = 1 + +[XCHAL_INT2_EXTNUM] +Integer = 2 + +[XCHAL_INT13_TYPE] +Interrupt = "ExternLevel" + +[XCHAL_INTLEVEL2_VECOFS] +Integer = 384 + +[XCHAL_EXTINT8_NUM] +Integer = 10 + +[XCHAL_HAVE_CALL4AND12] +Integer = 1 + +[XCHAL_INT22_EXTNUM] +Integer = 17 + +[XCHAL_EXTINT6_NUM] +Integer = 8 + +[XCHAL_HAVE_THREADPTR] +Integer = 1 + +[XCHAL_NMILEVEL] +Integer = 7 + +[XCHAL_HAVE_PSO] +Integer = 0 + +[XCHAL_HAVE_IDENTITY_MAP] +Integer = 1 + +[XCHAL_MPU_BG_CACHEADRDIS] +Integer = 0 + +[XCHAL_RESET_VECTOR1_VADDR] +Integer = 1073742848 + +[XCHAL_HAVE_NMI] +Integer = 1 + +[XCHAL_HAVE_MUL32_HIGH] +Integer = 1 + +[XCHAL_PREFETCH_BLOCK_ENTRIES] +Integer = 0 + +[XCHAL_RESET_VECTOR1_PADDR] +Integer = 1073742848 + +[XCHAL_HAVE_FUSION_AES] +Integer = 0 + +[XCHAL_HAVE_FUSIONG3] +Integer = 0 + +[XCHAL_MMU_RINGS] +Integer = 1 + +[XCHAL_FUSIONG_SIMD32] +Integer = 0 + +[XCHAL_RESET_VECBASE_OVERLAP] +Integer = 0 + +[XCHAL_KERNEL_VECOFS] +Integer = 768 + +[XCHAL_HAVE_GRIVPEP_HISTOGRAM] +Integer = 0 + +[XCHAL_HAVE_FUSION_16BIT_BASEBAND] +Integer = 0 + +[XCHAL_HAVE_RELEASE_SYNC] +Integer = 1 + +[XCHAL_NUM_WRITEBUFFER_ENTRIES] +Integer = 4 + +[XCHAL_INT31_EXTNUM] +Integer = 25 + +[XCHAL_HAVE_DFP_SQRT] +Integer = 0 + +[XCHAL_HW_MIN_VERSION] +Integer = 270012 + +[XCHAL_DCACHE_SIZE] +Integer = 0 + +[XCHAL_HAVE_DEBUG] +Integer = 1 + +[XCHAL_INT26_TYPE] +Interrupt = "ExternLevel" + +[XCHAL_EXTINT10_NUM] +Integer = 13 + +[XCHAL_INT25_LEVEL] +Integer = 4 + +[XCHAL_NUM_EXTINTERRUPTS] +Integer = 26 + +[XCHAL_INT18_EXTNUM] +Integer = 13 + +[XCHAL_EXTINT16_NUM] +Integer = 21 + +[XCHAL_USER_VECTOR_PADDR] +Integer = 1073742656 + +[XCHAL_HAVE_VISIONC] +Integer = 0 + +[XCHAL_HW_REL_LX7_0] +Integer = 1 + +[XCHAL_HAVE_BBE16_RSQRT] +Integer = 0 + +[XCHAL_HAVE_WINDOWED] +Integer = 1 + +[XCHAL_BUILD_UNIQUE_ID] +Integer = 593695 + +[XCHAL_INTLEVEL4_MASK] +Integer = 1392508928 + +[XCHAL_NUM_LOADSTORE_UNITS] +Integer = 1 + +[XCHAL_INT25_EXTNUM] +Integer = 20 + +[XCHAL_HAVE_FUSION_FP] +Integer = 0 + +[XCHAL_INSTRAM0_VADDR] +Integer = 1073741824 + +[XCHAL_WINDOW_OF8_VECOFS] +Integer = 128 + +[XCHAL_INTLEVEL2_VECTOR_VADDR] +Integer = 1073742208 + +[XCHAL_INTLEVEL5_VECOFS] +Integer = 576 + +[XCHAL_HAVE_TRAX] +Integer = 1 + +[XCHAL_DOUBLEEXC_VECOFS] +Integer = 960 + +[XCHAL_HAVE_FUSION_SOFTDEMAP] +Integer = 0 + +[XCHAL_DEBUG_VECTOR_VADDR] +Integer = 1073742464 + +[XCHAL_NUM_DBREAK] +Integer = 2 + +[XCHAL_ICACHE_WAYS] +Integer = 1 + +[XCHAL_INT17_LEVEL] +Integer = 1 + +[XCHAL_INT18_LEVEL] +Integer = 1 + +[XCHAL_INT14_LEVEL] +Integer = 7 + +[XCHAL_HAVE_MP_RUNSTALL] +Integer = 0 + +[XCHAL_HAVE_TURBO16] +Integer = 0 + +[XCHAL_HAVE_VECTOR_SELECT] +Integer = 1 + +[XCHAL_HAVE_BOOLEANS] +Integer = 1 + +[XCHAL_HAVE_GRIVPEP] +Integer = 0 + +[XCHAL_HAVE_DFP_DIV] +Integer = 0 + +[XCHAL_DCACHE_ACCESS_SIZE] +Integer = 1 + +[XCHAL_INT10_TYPE] +Interrupt = "ExternEdge" + +[XCHAL_HAVE_LOOPS] +Integer = 1 + +[XCHAL_HAVE_HIFIPRO] +Integer = 0 + +[XCHAL_SW_VERSION] +Integer = 1200012 + +[XCHAL_HW_MIN_VERSION_MINOR] +Integer = 12 + +[XCHAL_ICACHE_LINESIZE] +Integer = 4 + +[XCHAL_HAVE_PDX] +Integer = 0 + +[XCHAL_INT24_LEVEL] +Integer = 4 + +[XCHAL_INT20_TYPE] +Interrupt = "ExternLevel" + +[XCHAL_INT3_EXTNUM] +Integer = 3 + +[XCHAL_WINDOW_UF12_VECOFS] +Integer = 320 + +[XCHAL_HAVE_VISION_SP_VFPU] +Integer = 0 + +[XCHAL_HAVE_PIF] +Integer = 1 + +[XCHAL_INT27_TYPE] +Interrupt = "ExternLevel" + +[XCHAL_INTTYPE_MASK_GS_ERR] +Integer = 0 + +[XCHAL_HAVE_PSO_FULL_RETENTION] +Integer = 0 + +[XCHAL_INTLEVEL4_VECTOR_PADDR] +Integer = 1073742336 + +[XCHAL_HAVE_HIFI5_HP_VFPU] +Integer = 0 + +[XCHAL_INT5_LEVEL] +Integer = 1 + +[XCHAL_HAVE_ABSOLUTE_LITERALS] +Integer = 0 + +[XCHAL_HAVE_CONNXD2] +Integer = 0 + +[XCHAL_DOUBLEEXC_VECTOR_PADDR] +Integer = 1073742784 + +[XCHAL_NUM_AREGS] +Integer = 64 + +[XCHAL_HAVE_HIFI3_VFPU] +Integer = 0 + +[XCHAL_HAVE_VECTORFPU2005] +Integer = 0 + +[XCHAL_INT28_TYPE] +Interrupt = "ExternEdge" + +[XCHAL_INTTYPE_MASK_NMI] +Integer = 16384 + +[XCHAL_HAVE_S32C1I] +Integer = 1 + +[XCHAL_VECBASE_RESET_VADDR] +Integer = 1073741824 + +[XCHAL_VISION_TYPE] +Integer = 0 + +[XCHAL_DCACHE_IS_WRITEBACK] +Integer = 0 + +[XCHAL_PROFILING_INTERRUPT] +Integer = 11 + +[XCHAL_HAVE_BSP3] +Integer = 0 + +[XCHAL_INT8_LEVEL] +Integer = 1 + +[XCHAL_INTLEVEL7_MASK] +Integer = 16384 + +[XCHAL_HW_CONFIGID0] +Integer = 3270574078 + +[XCHAL_EXTINT21_NUM] +Integer = 26 + +[XCHAL_EXTINT24_NUM] +Integer = 30 + +[XCHAL_DCACHE_SETWIDTH] +Integer = 0 + +[XCHAL_HAVE_OCD_LS32DDR] +Integer = 1 + +[XCHAL_DEBUG_VECOFS] +Integer = 640 + +[XCHAL_INTTYPE_MASK_UNCONFIGURED] +Integer = 0 + +[XCHAL_INT0_LEVEL] +Integer = 1 + +[XCHAL_RESET_VECTOR_VADDR] +Integer = 1073742848 + +[XCHAL_CLOCK_GATING_FUNCUNIT] +Integer = 1 + +[XCHAL_TIMER1_INTERRUPT] +Integer = 15 + +[XCHAL_NUM_IBREAK] +Integer = 2 + +[XCHAL_DATARAM0_ECC_PARITY] +Integer = 0 + +[XCHAL_HAVE_BBP16] +Integer = 0 + +[XCHAL_HAVE_PDX8] +Integer = 0 + +[XCHAL_NMI_VECTOR_PADDR] +Integer = 1073742528 + +[XCHAL_UNALIGNED_STORE_EXCEPTION] +Integer = 0 + +[XCHAL_HAVE_HIFI4_VFPU] +Integer = 0 + +[XCHAL_INSTRAM0_ECC_PARITY] +Integer = 0 + +[XCHAL_RESET_VECTOR0_VADDR] +Integer = 1342177280 + +[XCHAL_INTLEVEL6_VECTOR_PADDR] +Integer = 1073742464 + +[XCHAL_PDX_SIMD32] +Integer = 0 + +[XCHAL_INT6_LEVEL] +Integer = 1 + +[XCHAL_HAVE_DFP_RSQRT] +Integer = 0 + +[XCHAL_HAVE_INSTRAM0] +Integer = 1 + +[XCHAL_RESET_VECTOR_PADDR] +Integer = 1073742848 + +[XCHAL_USER_VECOFS] +Integer = 832 + +[XCHAL_CP_MAXCFG] +Integer = 8 + +[XCHAL_MMU_ASID_BITS] +Integer = 0 + +[XCHAL_INTLEVEL6_ANDBELOW_MASK] +Integer = 4294950911 + +[XCHAL_INT22_TYPE] +Interrupt = "ExternEdge" + +[XCHAL_HAVE_XEA1] +Integer = 0 + +[XCHAL_HAVE_FP] +Integer = 1 + +[XCHAL_HAVE_BBENEP_SP_VFPU] +Integer = 0 + +[XCHAL_EXTINT3_NUM] +Integer = 3 + +[XCHAL_TIMER3_INTERRUPT] +Interrupt = "TimerUnconfigured" + +[XCHAL_HAVE_BOOTLOADER] +Integer = 0 + +[XCHAL_INT7_TYPE] +Interrupt = "Software" + +[XCHAL_INT31_LEVEL] +Integer = 5 + +[XCHAL_EXTINT2_NUM] +Integer = 2 + +[XCHAL_HAVE_VISION_HP_VFPU] +Integer = 0 diff --git a/xtensa-lx-rt/exception-esp32.x.jinja b/xtensa-lx-rt/exception-esp32.x.jinja new file mode 100644 index 000000000..b9d5c8331 --- /dev/null +++ b/xtensa-lx-rt/exception-esp32.x.jinja @@ -0,0 +1,96 @@ +/* exception vector for the ESP32, requiring high priority interrupts and register window support */ + +/* high level exception/interrupt routines, which can be override with Rust functions */ +PROVIDE(__exception = __default_exception); +PROVIDE(__user_exception = __default_user_exception); +PROVIDE(__double_exception = __default_double_exception); +PROVIDE(__level_1_interrupt = __default_interrupt); +PROVIDE(__level_2_interrupt = __default_interrupt); +PROVIDE(__level_3_interrupt = __default_interrupt); +PROVIDE(__level_4_interrupt = __default_interrupt); +PROVIDE(__level_5_interrupt = __default_interrupt); +PROVIDE(__level_6_interrupt = __default_interrupt); +PROVIDE(__level_7_interrupt = __default_interrupt); + +/* high level CPU interrupts */ +PROVIDE(Timer0 = __default_user_exception); +PROVIDE(Timer1 = __default_user_exception); +PROVIDE(Timer2 = __default_user_exception); +PROVIDE(Timer3 = __default_user_exception); +PROVIDE(Profiling = __default_user_exception); +PROVIDE(NMI = __default_user_exception); +PROVIDE(Software0 = __default_user_exception); +PROVIDE(Software1 = __default_user_exception); + +/* low level exception/interrupt, which must be overridden using naked functions */ +PROVIDE(__naked_user_exception = __default_naked_exception); +PROVIDE(__naked_kernel_exception = __default_naked_exception); +PROVIDE(__naked_double_exception = __default_naked_double_exception); +PROVIDE(__naked_level_2_interrupt = __default_naked_level_2_interrupt); +PROVIDE(__naked_level_3_interrupt = __default_naked_level_3_interrupt); +PROVIDE(__naked_level_4_interrupt = __default_naked_level_4_interrupt); +PROVIDE(__naked_level_5_interrupt = __default_naked_level_5_interrupt); +PROVIDE(__naked_level_6_interrupt = __default_naked_level_6_interrupt); +PROVIDE(__naked_level_7_interrupt = __default_naked_level_7_interrupt); + + +/* needed to force inclusion of the vectors */ +EXTERN(__default_exception); +EXTERN(__default_double_exception); +EXTERN(__default_interrupt); + +EXTERN(__default_naked_exception); +EXTERN(__default_naked_double_exception); +EXTERN(__default_naked_level_2_interrupt); +EXTERN(__default_naked_level_3_interrupt); +EXTERN(__default_naked_level_4_interrupt); +EXTERN(__default_naked_level_5_interrupt); +EXTERN(__default_naked_level_6_interrupt); +EXTERN(__default_naked_level_7_interrupt); + + +/* Define output sections */ +SECTIONS { + + .vectors : + { + /* + Each vector has 64 bytes that it must fit inside. For each vector we calculate the size of the previous one, + and subtract that from 64 and start the new vector there. + */ + _init_start = ABSOLUTE(.); + . = ALIGN(64); + KEEP(*(.WindowOverflow4.text)); + . = ALIGN(64); + KEEP(*(.WindowUnderflow4.text)); + . = ALIGN(64); + KEEP(*(.WindowOverflow8.text)); + . = ALIGN(64); + KEEP(*(.WindowUnderflow8.text)); + . = ALIGN(64); + KEEP(*(.WindowOverflow12.text)); + . = ALIGN(64); + KEEP(*(.WindowUnderflow12.text)); + . = ALIGN(64); + KEEP(*(.Level2InterruptVector.text)); + . = ALIGN(64); + KEEP(*(.Level3InterruptVector.text)); + . = ALIGN(64); + KEEP(*(.Level4InterruptVector.text)); + . = ALIGN(64); + KEEP(*(.Level5InterruptVector.text)); + . = ALIGN(64); + KEEP(*(.DebugExceptionVector.text)); + . = ALIGN(64); + KEEP(*(.NMIExceptionVector.text)); + . = ALIGN(64); + KEEP(*(.KernelExceptionVector.text)); + . = ALIGN(64); + KEEP(*(.UserExceptionVector.text)); + . = ALIGN(128); + KEEP(*(.DoubleExceptionVector.text)); + . = ALIGN(64); + . = ALIGN(0x400); + _init_end = ABSOLUTE(.); + } > vectors_seg +} diff --git a/xtensa-lx-rt/interrupt_level_masks.rs.jinja b/xtensa-lx-rt/interrupt_level_masks.rs.jinja new file mode 100644 index 000000000..3b408f621 --- /dev/null +++ b/xtensa-lx-rt/interrupt_level_masks.rs.jinja @@ -0,0 +1,23 @@ +pub enum CpuInterruptLevel { + Level1, + Level2, + Level3, + Level4, + Level5, + Level6, + Level7, +} + +impl CpuInterruptLevel { + pub fn mask(&self) -> u32 { + match &self { + CpuInterruptLevel::Level1 => {{ XCHAL_INTLEVEL1_MASK }}u32, + CpuInterruptLevel::Level2 => {{ XCHAL_INTLEVEL2_MASK }}u32, + CpuInterruptLevel::Level3 => {{ XCHAL_INTLEVEL3_MASK }}u32, + CpuInterruptLevel::Level4 => {{ XCHAL_INTLEVEL4_MASK }}u32, + CpuInterruptLevel::Level5 => {{ XCHAL_INTLEVEL5_MASK }}u32, + CpuInterruptLevel::Level6 => {{ XCHAL_INTLEVEL6_MASK }}u32, + CpuInterruptLevel::Level7 => {{ XCHAL_INTLEVEL7_MASK }}u32, + } + } +} diff --git a/xtensa-lx-rt/procmacros/Cargo.toml b/xtensa-lx-rt/procmacros/Cargo.toml new file mode 100644 index 000000000..ff9bd581a --- /dev/null +++ b/xtensa-lx-rt/procmacros/Cargo.toml @@ -0,0 +1,24 @@ +[package] +name = "xtensa-lx-rt-proc-macros" +authors = [ + "Jorge Aparicio ", + "Arjan Mels ", + "Scott Mabin ", +] +version = "0.2.2" +edition = "2021" +rust-version = "1.65" +description = "Attributes re-exported in `xtensa-lx-rt`" +repository = "https://github.com/esp-rs/esp-hal" +license = "MIT OR Apache-2.0" +keywords = ["esp32", "xtensa-lx-rt", "runtime", "startup"] +categories = ["embedded", "no-std"] + +[lib] +proc-macro = true + +[dependencies] +darling = "0.20" +proc-macro2 = "1.0" +quote = "1.0" +syn = { version = "2.0", features = ["extra-traits", "full"] } diff --git a/xtensa-lx-rt/procmacros/src/lib.rs b/xtensa-lx-rt/procmacros/src/lib.rs new file mode 100644 index 000000000..1b601717b --- /dev/null +++ b/xtensa-lx-rt/procmacros/src/lib.rs @@ -0,0 +1,574 @@ +//! Internal implementation details of `xtensa-lx-rt`. +//! +//! Do not use this crate directly. + +#![deny(warnings)] + +extern crate proc_macro; + +use std::collections::HashSet; + +use darling::ast::NestedMeta; +use proc_macro::TokenStream; +use proc_macro2::Span; +use quote::quote; +use syn::{ + parse, + parse_macro_input, + spanned::Spanned, + AttrStyle, + Attribute, + FnArg, + Ident, + Item, + ItemFn, + ItemStatic, + ReturnType, + StaticMutability, + Stmt, + Type, + Visibility, +}; + +/// Marks a function as the main function to be called on program start +#[proc_macro_attribute] +pub fn entry(args: TokenStream, input: TokenStream) -> TokenStream { + let mut f = parse_macro_input!(input as ItemFn); + + // check the function signature + let valid_signature = f.sig.constness.is_none() + && f.vis == Visibility::Inherited + && f.sig.abi.is_none() + && f.sig.inputs.is_empty() + && f.sig.generics.params.is_empty() + && f.sig.generics.where_clause.is_none() + && f.sig.variadic.is_none() + && match f.sig.output { + ReturnType::Default => false, + ReturnType::Type(_, ref ty) => match **ty { + Type::Never(_) => true, + _ => false, + }, + }; + + if !valid_signature { + return parse::Error::new( + f.span(), + "`#[entry]` function must have signature `[unsafe] fn() -> !`", + ) + .to_compile_error() + .into(); + } + + if !args.is_empty() { + return parse::Error::new(Span::call_site(), "This attribute accepts no arguments") + .to_compile_error() + .into(); + } + + let (statics, stmts) = match extract_static_muts(f.block.stmts) { + Err(e) => return e.to_compile_error().into(), + Ok(x) => x, + }; + + f.sig.ident = Ident::new( + &format!("__xtensa_lx_rt_{}", f.sig.ident), + Span::call_site(), + ); + f.sig.inputs.extend(statics.iter().map(|statik| { + let ident = &statik.ident; + let ty = &statik.ty; + let attrs = &statik.attrs; + + // Note that we use an explicit `'static` lifetime for the entry point + // arguments. This makes it more flexible, and is sound here, since the + // entry will not be called again, ever. + syn::parse::( + quote!(#[allow(non_snake_case)] #(#attrs)* #ident: &'static mut #ty).into(), + ) + .unwrap() + })); + f.block.stmts = stmts; + + let tramp_ident = Ident::new(&format!("{}_trampoline", f.sig.ident), Span::call_site()); + let ident = &f.sig.ident; + + let resource_args = statics + .iter() + .map(|statik| { + let (ref cfgs, ref attrs) = extract_cfgs(statik.attrs.clone()); + let ident = &statik.ident; + let ty = &statik.ty; + let expr = &statik.expr; + quote! { + #(#cfgs)* + { + #(#attrs)* + static mut #ident: #ty = #expr; + &mut #ident + } + } + }) + .collect::>(); + + if let Err(error) = check_attr_whitelist(&f.attrs, WhiteListCaller::Entry) { + return error; + } + + let (ref cfgs, ref attrs) = extract_cfgs(f.attrs.clone()); + + quote!( + #(#cfgs)* + #(#attrs)* + #[doc(hidden)] + #[export_name = "main"] + pub unsafe extern "C" fn #tramp_ident() { + #ident( + #(#resource_args),* + ) + } + + #[allow(clippy::inline_always)] + #[inline(always)] + #f + ) + .into() +} + +/// Marks a function as the exception handler +#[proc_macro_attribute] +pub fn exception(args: TokenStream, input: TokenStream) -> TokenStream { + let mut f = parse_macro_input!(input as ItemFn); + + if !args.is_empty() { + return parse::Error::new(Span::call_site(), "This attribute accepts no arguments") + .to_compile_error() + .into(); + } + + if let Err(error) = check_attr_whitelist(&f.attrs, WhiteListCaller::Exception) { + return error; + } + + let valid_signature = f.sig.constness.is_none() + && f.vis == Visibility::Inherited + && f.sig.abi.is_none() + && f.sig.inputs.len() <= 2 + && f.sig.generics.params.is_empty() + && f.sig.generics.where_clause.is_none() + && f.sig.variadic.is_none() + && match f.sig.output { + ReturnType::Default => true, + ReturnType::Type(_, ref ty) => match **ty { + Type::Tuple(ref tuple) => tuple.elems.is_empty(), + Type::Never(..) => true, + _ => false, + }, + }; + + if !valid_signature { + return parse::Error::new( + f.span(), + "`#[exception]` handlers must have signature `[unsafe] fn([ExceptionCause[, Context]) [-> !]`", + ) + .to_compile_error() + .into(); + } + + let (statics, stmts) = match extract_static_muts(f.block.stmts) { + Err(e) => return e.to_compile_error().into(), + Ok(x) => x, + }; + + f.sig.ident = Ident::new(&format!("__xtensa_lx_6_{}", f.sig.ident), Span::call_site()); + f.sig.inputs.extend(statics.iter().map(|statik| { + let ident = &statik.ident; + let ty = &statik.ty; + let attrs = &statik.attrs; + syn::parse::(quote!(#[allow(non_snake_case)] #(#attrs)* #ident: &mut #ty).into()) + .unwrap() + })); + f.block.stmts = stmts; + + let (ref cfgs, ref attrs) = extract_cfgs(f.attrs.clone()); + + quote!( + #(#cfgs)* + #(#attrs)* + #[doc(hidden)] + #[export_name = "__user_exception"] + #f + ) + .into() +} + +/// Marks a function as the interrupt handler, with optional interrupt level +/// indicated +/// +/// When the function is also marked `#[naked]`, it is a low-level interrupt +/// handler: no entry and exit code to store processor state will be generated. +/// The user needs to ensure that all registers which are used are saved and +/// restored and that the proper return instruction is used. +#[proc_macro_attribute] +pub fn interrupt(args: TokenStream, input: TokenStream) -> TokenStream { + let mut f: ItemFn = syn::parse(input).expect("`#[interrupt]` must be applied to a function"); + + let attr_args = match NestedMeta::parse_meta_list(args.into()) { + Ok(v) => v, + Err(e) => { + return TokenStream::from(darling::Error::from(e).write_errors()); + } + }; + + if attr_args.len() > 1 { + return parse::Error::new( + Span::call_site(), + "This attribute accepts zero or 1 arguments", + ) + .to_compile_error() + .into(); + } + + let mut level = 1; + + if attr_args.len() == 1 { + match &attr_args[0] { + NestedMeta::Lit(syn::Lit::Int(lit_int)) => match lit_int.base10_parse::() { + Ok(x) => level = x, + Err(_) => { + return parse::Error::new( + Span::call_site(), + "This attribute accepts an integer attribute", + ) + .to_compile_error() + .into() + } + }, + _ => { + return parse::Error::new( + Span::call_site(), + "This attribute accepts an integer attribute", + ) + .to_compile_error() + .into() + } + } + } + + if let Err(error) = check_attr_whitelist(&f.attrs, WhiteListCaller::Interrupt) { + return error; + } + + let naked = f.attrs.iter().position(|x| eq(x, "naked")).is_some(); + + let ident_s = if naked { + format!("__naked_level_{}_interrupt", level) + } else { + format!("__level_{}_interrupt", level) + }; + + if naked && (level < 2 || level > 7) { + return parse::Error::new( + f.span(), + "`#[naked]` `#[interrupt]` handlers must have interrupt level >=2 and <=7", + ) + .to_compile_error() + .into(); + } else if !naked && (level < 1 || level > 7) { + return parse::Error::new( + f.span(), + "`#[interrupt]` handlers must have interrupt level >=1 and <=7", + ) + .to_compile_error() + .into(); + } + + let valid_signature = f.sig.constness.is_none() + && f.vis == Visibility::Inherited + && f.sig.abi.is_none() + && ((!naked && f.sig.inputs.len() <= 2) || (naked && f.sig.inputs.len() == 0)) + && f.sig.generics.params.is_empty() + && f.sig.generics.where_clause.is_none() + && f.sig.variadic.is_none() + && match f.sig.output { + ReturnType::Default => true, + ReturnType::Type(_, ref ty) => match **ty { + Type::Tuple(ref tuple) => tuple.elems.is_empty(), + Type::Never(..) => true, + _ => false, + }, + }; + + if !valid_signature { + if naked { + return parse::Error::new( + f.span(), + "`#[naked]` `#[interrupt]` handlers must have signature `[unsafe] fn() [-> !]`", + ) + .to_compile_error() + .into(); + } else { + return parse::Error::new( + f.span(), + "`#[interrupt]` handlers must have signature `[unsafe] fn([u32[, Context]]) [-> !]`", + ) + .to_compile_error() + .into(); + } + } + + let (statics, stmts) = match extract_static_muts(f.block.stmts.iter().cloned()) { + Err(e) => return e.to_compile_error().into(), + Ok(x) => x, + }; + + let inputs = f.sig.inputs.clone(); + + let args = inputs.iter().map(|arg| match arg { + syn::FnArg::Typed(x) => { + let pat = &*x.pat; + quote!(#pat) + } + _ => quote!(#arg), + }); + + f.sig.ident = Ident::new(&format!("__xtensa_lx_6_{}", f.sig.ident), Span::call_site()); + f.sig.inputs.extend(statics.iter().map(|statik| { + let ident = &statik.ident; + let ty = &statik.ty; + let attrs = &statik.attrs; + syn::parse::(quote!(#[allow(non_snake_case)] #(#attrs)* #ident: &mut #ty).into()) + .unwrap() + })); + f.block.stmts = stmts; + + let tramp_ident = Ident::new(&format!("{}_trampoline", f.sig.ident), Span::call_site()); + let ident = &f.sig.ident; + + let resource_args = statics + .iter() + .map(|statik| { + let (ref cfgs, ref attrs) = extract_cfgs(statik.attrs.clone()); + let ident = &statik.ident; + let ty = &statik.ty; + let expr = &statik.expr; + quote! { + #(#cfgs)* + { + #(#attrs)* + static mut #ident: #ty = #expr; + &mut #ident + } + } + }) + .collect::>(); + + let (ref cfgs, ref attrs) = extract_cfgs(f.attrs.clone()); + + if naked { + quote!( + #(#cfgs)* + #(#attrs)* + #[doc(hidden)] + #[export_name = #ident_s] + pub unsafe extern "C" fn #tramp_ident() { + #ident( + #(#resource_args),* + ) + } + + #[doc(hidden)] + #[allow(clippy::inline_always)] + #[inline(always)] + #f + ) + .into() + } else { + quote!( + #(#cfgs)* + #(#attrs)* + #[doc(hidden)] + #[export_name = #ident_s] + pub unsafe extern "C" fn #tramp_ident( + level: u32, + frame: xtensa_lx_rt::exception::Context + ) { + #ident(#(#args),* + #(#resource_args),* + ) + } + + #[allow(clippy::inline_always)] + #[inline(always)] + #f + ) + .into() + } +} + +/// Marks a function as the pre_init function. This function is called before +/// main and *before the memory is initialized*. +#[proc_macro_attribute] +pub fn pre_init(args: TokenStream, input: TokenStream) -> TokenStream { + let f = parse_macro_input!(input as ItemFn); + + // check the function signature + let valid_signature = f.sig.constness.is_none() + && f.vis == Visibility::Inherited + && f.sig.unsafety.is_some() + && f.sig.abi.is_none() + && f.sig.inputs.is_empty() + && f.sig.generics.params.is_empty() + && f.sig.generics.where_clause.is_none() + && f.sig.variadic.is_none() + && match f.sig.output { + ReturnType::Default => true, + ReturnType::Type(_, ref ty) => match **ty { + Type::Tuple(ref tuple) => tuple.elems.is_empty(), + _ => false, + }, + }; + + if !valid_signature { + return parse::Error::new( + f.span(), + "`#[pre_init]` function must have signature `unsafe fn()`", + ) + .to_compile_error() + .into(); + } + + if !args.is_empty() { + return parse::Error::new(Span::call_site(), "This attribute accepts no arguments") + .to_compile_error() + .into(); + } + + if let Err(error) = check_attr_whitelist(&f.attrs, WhiteListCaller::PreInit) { + return error; + } + + let attrs = f.attrs; + let ident = f.sig.ident; + let block = f.block; + + quote!( + #[export_name = "__pre_init"] + #[allow(missing_docs)] // we make a private fn public, which can trigger this lint + #(#attrs)* + pub unsafe fn #ident() #block + ) + .into() +} + +/// Extracts `static mut` vars from the beginning of the given statements +fn extract_static_muts( + stmts: impl IntoIterator, +) -> Result<(Vec, Vec), parse::Error> { + let mut istmts = stmts.into_iter(); + + let mut seen = HashSet::new(); + let mut statics = vec![]; + let mut stmts = vec![]; + while let Some(stmt) = istmts.next() { + match stmt { + Stmt::Item(Item::Static(var)) => match var.mutability { + StaticMutability::Mut(_) => { + if seen.contains(&var.ident) { + return Err(parse::Error::new( + var.ident.span(), + format!("the name `{}` is defined multiple times", var.ident), + )); + } + + seen.insert(var.ident.clone()); + statics.push(var); + } + StaticMutability::None => { + stmts.push(Stmt::Item(Item::Static(var))); + } + _ => unimplemented!(), // `StaticMutability` is `#[non_exhaustive]` + }, + _ => { + stmts.push(stmt); + break; + } + } + } + + stmts.extend(istmts); + + Ok((statics, stmts)) +} + +fn extract_cfgs(attrs: Vec) -> (Vec, Vec) { + let mut cfgs = vec![]; + let mut not_cfgs = vec![]; + + for attr in attrs { + if eq(&attr, "cfg") { + cfgs.push(attr); + } else { + not_cfgs.push(attr); + } + } + + (cfgs, not_cfgs) +} + +enum WhiteListCaller { + Entry, + Exception, + Interrupt, + PreInit, +} + +fn check_attr_whitelist(attrs: &[Attribute], caller: WhiteListCaller) -> Result<(), TokenStream> { + let whitelist = &[ + "doc", + "link_section", + "cfg", + "allow", + "warn", + "deny", + "forbid", + "cold", + "ram", + ]; + + 'o: for attr in attrs { + for val in whitelist { + if eq(&attr, &val) { + continue 'o; + } + } + + let err_str = match caller { + WhiteListCaller::Entry => "this attribute is not allowed on a xtensa-lx-rt entry point", + WhiteListCaller::Exception => { + "this attribute is not allowed on an exception handler controlled by xtensa-lx-rt" + } + WhiteListCaller::Interrupt => { + if eq(&attr, "naked") { + continue 'o; + } + + "this attribute is not allowed on an interrupt handler controlled by xtensa-lx-rt" + } + WhiteListCaller::PreInit => { + "this attribute is not allowed on a pre-init controlled by xtensa-lx-rt" + } + }; + + return Err(parse::Error::new(attr.span(), &err_str) + .to_compile_error() + .into()); + } + + Ok(()) +} + +/// Returns `true` if `attr.path` matches `name` +fn eq(attr: &Attribute, name: &str) -> bool { + attr.style == AttrStyle::Outer && attr.path().is_ident(name) +} diff --git a/xtensa-lx-rt/src/exception.rs b/xtensa-lx-rt/src/exception.rs new file mode 100644 index 000000000..a088e4f3f --- /dev/null +++ b/xtensa-lx-rt/src/exception.rs @@ -0,0 +1,121 @@ +//! Exception handling +//! +//! Currently specialized for ESP32 (LX6) configuration: which extra registers +//! to store, how many interrupt levels etc. +//! +//! First level interrupts and exceptions save full processor state to the user +//! stack. This includes the coprocessor registers contrary to the esp-idf where +//! these are lazily saved. (Kernel mode option is currently not used.) +//! +//! WindowUnder/Overflow and AllocA use default Xtensa implementation. +//! +//! LoadStoreError and Unaligned are not (yet) implemented: so all accesses to +//! IRAM must be word sized and aligned. +//! +//! Syscall 0 is not (yet) implemented: it doesn't seem to be used in rust. +//! +//! Double Exceptions can only occur during the early setup of the exception +//! handler. Afterwards PS.EXCM is set to 0 to be able to handle +//! WindowUnderflow/Overflow and recursive exceptions will happen instead. +//! +//! In various places call0 are used as long jump: `j.l` syntax is not supported +//! and `call0` can always be expanded to `mov a0,label; call a0`. Care must be +//! taken since A0 is overwritten. + +mod asm; +mod context; + +pub use context::Context; + +/// EXCCAUSE register values +/// +/// General Exception Causes. (Values of EXCCAUSE special register set by +/// general exceptions, which vector to the user, kernel, or double-exception +/// vectors). +#[allow(unused)] +#[derive(Debug)] +#[repr(C)] +pub enum ExceptionCause { + /// Illegal Instruction + Illegal = 0, + /// System Call (Syscall Instruction) + Syscall = 1, + /// Instruction Fetch Error + InstrError = 2, + /// Load Store Error + LoadStoreError = 3, + /// Level 1 Interrupt + LevelOneInterrupt = 4, + /// Stack Extension Assist (movsp Instruction) For Alloca + Alloca = 5, + /// Integer Divide By Zero + DivideByZero = 6, + /// Use Of Failed Speculative Access (Not Implemented) + NextPCValueIllegal = 7, + /// Privileged Instruction + Privileged = 8, + /// Unaligned Load Or Store + Unaligned = 9, + /// Reserved + ExternalRegisterPrivilegeError = 10, + /// Reserved + ExclusiveError = 11, + /// Pif Data Error On Instruction Fetch (Rb-200x And Later) + InstrDataError = 12, + /// Pif Data Error On Load Or Store (Rb-200x And Later) + LoadStoreDataError = 13, + /// Pif Address Error On Instruction Fetch (Rb-200x And Later) + InstrAddrError = 14, + /// Pif Address Error On Load Or Store (Rb-200x And Later) + LoadStoreAddrError = 15, + /// Itlb Miss (No Itlb Entry Matches, Hw Refill Also Missed) + ItlbMiss = 16, + /// Itlb Multihit (Multiple Itlb Entries Match) + ItlbMultiHit = 17, + /// Ring Privilege Violation On Instruction Fetch + InstrRing = 18, + /// Size Restriction On Ifetch (Not Implemented) + Reserved19 = 19, + /// Cache Attribute Does Not Allow Instruction Fetch + InstrProhibited = 20, + /// Reserved + Reserved21 = 21, + /// Reserved + Reserved22 = 22, + /// Reserved + Reserved23 = 23, + /// Dtlb Miss (No Dtlb Entry Matches, Hw Refill Also Missed) + DtlbMiss = 24, + /// Dtlb Multihit (Multiple Dtlb Entries Match) + DtlbMultiHit = 25, + /// Ring Privilege Violation On Load Or Store + LoadStoreRing = 26, + /// Size Restriction On Load/Store (Not Implemented) + Reserved27 = 27, + /// Cache Attribute Does Not Allow Load + LoadProhibited = 28, + /// Cache Attribute Does Not Allow Store + StoreProhibited = 29, + /// Reserved + Reserved30 = 30, + /// Reserved + Reserved31 = 31, + /// Access To Coprocessor 0 When Disabled + Cp0Disabled = 32, + /// Access To Coprocessor 1 When Disabled + Cp1Disabled = 33, + /// Access To Coprocessor 2 When Disabled + Cp2Disabled = 34, + /// Access To Coprocessor 3 When Disabled + Cp3Disabled = 35, + /// Access To Coprocessor 4 When Disabled + Cp4Disabled = 36, + /// Access To Coprocessor 5 When Disabled + Cp5Disabled = 37, + /// Access To Coprocessor 6 When Disabled + Cp6Disabled = 38, + /// Access To Coprocessor 7 When Disabled + Cp7Disabled = 39, + + None = 255, +} diff --git a/xtensa-lx-rt/src/exception/asm.rs b/xtensa-lx-rt/src/exception/asm.rs new file mode 100644 index 000000000..d4b475774 --- /dev/null +++ b/xtensa-lx-rt/src/exception/asm.rs @@ -0,0 +1,677 @@ +use core::arch::{asm, global_asm}; + +use crate::cfg_asm; + +// we could cfg symbols away and reduce frame size depending on features enabled +// i.e the frame size is a fixed size based on all the features right now +// we know at compile time if a target has loops for example, if it doesn't +// we could cut that memory usage. +// However in order to conveniently use `addmi` we need 256-byte alignment +// anyway so wasting a bit more stack space seems to be the better option. +// Additionally there is a chunk of memory reserved for spilled registers. +global_asm!( + " + .set XT_STK_PC, 0 + .set XT_STK_PS, 4 + .set XT_STK_A0, 8 + .equ XT_STK_A1, 12 + .set XT_STK_A2, 16 + .set XT_STK_A3, 20 + .set XT_STK_A4, 24 + .set XT_STK_A5, 28 + .set XT_STK_A6, 32 + .set XT_STK_A7, 36 + .set XT_STK_A8, 40 + .set XT_STK_A9, 44 + .set XT_STK_A10, 48 + .set XT_STK_A11, 52 + .set XT_STK_A12, 56 + .set XT_STK_A13, 60 + .set XT_STK_A14, 64 + .set XT_STK_A15, 68 + .set XT_STK_SAR, 72 + .set XT_STK_EXCCAUSE, 76 + .set XT_STK_EXCVADDR, 80 + .set XT_STK_LBEG, 84 // Registers for Loop Option + .set XT_STK_LEND, 88 + .set XT_STK_LCOUNT, 92 + .set XT_STK_THREADPTR, 96 // freely usable 32-bit register intended for TLS + .set XT_STK_SCOMPARE1, 100 // Register for s32ci instruction + .set XT_STK_BR, 104 // Register for Boolean Option + .set XT_STK_ACCLO, 108 // Registers for MAC16 option + .set XT_STK_ACCHI, 112 + .set XT_STK_M0, 116 + .set XT_STK_M1, 120 + .set XT_STK_M2, 124 + .set XT_STK_M3, 128 + .set XT_STK_F64R_LO, 132 // Registers for double support option + .set XT_STK_F64R_HI, 136 + .set XT_STK_F64S, 140 + .set XT_STK_FCR, 144 // Registers for floating point coprocessor + .set XT_STK_FSR, 148 + .set XT_STK_F0, 152 + .set XT_STK_F1, 156 + .set XT_STK_F2, 160 + .set XT_STK_F3, 164 + .set XT_STK_F4, 168 + .set XT_STK_F5, 172 + .set XT_STK_F6, 176 + .set XT_STK_F7, 180 + .set XT_STK_F8, 184 + .set XT_STK_F9, 188 + .set XT_STK_F10, 192 + .set XT_STK_F11, 196 + .set XT_STK_F12, 200 + .set XT_STK_F13, 204 + .set XT_STK_F14, 208 + .set XT_STK_F15, 212 + .set XT_STK_TMP, 216 + + .set XT_STK_FRMSZ, 256 // needs to be multiple of 16 and enough additional free space + // for the registers spilled to the stack (max 8 registers / 0x20 bytes) + // multiple of 256 allows use of addmi instruction + + + + .set PS_INTLEVEL_EXCM, 3 // interrupt handlers above this level shouldn't be written in high level languages + .set PS_INTLEVEL_MASK, 0x0000000f + .set PS_EXCM, 0x00000010 + .set PS_UM, 0x00000020 + .set PS_WOE, 0x00040000 + " +); + +/// Save processor state to stack. +/// +/// *Must only be called with call0.* +/// *For spill all window registers to work WOE must be enabled on entry +/// +/// Saves all registers except PC, PS, A0, A1 +/// +/// Inputs: +/// A0 is the return address +/// A1 is the stack pointers +/// Exceptions are disabled (PS.EXCM = 1) +/// +/// Output: +/// A0 is the return address +/// A1 is the stack pointer +/// A3, A9 are used as scratch registers +/// EPC1 is changed +#[naked] +#[no_mangle] +#[link_section = ".rwtext"] +unsafe extern "C" fn save_context() { + cfg_asm!( + { + " + s32i a2, sp, +XT_STK_A2 + s32i a3, sp, +XT_STK_A3 + s32i a4, sp, +XT_STK_A4 + s32i a5, sp, +XT_STK_A5 + s32i a6, sp, +XT_STK_A6 + s32i a7, sp, +XT_STK_A7 + s32i a8, sp, +XT_STK_A8 + s32i a9, sp, +XT_STK_A9 + s32i a10, sp, +XT_STK_A10 + s32i a11, sp, +XT_STK_A11 + s32i a12, sp, +XT_STK_A12 + s32i a13, sp, +XT_STK_A13 + s32i a14, sp, +XT_STK_A14 + s32i a15, sp, +XT_STK_A15 + + rsr a3, SAR + s32i a3, sp, +XT_STK_SAR + ", + #[cfg(all(XCHAL_HAVE_CP, not(feature = "float-save-restore")))] + " + /* Disable coprocessor, any use of floats in ISRs will cause an exception unless float-save-restore feature is enabled */ + movi a3, 0 + wsr a3, CPENABLE + rsync + ", + #[cfg(XCHAL_HAVE_LOOPS)] + " + // Loop Option + rsr a3, LBEG + s32i a3, sp, +XT_STK_LBEG + rsr a3, LEND + s32i a3, sp, +XT_STK_LEND + rsr a3, LCOUNT + s32i a3, sp, +XT_STK_LCOUNT + ", + #[cfg(XCHAL_HAVE_THREADPTR)] + " + // Thread Pointer Option + rur a3, threadptr + s32i a3, sp, +XT_STK_THREADPTR + ", + #[cfg(XCHAL_HAVE_S32C1I)] + " + // Conditional Store Option + rsr a3, scompare1 + s32i a3, sp, +XT_STK_SCOMPARE1 + ", + #[cfg(XCHAL_HAVE_BOOLEANS)] + " + // Boolean Option + rsr a3, br + s32i a3, sp, +XT_STK_BR + ", + #[cfg(XCHAL_HAVE_MAC16)] + " + // MAC16 Option + rsr a3, acclo + s32i a3, sp, +XT_STK_ACCLO + rsr a3, acchi + s32i a3, sp, +XT_STK_ACCHI + rsr a3, m0 + s32i a3, sp, +XT_STK_M0 + rsr a3, m1 + s32i a3, sp, +XT_STK_M1 + rsr a3, m2 + s32i a3, sp, +XT_STK_M2 + rsr a3, m3 + s32i a3, sp, +XT_STK_M3 + ", + #[cfg(all(feature = "float-save-restore", XCHAL_HAVE_DFP_ACCEL))] + " + // Double Precision Accelerator Option + rur a3, f64r_lo + s32i a3, sp, +XT_STK_F64R_LO + rur a3, f64r_hi + s32i a3, sp, +XT_STK_F64R_HI + rur a3, f64s + s32i a3, sp, +XT_STK_F64S + ", + #[cfg(all(feature = "float-save-restore", XCHAL_HAVE_FP))] + " + // Coprocessor Option + rur a3, fcr + s32i a3, sp, +XT_STK_FCR + rur a3, fsr + s32i a3, sp, +XT_STK_FSR + ssi f0, sp, +XT_STK_F0 + ssi f1, sp, +XT_STK_F1 + ssi f2, sp, +XT_STK_F2 + ssi f3, sp, +XT_STK_F3 + ssi f4, sp, +XT_STK_F4 + ssi f5, sp, +XT_STK_F5 + ssi f6, sp, +XT_STK_F6 + ssi f7, sp, +XT_STK_F7 + ssi f8, sp, +XT_STK_F8 + ssi f9, sp, +XT_STK_F9 + ssi f10, sp, +XT_STK_F10 + ssi f11, sp, +XT_STK_F11 + ssi f12, sp, +XT_STK_F12 + ssi f13, sp, +XT_STK_F13 + ssi f14, sp, +XT_STK_F14 + ssi f15, sp, +XT_STK_F15 + ", + #[cfg(XCHAL_HAVE_WINDOWED)] + " + s32i a0, sp, +XT_STK_TMP // keep return address on the stack + + // SPILL_REGISTERS macro requires window overflow exceptions to be enabled, + // i.e. PS.EXCM cleared and PS.WOE set. + // Since we are going to clear PS.EXCM, we also need to increase INTLEVEL + // at least to XCHAL_EXCM_LEVEL. This matches that value of effective INTLEVEL + // at entry (CINTLEVEL=max(PS.INTLEVEL, XCHAL_EXCM_LEVEL) when PS.EXCM is set. + // Since WindowOverflow exceptions will trigger inside SPILL_REGISTERS, + // need to save/restore EPC1 as well. + // Note: even though a4-a15 are saved into the exception frame, we should not + // clobber them until after SPILL_REGISTERS. This is because these registers + // may contain live windows belonging to previous frames in the call stack. + // These frames will be spilled by SPILL_REGISTERS, and if the register was + // used as a temporary by this code, the temporary value would get stored + // onto the stack, instead of the real value. + // + + rsr a2, PS // to be restored after SPILL_REGISTERS + movi a0, PS_INTLEVEL_MASK + and a3, a2, a0 // get the current INTLEVEL + bgeui a3, +PS_INTLEVEL_EXCM, 1f // calculate max(INTLEVEL, XCHAL_EXCM_LEVEL) - 3 = XCHAL_EXCM_LEVEL + movi a3, PS_INTLEVEL_EXCM + 1: + movi a0, PS_WOE // clear EXCM, enable window overflow, set new INTLEVEL + or a3, a3, a0 + wsr a3, ps + rsr a0, EPC1 + + addmi sp, sp, +XT_STK_FRMSZ // go back to spill register region + SPILL_REGISTERS + addmi sp, sp, -XT_STK_FRMSZ // return the current stack pointer + + wsr a2, PS // restore to the value at entry + rsync + wsr a0, EPC1 + + l32i a0, sp, +XT_STK_TMP + ", + " + ret + ", + }, + options(noreturn) + ); +} + +global_asm!( + r#" + // Spills all active windowed registers (i.e. registers not visible as + // A0-A15) to their ABI-defined spill regions on the stack. + // It will spill registers to their reserved locations in previous frames. + // + // Unlike the Xtensa HAL implementation, this code requires that the + // EXCM and WOE bit be enabled in PS, and relies on repeated hardware + // exception handling to do the register spills. The trick is to do a + // noop write to the high registers, which the hardware will trap + // (into an overflow exception) in the case where those registers are + // already used by an existing call frame. Then it rotates the window + // and repeats until all but the A0-A3 registers of the original frame + // are guaranteed to be spilled, eventually rotating back around into + // the original frame. Advantages: + // + // - Vastly smaller code size + // + // - More easily maintained if changes are needed to window over/underflow + // exception handling. + // + // - Requires no scratch registers to do its work, so can be used safely in any + // context. + // + // - If the WOE bit is not enabled (for example, in code written for + // the CALL0 ABI), this becomes a silent noop and operates compatbily. + // + // - Hilariously it's ACTUALLY FASTER than the HAL routine. And not + // just a little bit, it's MUCH faster. With a mostly full register + // file on an LX6 core (ESP-32) I'm measuring 145 cycles to spill + // registers with this vs. 279 (!) to do it with + // xthal_spill_windows(). + + .macro SPILL_REGISTERS + and a12, a12, a12 + rotw 3 + and a12, a12, a12 + rotw 3 + and a12, a12, a12 + rotw 3 + and a12, a12, a12 + rotw 3 + and a12, a12, a12 + rotw 4 + .endm + "# +); + +global_asm!( + r#" + .macro SAVE_CONTEXT level:req + mov a0, a1 // save a1/sp + addmi sp, sp, -XT_STK_FRMSZ // only allow multiple of 256 + + s32i a0, sp, +XT_STK_A1 // save interruptee's A1/SP + s32e a0, sp, -12 // for debug backtrace + + .ifc \level,1 + rsr a0, PS + s32i a0, sp, +XT_STK_PS // save interruptee's PS + + rsr a0, EXCCAUSE + s32i a0, sp, +XT_STK_EXCCAUSE + rsr a0, EXCVADDR + s32i a0, sp, +XT_STK_EXCVADDR + .else + rsr a0, EPS\level + s32i a0, sp, +XT_STK_PS // save interruptee's PS + .endif + + rsr a0, EPC\level + s32i a0, sp, +XT_STK_PC // save interruptee's PC + s32e a0, sp, -16 // for debug backtrace + + rsr a0, EXCSAVE\level + s32i a0, sp, +XT_STK_A0 // save interruptee's A0 + + call0 save_context + + .endm + "# +); + +#[naked] +#[no_mangle] +#[link_section = ".rwtext"] +unsafe extern "C" fn restore_context() { + cfg_asm!( + { + " + l32i a3, sp, +XT_STK_SAR + wsr a3, SAR + ", + #[cfg(XCHAL_HAVE_LOOPS)] + " + // Loop Option + l32i a3, sp, +XT_STK_LBEG + wsr a3, LBEG + l32i a3, sp, +XT_STK_LEND + wsr a3, LEND + l32i a3, sp, +XT_STK_LCOUNT + wsr a3, LCOUNT + ", + #[cfg(XCHAL_HAVE_THREADPTR)] + " + // Thread Pointer Option + l32i a3, sp, +XT_STK_THREADPTR + wur a3, threadptr + ", + #[cfg(XCHAL_HAVE_S32C1I)] + " + // Conditional Store Option + l32i a3, sp, +XT_STK_SCOMPARE1 + wsr a3, scompare1 + ", + #[cfg(XCHAL_HAVE_BOOLEANS)] + " + // Boolean Option + l32i a3, sp, +XT_STK_BR + wsr a3, br + ", + #[cfg(XCHAL_HAVE_MAC16)] + " + // MAC16 Option + l32i a3, sp, +XT_STK_ACCLO + wsr a3, acclo + l32i a3, sp, +XT_STK_ACCHI + wsr a3, acchi + l32i a3, sp, +XT_STK_M0 + wsr a3, m0 + l32i a3, sp, +XT_STK_M1 + wsr a3, m1 + l32i a3, sp, +XT_STK_M2 + wsr a3, m2 + l32i a3, sp, +XT_STK_M3 + wsr a3, m3 + ", + #[cfg(all(feature = "float-save-restore", XCHAL_HAVE_DFP_ACCEL))] + " + // Double Precision Accelerator Option + l32i a3, sp, +XT_STK_F64R_LO + wur a3, f64r_lo + l32i a3, sp, +XT_STK_F64R_HI + wur a3, f64r_hi + l32i a3, sp, +XT_STK_F64S + wur a3, f64s + ", + #[cfg(all(feature = "float-save-restore", XCHAL_HAVE_FP))] + " + // Coprocessor Option + l32i a3, sp, +XT_STK_FCR + wur a3, fcr + l32i a3, sp, +XT_STK_FSR + wur a3, fsr + lsi f0, sp, +XT_STK_F0 + lsi f1, sp, +XT_STK_F1 + lsi f2, sp, +XT_STK_F2 + lsi f3, sp, +XT_STK_F3 + lsi f4, sp, +XT_STK_F4 + lsi f5, sp, +XT_STK_F5 + lsi f6, sp, +XT_STK_F6 + lsi f7, sp, +XT_STK_F7 + lsi f8, sp, +XT_STK_F8 + lsi f9, sp, +XT_STK_F9 + lsi f10, sp, +XT_STK_F10 + lsi f11, sp, +XT_STK_F11 + lsi f12, sp, +XT_STK_F12 + lsi f13, sp, +XT_STK_F13 + lsi f14, sp, +XT_STK_F14 + lsi f15, sp, +XT_STK_F15 + ", + #[cfg(all(XCHAL_HAVE_CP, not(feature = "float-save-restore")))] + " + /* Re-enable coprocessor(s) after ISR */ + movi a3, 8 /* XCHAL_CP_MAXCFG */ + wsr a3, CPENABLE + rsync + ", + " + // general registers + l32i a2, sp, +XT_STK_A2 + l32i a3, sp, +XT_STK_A3 + l32i a4, sp, +XT_STK_A4 + l32i a5, sp, +XT_STK_A5 + l32i a6, sp, +XT_STK_A6 + l32i a7, sp, +XT_STK_A7 + l32i a8, sp, +XT_STK_A8 + l32i a9, sp, +XT_STK_A9 + l32i a10, sp, +XT_STK_A10 + l32i a11, sp, +XT_STK_A11 + l32i a12, sp, +XT_STK_A12 + l32i a13, sp, +XT_STK_A13 + l32i a14, sp, +XT_STK_A14 + l32i a15, sp, +XT_STK_A15 + ret + ", + }, options(noreturn)); +} + +global_asm!( + r#" + .macro RESTORE_CONTEXT level:req + + // Restore context and return + call0 restore_context + + .ifc \level,1 + l32i a0, sp, +XT_STK_PS // retrieve interruptee's PS + wsr a0, PS + l32i a0, sp, +XT_STK_PC // retrieve interruptee's PC + wsr a0, EPC\level + .else + l32i a0, sp, +XT_STK_PS // retrieve interruptee's PS + wsr a0, EPS\level + l32i a0, sp, +XT_STK_PC // retrieve interruptee's PC + wsr a0, EPC\level + .endif + + l32i a0, sp, +XT_STK_A0 // retrieve interruptee's A0 + l32i sp, sp, +XT_STK_A1 // remove exception frame + rsync // ensure PS and EPC written + + .endm + "# +); + +/// Handle Other Exceptions or Level 1 interrupt by storing full context and +/// then calling regular function +/// +/// # Input: +/// * A0 stored in EXCSAVE1 +#[naked] +#[no_mangle] +#[link_section = ".rwtext"] +unsafe extern "C" fn __default_naked_exception() { + asm!( + " + SAVE_CONTEXT 1 + + movi a0, (PS_INTLEVEL_EXCM | PS_WOE) + wsr a0, PS + rsync + + l32i a6, sp, +XT_STK_EXCCAUSE // put cause in a6 = a2 in callee + beqi a6, 4, .Level1Interrupt + + mov a7, sp // put address of save frame in a7=a3 in callee + call4 __exception // call handler <= actual call! + + j .RestoreContext + + .Level1Interrupt: + movi a0, (1 | PS_WOE) // set PS.INTLEVEL accordingly + wsr a0, PS + rsync + + movi a6, 1 // put interrupt level in a6 = a2 in callee + mov a7, sp // put address of save frame in a7=a3 in callee + call4 __level_1_interrupt // call handler <= actual call! + + .RestoreContext: + RESTORE_CONTEXT 1 + + rfe // PS.EXCM is cleared + ", + options(noreturn) + ) +} + +/// Handle Double Exceptions by storing full context and then calling regular +/// function Double exceptions are not a normal occurrence. They indicate a bug +/// of some kind. +/// +/// # Input: +/// * A0 stored in EXCSAVE1 +#[naked] +#[no_mangle] +#[link_section = ".rwtext"] +unsafe extern "C" fn __default_naked_double_exception() { + asm!( + " + mov a0, a1 // save a1/sp + addmi sp, sp, -XT_STK_FRMSZ // only allow multiple of 256 + + s32i a0, sp, +XT_STK_A1 // save interruptee's A1/SP + s32e a0, sp, -12 // for debug backtrace + + rsr a0, PS + s32i a0, sp, +XT_STK_PS // save interruptee's PS + + rsr a0, EXCCAUSE + s32i a0, sp, +XT_STK_EXCCAUSE + rsr a0, EXCVADDR + s32i a0, sp, +XT_STK_EXCVADDR + + rsr a0, DEPC + s32i a0, sp, +XT_STK_PC // save interruptee's PC + s32e a0, sp, -16 // for debug backtrace + + rsr a0, EXCSAVE7 // ok to reuse EXCSAVE7 for double exception as long as + // double exception is not in first couple of instructions + // of level 7 handler + s32i a0, sp, +XT_STK_A0 // save interruptee's A0 + + call0 save_context + + l32i a6, sp, +XT_STK_EXCCAUSE // put cause in a6 = a2 in callee + mov a7, sp // put address of save frame in a7=a3 in callee + call4 __exception // call handler <= actual call! + + // Restore context and return + call0 restore_context + + l32i a0, sp, +XT_STK_PS // retrieve interruptee's PS + wsr a0, PS + l32i a0, sp, +XT_STK_PC // retrieve interruptee's PC + wsr a0, EPC1 + + l32i a0, sp, +XT_STK_A0 // retrieve interruptee's A0 + l32i sp, sp, +XT_STK_A1 // remove exception frame + rsync // ensure PS and EPC written + + rfde + ", + options(noreturn) + ) +} + +global_asm!( + r#" + .macro HANDLE_INTERRUPT_LEVEL level + SAVE_CONTEXT \level + + movi a0, (\level | PS_WOE) + wsr a0, PS + rsync + + movi a6, \level // put interrupt level in a6 = a2 in callee + mov a7, sp // put address of save frame in a7=a3 in callee + call4 __level_\level\()_interrupt // call handler <= actual call! + + RESTORE_CONTEXT \level + rfi \level + + .endm +"# +); + +/// Handle Level 2 Interrupt by storing full context and then calling regular +/// function +/// +/// # Input: +/// * A0 stored in EXCSAVE2 +#[naked] +#[no_mangle] +#[link_section = ".rwtext"] +unsafe extern "C" fn __default_naked_level_2_interrupt() { + asm!("HANDLE_INTERRUPT_LEVEL 2", options(noreturn)); +} + +/// Handle Level 3 Interrupt by storing full context and then calling regular +/// function +/// +/// # Input: +/// * A0 stored in EXCSAVE3 +#[naked] +#[no_mangle] +#[link_section = ".rwtext"] +unsafe extern "C" fn __default_naked_level_3_interrupt() { + asm!("HANDLE_INTERRUPT_LEVEL 3", options(noreturn)); +} + +/// Handle Level 4 Interrupt by storing full context and then calling regular +/// function +/// +/// # Input: +/// * A0 stored in EXCSAVE4 +#[naked] +#[no_mangle] +#[link_section = ".rwtext"] +unsafe extern "C" fn __default_naked_level_4_interrupt() { + asm!("HANDLE_INTERRUPT_LEVEL 4", options(noreturn)); +} + +/// Handle Level 5 Interrupt by storing full context and then calling regular +/// function +/// +/// # Input: +/// * A0 stored in EXCSAVE5 +#[naked] +#[no_mangle] +#[link_section = ".rwtext"] +unsafe extern "C" fn __default_naked_level_5_interrupt() { + asm!("HANDLE_INTERRUPT_LEVEL 5", options(noreturn)); +} + +/// Handle Level 6 (=Debug) Interrupt by storing full context and then calling +/// regular function +/// +/// # Input: +/// * A0 stored in EXCSAVE6 +#[naked] +#[no_mangle] +#[link_section = ".rwtext"] +unsafe extern "C" fn __default_naked_level_6_interrupt() { + asm!("HANDLE_INTERRUPT_LEVEL 6", options(noreturn)); +} + +/// Handle Level 7 (=NMI) Interrupt by storing full context and then calling +/// regular function +/// +/// # Input: +/// * A0 stored in EXCSAVE7 +#[naked] +#[no_mangle] +#[link_section = ".rwtext"] +unsafe extern "C" fn __default_naked_level_7_interrupt() { + asm!("HANDLE_INTERRUPT_LEVEL 7", options(noreturn)); +} diff --git a/xtensa-lx-rt/src/exception/context.rs b/xtensa-lx-rt/src/exception/context.rs new file mode 100644 index 000000000..4c4099dcd --- /dev/null +++ b/xtensa-lx-rt/src/exception/context.rs @@ -0,0 +1,427 @@ +use core::arch::asm; + +use super::ExceptionCause; + +/// State of the CPU saved when entering exception or interrupt +/// +/// Must be aligned with assembly frame format in assembly_esp32 +#[repr(C)] +#[allow(non_snake_case)] +#[derive(Debug, Clone, Copy)] +pub struct Context { + pub PC: u32, + pub PS: u32, + + pub A0: u32, + pub A1: u32, + pub A2: u32, + pub A3: u32, + pub A4: u32, + pub A5: u32, + pub A6: u32, + pub A7: u32, + pub A8: u32, + pub A9: u32, + pub A10: u32, + pub A11: u32, + pub A12: u32, + pub A13: u32, + pub A14: u32, + pub A15: u32, + pub SAR: u32, + pub EXCCAUSE: u32, + pub EXCVADDR: u32, + pub LBEG: u32, + pub LEND: u32, + pub LCOUNT: u32, + pub THREADPTR: u32, + pub SCOMPARE1: u32, + pub BR: u32, + pub ACCLO: u32, + pub ACCHI: u32, + pub M0: u32, + pub M1: u32, + pub M2: u32, + pub M3: u32, + #[cfg(all(feature = "float-save-restore", XCHAL_HAVE_DFP_ACCEL))] + pub F64R_LO: u32, + #[cfg(all(feature = "float-save-restore", XCHAL_HAVE_DFP_ACCEL))] + pub F64R_HI: u32, + #[cfg(all(feature = "float-save-restore", XCHAL_HAVE_DFP_ACCEL))] + pub F64S: u32, + #[cfg(all(feature = "float-save-restore", XCHAL_HAVE_FP))] + pub FCR: u32, + #[cfg(all(feature = "float-save-restore", XCHAL_HAVE_FP))] + pub FSR: u32, + #[cfg(all(feature = "float-save-restore", XCHAL_HAVE_FP))] + pub F0: u32, + #[cfg(all(feature = "float-save-restore", XCHAL_HAVE_FP))] + pub F1: u32, + #[cfg(all(feature = "float-save-restore", XCHAL_HAVE_FP))] + pub F2: u32, + #[cfg(all(feature = "float-save-restore", XCHAL_HAVE_FP))] + pub F3: u32, + #[cfg(all(feature = "float-save-restore", XCHAL_HAVE_FP))] + pub F4: u32, + #[cfg(all(feature = "float-save-restore", XCHAL_HAVE_FP))] + pub F5: u32, + #[cfg(all(feature = "float-save-restore", XCHAL_HAVE_FP))] + pub F6: u32, + #[cfg(all(feature = "float-save-restore", XCHAL_HAVE_FP))] + pub F7: u32, + #[cfg(all(feature = "float-save-restore", XCHAL_HAVE_FP))] + pub F8: u32, + #[cfg(all(feature = "float-save-restore", XCHAL_HAVE_FP))] + pub F9: u32, + #[cfg(all(feature = "float-save-restore", XCHAL_HAVE_FP))] + pub F10: u32, + #[cfg(all(feature = "float-save-restore", XCHAL_HAVE_FP))] + pub F11: u32, + #[cfg(all(feature = "float-save-restore", XCHAL_HAVE_FP))] + pub F12: u32, + #[cfg(all(feature = "float-save-restore", XCHAL_HAVE_FP))] + pub F13: u32, + #[cfg(all(feature = "float-save-restore", XCHAL_HAVE_FP))] + pub F14: u32, + #[cfg(all(feature = "float-save-restore", XCHAL_HAVE_FP))] + pub F15: u32, +} + +extern "Rust" { + /// The exception assembly jumps here once registers have been spilled + fn __exception(cause: ExceptionCause, save_frame: &mut Context); + /// This symbol will be provided by the user via `#[exception]` + fn __user_exception(cause: ExceptionCause, save_frame: &mut Context); + /// No attribute is supplied for this symbol as the double exception can + /// hardly occur + fn __double_exception(cause: ExceptionCause, save_frame: &mut Context); + + /// This symbol will be provided by the user via `#[interrupt(1)]` + fn __level_1_interrupt(level: u32, save_frame: &mut Context); + /// This symbol will be provided by the user via `#[interrupt(2)]` + fn __level_2_interrupt(level: u32, save_frame: &mut Context); + /// This symbol will be provided by the user via `#[interrupt(3)]` + fn __level_3_interrupt(level: u32, save_frame: &mut Context); + /// This symbol will be provided by the user via `#[interrupt(4)]` + fn __level_4_interrupt(level: u32, save_frame: &mut Context); + /// This symbol will be provided by the user via `#[interrupt(5)]` + fn __level_5_interrupt(level: u32, save_frame: &mut Context); + /// This symbol will be provided by the user via `#[interrupt(6)]` + fn __level_6_interrupt(level: u32, save_frame: &mut Context); + /// This symbol will be provided by the user via `#[interrupt(7)]` + fn __level_7_interrupt(level: u32, save_frame: &mut Context); +} + +#[no_mangle] +#[link_section = ".rwtext"] +unsafe extern "C" fn __default_exception(cause: ExceptionCause, save_frame: &mut Context) { + __user_exception(cause, save_frame) +} + +#[no_mangle] +#[link_section = ".rwtext"] +extern "C" fn __default_user_exception(cause: ExceptionCause, save_frame: &Context) { + panic!("Exception: {:?}, {:08x?}", cause, save_frame) +} + +#[no_mangle] +#[link_section = ".rwtext"] +extern "C" fn __default_interrupt(level: u32, save_frame: &Context) { + panic!("Interrupt: {:?}, {:08x?}", level, save_frame) +} + +#[no_mangle] +#[link_section = ".rwtext"] +extern "C" fn __default_double_exception(cause: ExceptionCause, save_frame: &Context) { + panic!("Double Exception: {:?}, {:08x?}", cause, save_frame) +} + +// Raw vector handlers +// +// The interrupt handlers all use special return instructions. +// rust still generates a ret.w instruction, which will never be reached. +// generation of the ret.w can be prevented by using +// core::intrinsics::unreachable, but then a break 15,1 will be generated (which +// takes 3 bytes instead of 2) or a 'loop {}', but then a jump to own address +// will be generated which is also 3 bytes. No way found yet to prevent this +// generation altogether. + +#[naked] +#[no_mangle] +#[link_section = ".KernelExceptionVector.text"] +unsafe extern "C" fn _KernelExceptionVector() { + asm!( + " + wsr a0, EXCSAVE1 // preserve a0 + rsr a0, EXCCAUSE // get exception cause + + beqi a0, 5, .AllocAException + + call0 __naked_kernel_exception + ", + options(noreturn) + ); +} + +#[naked] +#[no_mangle] +#[link_section = ".UserExceptionVector.text"] +unsafe extern "C" fn _UserExceptionVector() { + asm!( + " + wsr a0, EXCSAVE1 // preserve a0 + rsr a0, EXCCAUSE // get exception cause + + beqi a0, 5, .AllocAException + + call0 __naked_user_exception + + .AllocAException: + call0 _AllocAException + ", + options(noreturn) + ); +} + +#[naked] +#[no_mangle] +#[link_section = ".DoubleExceptionVector.text"] +unsafe extern "C" fn _DoubleExceptionVector() { + asm!( + " + wsr a0, EXCSAVE1 // preserve a0 (EXCSAVE1 can be reused as long as there + // is no double exception in the first exception until + // EXCSAVE1 is stored to the stack.) + call0 __naked_double_exception // used as long jump + ", + options(noreturn) + ); +} + +#[naked] +#[no_mangle] +#[link_section = ".Level2InterruptVector.text"] +unsafe extern "C" fn _Level2InterruptVector() { + asm!( + " + wsr a0, EXCSAVE2 // preserve a0 + call0 __naked_level_2_interrupt // used as long jump + ", + options(noreturn) + ); +} + +#[naked] +#[no_mangle] +#[link_section = ".Level3InterruptVector.text"] +unsafe extern "C" fn _Level3InterruptVector() { + asm!( + " + wsr a0, EXCSAVE3 // preserve a0 + call0 __naked_level_3_interrupt // used as long jump + ", + options(noreturn) + ); +} + +#[naked] +#[no_mangle] +#[link_section = ".Level4InterruptVector.text"] +unsafe extern "C" fn _Level4InterruptVector() { + asm!( + " + wsr a0, EXCSAVE4 // preserve a0 + call0 __naked_level_4_interrupt // used as long jump + ", + options(noreturn) + ); +} + +#[naked] +#[no_mangle] +#[link_section = ".Level5InterruptVector.text"] +unsafe extern "C" fn _Level5InterruptVector() { + asm!( + " + wsr a0, EXCSAVE5 // preserve a0 + call0 __naked_level_5_interrupt // used as long jump + ", + options(noreturn) + ); +} + +#[naked] +#[no_mangle] +#[link_section = ".DebugExceptionVector.text"] +unsafe extern "C" fn _Level6InterruptVector() { + asm!( + " + wsr a0, EXCSAVE6 // preserve a0 + call0 __naked_level_6_interrupt // used as long jump + ", + options(noreturn) + ); +} + +#[naked] +#[no_mangle] +#[link_section = ".NMIExceptionVector.text"] +unsafe extern "C" fn _Level7InterruptVector() { + asm!( + " + wsr a0, EXCSAVE7 // preserve a0 + call0 __naked_level_7_interrupt // used as long jump + ", + options(noreturn) + ); +} + +#[naked] +#[no_mangle] +#[link_section = ".WindowOverflow4.text"] +unsafe extern "C" fn _WindowOverflow4() { + asm!( + " + s32e a0, a5, -16 + s32e a1, a5, -12 + s32e a2, a5, -8 + s32e a3, a5, -4 + rfwo + ", + options(noreturn) + ); +} + +#[naked] +#[no_mangle] +#[link_section = ".WindowUnderflow4.text"] +unsafe extern "C" fn _WindowUnderflow4() { + asm!( + " + l32e a0, a5, -16 + l32e a1, a5, -12 + l32e a2, a5, -8 + l32e a3, a5, -4 + rfwu + + // inline the _AllocAException saves on the ret.w for WindowUnderflow4 + // this makes that it just fits, which is needed for the bbci instructions + + .align 4 + _AllocAException: + rsr a0, WINDOWBASE // grab WINDOWBASE before rotw changes it + rotw -1 // WINDOWBASE goes to a4, new a0-a3 are scratch + rsr a2, PS + extui a3, a2, 8, 4 // XCHAL_PS_OWB_SHIFT, XCHAL_PS_OWB_BITS + xor a3, a3, a4 // bits changed from old to current windowbase + rsr a4, EXCSAVE1 // restore original a0 (now in a4) + slli a3, a3, 8 // XCHAL_PS_OWB_SHIFT + xor a2, a2, a3 // flip changed bits in old window base + wsr a2, PS // update PS.OWB to new window base + rsync + + bbci a4, 31, _WindowUnderflow4 + rotw -1 // original a0 goes to a8 + bbci a8, 30, _WindowUnderflow8 + rotw -1 + j _WindowUnderflow12 + ", + options(noreturn) + ); +} + +#[naked] +#[no_mangle] +#[link_section = ".WindowOverflow8.text"] +unsafe extern "C" fn _WindowOverflow8() { + asm!( + " + s32e a0, a9, -16 + l32e a0, a1, -12 + + s32e a1, a9, -12 + s32e a2, a9, -8 + s32e a3, a9, -4 + s32e a4, a0, -32 + s32e a5, a0, -28 + s32e a6, a0, -24 + s32e a7, a0, -20 + rfwo + ", + options(noreturn) + ); +} + +#[naked] +#[no_mangle] +#[link_section = ".WindowUnderflow8.text"] +unsafe extern "C" fn _WindowUnderflow8() { + asm!( + " + l32e a0, a9, -16 + l32e a1, a9, -12 + l32e a2, a9, -8 + l32e a7, a1, -12 + + l32e a3, a9, -4 + l32e a4, a7, -32 + l32e a5, a7, -28 + l32e a6, a7, -24 + l32e a7, a7, -20 + rfwu + ", + options(noreturn) + ); +} + +#[naked] +#[no_mangle] +#[link_section = ".WindowOverflow12.text"] +unsafe extern "C" fn _WindowOverflow12() { + asm!( + " + s32e a0, a13, -16 + l32e a0, a1, -12 + + s32e a1, a13, -12 + s32e a2, a13, -8 + s32e a3, a13, -4 + s32e a4, a0, -48 + s32e a5, a0, -44 + s32e a6, a0, -40 + s32e a7, a0, -36 + s32e a8, a0, -32 + s32e a9, a0, -28 + s32e a10, a0, -24 + s32e a11, a0, -20 + rfwo + ", + options(noreturn) + ); +} + +#[naked] +#[no_mangle] +#[link_section = ".WindowUnderflow12.text"] +unsafe extern "C" fn _WindowUnderflow12() { + asm!( + " + l32e a0, a13, -16 + l32e a1, a13, -12 + l32e a2, a13, -8 + l32e a11, a1, -12 + + l32e a3, a13, -4 + l32e a4, a11, -48 + l32e a5, a11, -44 + l32e a6, a11, -40 + l32e a7, a11, -36 + l32e a8, a11, -32 + l32e a9, a11, -28 + l32e a10, a11, -24 + l32e a11, a11, -20 + rfwu + ", + options(noreturn) + ); +} diff --git a/xtensa-lx-rt/src/interrupt.rs b/xtensa-lx-rt/src/interrupt.rs new file mode 100644 index 000000000..c89c93eff --- /dev/null +++ b/xtensa-lx-rt/src/interrupt.rs @@ -0,0 +1,3 @@ +//! Interrupts + +include!(concat!(env!("OUT_DIR"), "/interrupt_level_masks.rs")); diff --git a/xtensa-lx-rt/src/lib.rs b/xtensa-lx-rt/src/lib.rs new file mode 100644 index 000000000..a3ee0e054 --- /dev/null +++ b/xtensa-lx-rt/src/lib.rs @@ -0,0 +1,172 @@ +//! Minimal startup/runtime for Xtensa LX CPUs. +//! +//! ## Minimum Supported Rust Version (MSRV) +//! +//! This crate is guaranteed to compile on stable Rust 1.65 and up. It might +//! compile with older versions but that may change in any new patch release. +//! +//! ## Feature Flags +#![doc = document_features::document_features!()] +#![doc(html_logo_url = "https://avatars.githubusercontent.com/u/46717278")] +#![allow(asm_sub_register, named_asm_labels)] +#![feature(asm_experimental_arch, naked_functions)] +#![no_std] + +use core::{ + arch::asm, + ptr::{addr_of, addr_of_mut}, +}; + +pub use macros::{entry, exception, interrupt, pre_init}; +pub use r0::{init_data, zero_bss}; +pub use xtensa_lx; + +pub mod exception; +pub mod interrupt; + +#[doc(hidden)] +#[no_mangle] +pub unsafe extern "C" fn DefaultPreInit() {} + +#[doc(hidden)] +#[no_mangle] +pub unsafe extern "C" fn Reset() -> ! { + // These symbols come from `link.x` + extern "C" { + static mut _bss_start: u32; + static mut _bss_end: u32; + + static mut _data_start: u32; + static mut _data_end: u32; + static _sidata: u32; + + static mut _init_start: u32; + + } + + extern "Rust" { + // This symbol will be provided by the user via `#[entry]` + fn main() -> !; + + // This symbol will be provided by the user via `#[pre_init]` + fn __pre_init(); + + fn __post_init(); + + fn __zero_bss() -> bool; + + fn __init_data() -> bool; + } + + __pre_init(); + + if __zero_bss() { + r0::zero_bss(addr_of_mut!(_bss_start), addr_of_mut!(_bss_end)); + } + + if __init_data() { + r0::init_data(addr_of_mut!(_data_start), addr_of_mut!(_data_end), &_sidata); + } + + // Copy of data segment is done by bootloader + + // According to 4.4.6.2 of the xtensa isa, ccount and compare are undefined on + // reset, set all values to zero to disable + reset_internal_timers(); + + // move vec table + set_vecbase(addr_of!(_init_start)); + + __post_init(); + + main(); +} + +#[doc(hidden)] +#[no_mangle] +#[rustfmt::skip] +pub unsafe extern "Rust" fn default_post_init() {} + +// We redefine these functions to avoid pulling in `xtensa-lx` as a dependency: + +#[doc(hidden)] +#[inline] +unsafe fn reset_internal_timers() { + #[cfg(any( + XCHAL_HAVE_TIMER0, + XCHAL_HAVE_TIMER1, + XCHAL_HAVE_TIMER2, + XCHAL_HAVE_TIMER3 + ))] + { + let value = 0; + cfg_asm!( + { + #[cfg(XCHAL_HAVE_TIMER0)] + "wsr.ccompare0 {0}", + #[cfg(XCHAL_HAVE_TIMER1)] + "wsr.ccompare1 {0}", + #[cfg(XCHAL_HAVE_TIMER2)] + "wsr.ccompare2 {0}", + #[cfg(XCHAL_HAVE_TIMER3)] + "wsr.ccompare3 {0}", + "isync", + }, in(reg) value, options(nostack)); + } +} + +// CPU Interrupts +extern "C" { + #[cfg(XCHAL_HAVE_TIMER0)] + pub fn Timer0(level: u32, save_frame: &mut crate::exception::Context); + #[cfg(XCHAL_HAVE_TIMER1)] + pub fn Timer1(level: u32, save_frame: &mut crate::exception::Context); + #[cfg(XCHAL_HAVE_TIMER2)] + pub fn Timer2(level: u32, save_frame: &mut crate::exception::Context); + #[cfg(XCHAL_HAVE_TIMER3)] + pub fn Timer3(level: u32, save_frame: &mut crate::exception::Context); + + #[cfg(XCHAL_HAVE_PROFILING)] + pub fn Profiling(level: u32, save_frame: &mut crate::exception::Context); + + #[cfg(XCHAL_HAVE_SOFTWARE0)] + pub fn Software0(level: u32, save_frame: &mut crate::exception::Context); + #[cfg(XCHAL_HAVE_SOFTWARE1)] + pub fn Software1(level: u32, save_frame: &mut crate::exception::Context); + + #[cfg(XCHAL_HAVE_NMI)] + pub fn NMI(level: u32, save_frame: &mut crate::exception::Context); +} + +#[doc(hidden)] +#[inline] +unsafe fn set_vecbase(base: *const u32) { + asm!("wsr.vecbase {0}", in(reg) base, options(nostack)); +} + +#[doc(hidden)] +#[no_mangle] +#[rustfmt::skip] +pub extern "Rust" fn default_mem_hook() -> bool { + true // default to zeroing bss & initializing data +} + +#[doc(hidden)] +#[macro_export] +macro_rules! cfg_asm { + (@inner, [$($x:tt)*], [$($opts:tt)*], ) => { + asm!($($x)* $($opts)*) + }; + (@inner, [$($x:tt)*], [$($opts:tt)*], #[cfg($meta:meta)] $asm:literal, $($rest:tt)*) => { + #[cfg($meta)] + cfg_asm!(@inner, [$($x)* $asm,], [$($opts)*], $($rest)*); + #[cfg(not($meta))] + cfg_asm!(@inner, [$($x)*], [$($opts)*], $($rest)*) + }; + (@inner, [$($x:tt)*], [$($opts:tt)*], $asm:literal, $($rest:tt)*) => { + cfg_asm!(@inner, [$($x)* $asm,], [$($opts)*], $($rest)*) + }; + ({$($asms:tt)*}, $($opts:tt)*) => { + cfg_asm!(@inner, [], [$($opts)*], $($asms)*) + }; +} diff --git a/xtensa-lx-rt/xtensa.in.x b/xtensa-lx-rt/xtensa.in.x new file mode 100644 index 000000000..76c1e5761 --- /dev/null +++ b/xtensa-lx-rt/xtensa.in.x @@ -0,0 +1,79 @@ + +/* before memory.x to allow override */ +ENTRY(Reset) + +INCLUDE memory.x + +/* after memory.x to allow override */ +PROVIDE(__pre_init = DefaultPreInit); +PROVIDE(__zero_bss = default_mem_hook); +PROVIDE(__init_data = default_mem_hook); +PROVIDE(__post_init = default_post_init); + +INCLUDE exception.x + +SECTIONS { + .text : ALIGN(4) + { + _stext = .; + . = ALIGN (4); + _text_start = ABSOLUTE(.); + . = ALIGN (4); + *(.literal .text .literal.* .text.*) + _text_end = ABSOLUTE(.); + _etext = .; + } > ROTEXT + + .rodata : ALIGN(4) + { + _rodata_start = ABSOLUTE(.); + . = ALIGN (4); + *(.rodata .rodata.*) + _rodata_end = ABSOLUTE(.); + } > RODATA + + .data : ALIGN(4) + { + _data_start = ABSOLUTE(.); + . = ALIGN (4); + *(.data .data.*) + _data_end = ABSOLUTE(.); + } > RWDATA AT > RODATA + + /* LMA of .data */ + _sidata = LOADADDR(.data); + + .bss (NOLOAD) : ALIGN(4) + { + _bss_start = ABSOLUTE(.); + . = ALIGN (4); + *(.bss .bss.* COMMON) + _bss_end = ABSOLUTE(.); + } > RWDATA + + .noinit (NOLOAD) : ALIGN(4) + { + . = ALIGN(4); + *(.noinit .noinit.*) + } > RWDATA + + .rwtext : ALIGN(4) + { + . = ALIGN (4); + *(.rwtext.literal .rwtext .rwtext.literal.* .rwtext.*) + } > RWTEXT + + /* must be last segment using RWTEXT */ + .text_heap_start (NOLOAD) : ALIGN(4) + { + . = ALIGN (4); + _text_heap_start = ABSOLUTE(.); + } > RWTEXT + + /* must be last segment using RWDATA */ + .heap_start (NOLOAD) : ALIGN(4) + { + . = ALIGN (4); + _heap_start = ABSOLUTE(.); + } > RWDATA +} diff --git a/xtensa-lx/Cargo.toml b/xtensa-lx/Cargo.toml new file mode 100644 index 000000000..b3c658ad1 --- /dev/null +++ b/xtensa-lx/Cargo.toml @@ -0,0 +1,24 @@ +[package] +name = "xtensa-lx" +version = "0.9.0" +edition = "2021" +rust-version = "1.65" +description = "Low-level access to Xtensa LX processors and peripherals" +repository = "https://github.com/esp-rs/esp-hal" +license = "MIT OR Apache-2.0" +categories = ["embedded", "hardware-support", "no-std"] +keywords = ["lx", "peripheral", "register", "xtensa"] +links = "xtensa-lx" + +[package.metadata.docs.rs] +features = ["spin"] + +[dependencies] +bare-metal = "1.0.0" +document-features = "0.2.8" +mutex-trait = "0.2.0" +spin = { version = "0.9.8", optional = true } + +[features] +## Use the [spin] package for synchronization +spin = ["dep:spin"] diff --git a/xtensa-lx/README.md b/xtensa-lx/README.md new file mode 100644 index 000000000..b51154f38 --- /dev/null +++ b/xtensa-lx/README.md @@ -0,0 +1,32 @@ +# `xtensa-lx` + +[![Crates.io](https://img.shields.io/crates/v/xtensa-lx?labelColor=1C2C2E&color=C96329&logo=Rust&style=flat-square)](https://crates.io/crates/xtensa-lx) +[![docs.rs](https://img.shields.io/docsrs/xtensa-lx?labelColor=1C2C2E&color=C96329&logo=rust&style=flat-square)](https://docs.rs/xtensa-lx) +![Crates.io](https://img.shields.io/crates/l/xtensa-lx?labelColor=1C2C2E&style=flat-square) +[![Matrix](https://img.shields.io/matrix/esp-rs:matrix.org?label=join%20matrix&labelColor=1C2C2E&color=BEC5C9&logo=matrix&style=flat-square)](https://matrix.to/#/#esp-rs:matrix.org) + +Low level access to Xtensa LX processors. This crate currently supports the following CPUs: + +| Feature | Supported CPUs | +| --------- | ---------------- | +| `esp32` | ESP32 (_LX6_) | +| `esp32s2` | ESP32-S2 (_LX7_) | +| `esp32s3` | ESP32-S3 (_LX7_) | + +## [Documentation](https://docs.rs/crate/xtensa-lx) + +## License + +Licensed under either of + +- Apache License, Version 2.0 ([LICENSE-APACHE](../LICENSE-APACHE) or + http://www.apache.org/licenses/LICENSE-2.0) +- MIT license ([LICENSE-MIT](../LICENSE-MIT) or http://opensource.org/licenses/MIT) + +at your option. + +### Contribution + +Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the +work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any +additional terms or conditions. diff --git a/xtensa-lx/build.rs b/xtensa-lx/build.rs new file mode 100644 index 000000000..56354ee4c --- /dev/null +++ b/xtensa-lx/build.rs @@ -0,0 +1,6 @@ +use std::{env, path::PathBuf}; + +fn main() { + let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap()); + println!("cargo:rustc-link-search={}", out_dir.display()); +} diff --git a/xtensa-lx/src/interrupt.rs b/xtensa-lx/src/interrupt.rs new file mode 100644 index 000000000..c899398af --- /dev/null +++ b/xtensa-lx/src/interrupt.rs @@ -0,0 +1,174 @@ +//! Interrupts + +use core::arch::asm; + +pub use bare_metal::CriticalSection; + +/// Trait for enums of external interrupt numbers. +/// +/// This trait should be implemented by a peripheral access crate (PAC) +/// on its enum of available external interrupts for a specific device. +/// Each variant must convert to a u16 of its interrupt number, +/// which is its exception number - 16. +/// +/// # Safety +/// +/// This trait must only be implemented on enums of device interrupts. Each +/// enum variant must represent a distinct value (no duplicates are permitted), +/// and must always return the same value (do not change at runtime). +/// +/// These requirements ensure safe nesting of critical sections. +pub unsafe trait InterruptNumber: Copy { + /// Return the interrupt number associated with this variant. + /// + /// See trait documentation for safety requirements. + fn number(self) -> u16; +} + +/// Disables all interrupts and return the previous settings +#[inline] +pub fn disable() -> u32 { + unsafe { set_mask(0) } +} + +/// Enables all the interrupts +/// +/// # Safety +/// +/// - Do not call this function inside an `interrupt::free` critical section +#[inline] +pub unsafe fn enable() -> u32 { + set_mask(!0) +} + +/// Enables specific interrupts and returns the previous setting +/// +/// # Safety +/// +/// - Do not call this function inside an `interrupt::free` critical section +#[inline] +pub unsafe fn set_mask(mut mask: u32) -> u32 { + asm!(" + xsr {0}, intenable + rsync + ", + inout(reg) mask, options(nostack) + ); + mask +} + +/// Disables specific interrupts and returns the previous settings +#[inline] +pub fn disable_mask(mask: u32) -> u32 { + let mut prev: u32 = 0; + let _dummy: u32; + unsafe { + asm!(" + xsr.intenable {0} // get mask and temporarily disable interrupts + and {1}, {1}, {0} + rsync + wsr.intenable {1} + rsync + ", inout(reg) prev, inout(reg) !mask => _dummy, options(nostack) + ); + } + prev +} + +/// Enables specific interrupts and returns the previous setting +/// +/// # Safety +/// +/// - Do not call this function inside an `interrupt::free` critical section +#[inline] +pub unsafe fn enable_mask(mask: u32) -> u32 { + let mut prev: u32 = 0; + let _dummy: u32; + asm!(" + xsr.intenable {0} // get mask and temporarily disable interrupts + or {1}, {1}, {0} + rsync + wsr.intenable {1} + rsync + ", inout(reg) prev, inout(reg) mask => _dummy, options(nostack)); + prev +} + +/// Get current interrupt mask +#[inline] +pub fn get_mask() -> u32 { + let mask: u32; + unsafe { asm!("rsr.intenable {0}", out(reg) mask) }; + mask +} + +/// Get currently active interrupts +#[inline] +pub fn get() -> u32 { + let mask: u32; + unsafe { + asm!("rsr.interrupt {0}", out(reg) mask, options(nostack)); + } + mask +} + +/// Set interrupt +/// +/// # Safety +/// +/// Only valid for software interrupts +#[inline] +pub unsafe fn set(mask: u32) { + asm!(" + wsr.intset {0} + rsync + ", + in(reg) mask, options(nostack) + ); +} + +/// Clear interrupt +/// +/// # Safety +/// +/// Only valid for software and edge-triggered interrupts +#[inline] +pub unsafe fn clear(mask: u32) { + asm!(" + wsr.intclear {0} + rsync + ", + in(reg) mask, options(nostack) + ); +} + +/// Get current interrupt level +#[inline] +pub fn get_level() -> u32 { + let ps: u32; + unsafe { + asm!("rsr.ps {0}", out(reg) ps, options(nostack)); + }; + ps & 0xf +} + +/// Execute closure `f` in an interrupt-free context. +/// +/// This as also known as a "critical section". +#[inline] +pub fn free(f: F) -> R +where + F: FnOnce(&CriticalSection) -> R, +{ + // disable interrupts and store old mask + let old_mask = disable(); + + let r = f(unsafe { &CriticalSection::new() }); + + // enable previously disable interrupts + unsafe { + enable_mask(old_mask); + } + + r +} diff --git a/xtensa-lx/src/lib.rs b/xtensa-lx/src/lib.rs new file mode 100644 index 000000000..353870e6d --- /dev/null +++ b/xtensa-lx/src/lib.rs @@ -0,0 +1,113 @@ +//! Low-level access to Xtensa LX processors and peripherals. +//! +//! ## Minimum Supported Rust Version (MSRV) +//! +//! This crate is guaranteed to compile on stable Rust 1.65 and up. It might +//! compile with older versions but that may change in any new patch release. +//! +//! ## Feature Flags +#![doc = document_features::document_features!()] +#![doc(html_logo_url = "https://avatars.githubusercontent.com/u/46717278")] +#![allow(asm_sub_register)] +#![feature(asm_experimental_arch)] +#![no_std] + +use core::arch::asm; + +pub mod interrupt; +pub mod mutex; +pub mod timer; + +#[macro_use] +mod macros; + +const DCR_ENABLEOCD: u32 = 0x01; +const XDM_OCD_DCR_SET: u32 = 0x10200C; + +/// Move the vector base +/// +/// # Safety +/// +/// *This is highly unsafe!* +/// It should be used with care, `base` MUST be a valid pointer +#[inline(always)] +pub unsafe fn set_vecbase(base: *const u32) { + asm!("wsr.vecbase {0}", in(reg) base, options(nostack)); +} + +/// Get the core stack pointer +#[inline(always)] +pub fn get_stack_pointer() -> *const u32 { + let x: *const u32; + unsafe { asm!("mov {0}, sp", out(reg) x, options(nostack)) }; + x +} + +/// Set the core stack pointer +/// +/// `stack` pointer to the non-inclusive end of the stack (must be 16-byte +/// aligned) +/// +/// # Safety +/// +/// *This is highly unsafe!* +/// It should be used with care at e.g. program start or when building a task +/// scheduler +#[inline(always)] +pub unsafe fn set_stack_pointer(stack: *mut u32) { + // FIXME: this function relies on it getting inlined - if it doesn't inline it + // will try and return from this function using the adress in `a0` which has + // just been trashed... According to https://nnethercote.github.io/perf-book/inlining.html: + // "Inline attributes do not guarantee that a function is inlined or not + // inlined, but in practice, #[inline(always)] will cause inlining in all but + // the most exceptional cases." Is this good enough? Should we rewrite these + // as a macro to guarentee inlining? + + // NOTE: modification of the `sp` & `a0` is not typically allowed inside inline + // asm!, but because we *need* to modify it we can do so by ommiting it from + // the clobber + asm!( + "movi a0, 0", // trash return register + "mov sp, {0}", // move stack pointer + in(reg) stack, options(nostack) + ); +} + +/// Get the core current program counter +#[inline(always)] +pub fn get_program_counter() -> *const u32 { + let x: *const u32; + unsafe { + asm!(" + mov {1}, {2} + call0 1f + .align 4 + 1: + mov {0}, {2} + mov {2}, {1} + ", out(reg) x, out(reg) _, out(reg) _, options(nostack)) + }; + x +} + +/// Get the id of the current core +#[inline(always)] +pub fn get_processor_id() -> u32 { + let mut x: u32; + unsafe { asm!("rsr.prid {0}", out(reg) x, options(nostack)) }; + x +} + +/// Returns true if a debugger is attached +#[inline(always)] +pub fn is_debugger_attached() -> bool { + let mut x: u32; + unsafe { asm!("rer {0}, {1}", out(reg) x, in(reg) XDM_OCD_DCR_SET, options(nostack)) }; + (x & DCR_ENABLEOCD) != 0 +} + +/// Insert debug breakpoint +#[inline(always)] +pub fn debug_break() { + unsafe { asm!("break 1, 15", options(nostack)) }; +} diff --git a/xtensa-lx/src/macros.rs b/xtensa-lx/src/macros.rs new file mode 100644 index 000000000..31c7a0a4b --- /dev/null +++ b/xtensa-lx/src/macros.rs @@ -0,0 +1,52 @@ +/// Macro to create a mutable reference to a statically allocated value +/// +/// This macro returns a value with type `Option<&'static mut $ty>`. +/// `Some($expr)` will be returned the first time the macro is executed; further +/// calls will return `None`. To avoid `unwrap`ping a `None` variant the caller +/// must ensure that the macro is called from a function that's executed at most +/// once in the whole lifetime of the program. +/// +/// # Example +/// +/// ``` no_run +/// use xtensa_lx::singleton; +/// +/// fn main() { +/// // OK if `main` is executed only once +/// let x: &'static mut bool = singleton!(: bool = false).unwrap(); +/// +/// let y = alias(); +/// // BAD this second call to `alias` will definitively `panic!` +/// let y_alias = alias(); +/// } +/// +/// fn alias() -> &'static mut bool { +/// singleton!(: bool = false).unwrap() +/// } +/// ``` +#[macro_export] +macro_rules! singleton { + (: $ty:ty = $expr:expr) => { + $crate::interrupt::free(|_| { + static mut VAR: Option<$ty> = None; + + #[allow(unsafe_code)] + let used = unsafe { VAR.is_some() }; + if used { + None + } else { + let expr = $expr; + + #[allow(unsafe_code)] + unsafe { + VAR = Some(expr) + } + + #[allow(unsafe_code)] + unsafe { + VAR.as_mut() + } + } + }) + }; +} diff --git a/xtensa-lx/src/mutex.rs b/xtensa-lx/src/mutex.rs new file mode 100644 index 000000000..cbb0b7e46 --- /dev/null +++ b/xtensa-lx/src/mutex.rs @@ -0,0 +1,104 @@ +//! A series of Mutex's that also implements the `mutex-trait`. + +use core::cell::UnsafeCell; + +pub use mutex_trait::{self, Mutex}; + +/// A spinlock and critical section section based mutex. +#[cfg(feature = "spin")] +#[derive(Default)] +pub struct CriticalSectionSpinLockMutex { + data: spin::Mutex, +} + +#[cfg(feature = "spin")] +impl CriticalSectionSpinLockMutex { + /// Create a new mutex + pub const fn new(data: T) -> Self { + CriticalSectionSpinLockMutex { + data: spin::Mutex::new(data), + } + } +} + +#[cfg(feature = "spin")] +impl mutex_trait::Mutex for &'_ CriticalSectionSpinLockMutex { + type Data = T; + + fn lock(&mut self, f: impl FnOnce(&mut Self::Data) -> R) -> R { + crate::interrupt::free(|_| f(&mut (*self.data.lock()))) + } +} + +// NOTE A `Mutex` can be used as a channel so the protected data must be `Send` +// to prevent sending non-Sendable stuff (e.g. access tokens) across different +// execution contexts (e.g. interrupts) +#[cfg(feature = "spin")] +unsafe impl Sync for CriticalSectionSpinLockMutex where T: Send {} + +/// A Mutex based on critical sections +/// +/// # Safety +/// +/// **This Mutex is only safe on single-core applications.** +/// +/// A `CriticalSection` **is not sufficient** to ensure exclusive access across +/// cores. +#[derive(Default)] +pub struct CriticalSectionMutex { + data: UnsafeCell, +} + +impl CriticalSectionMutex { + /// Create a new mutex + pub const fn new(data: T) -> Self { + CriticalSectionMutex { + data: UnsafeCell::new(data), + } + } +} + +impl mutex_trait::Mutex for &'_ CriticalSectionMutex { + type Data = T; + + fn lock(&mut self, f: impl FnOnce(&mut Self::Data) -> R) -> R { + crate::interrupt::free(|_| f(unsafe { &mut *self.data.get() })) + } +} + +// NOTE A `Mutex` can be used as a channel so the protected data must be `Send` +// to prevent sending non-Sendable stuff (e.g. access tokens) across different +// execution contexts (e.g. interrupts) +unsafe impl Sync for CriticalSectionMutex where T: Send {} + +/// A spinlock based mutex. +#[cfg(feature = "spin")] +#[derive(Default)] +pub struct SpinLockMutex { + data: spin::Mutex, +} + +#[cfg(feature = "spin")] +impl SpinLockMutex { + /// Create a new mutex + pub const fn new(data: T) -> Self { + SpinLockMutex { + data: spin::Mutex::new(data), + } + } +} + +#[cfg(feature = "spin")] +impl mutex_trait::Mutex for &'_ SpinLockMutex { + type Data = T; + + fn lock(&mut self, f: impl FnOnce(&mut Self::Data) -> R) -> R { + f(&mut (*self.data.lock())) + } +} + +// NOTE A `Mutex` can be used as a channel so the protected data must be `Send` +// to prevent sending non-Sendable stuff (e.g. access tokens) across different +// execution contexts (e.g. interrupts) +#[cfg(feature = "spin")] +unsafe impl Sync for SpinLockMutex where T: Send {} diff --git a/xtensa-lx/src/timer.rs b/xtensa-lx/src/timer.rs new file mode 100644 index 000000000..a21aa1095 --- /dev/null +++ b/xtensa-lx/src/timer.rs @@ -0,0 +1,90 @@ +//! Xtensa internal timers + +use core::arch::asm; + +#[inline] +pub fn get_ccompare0() -> u32 { + let x: u32; + unsafe { asm!("rsr.ccompare0 {0}", out(reg) x, options(nostack)) }; + x +} + +#[inline] +pub fn get_ccompare1() -> u32 { + let x: u32; + unsafe { asm!("rsr.ccompare1 {0}", out(reg) x, options(nostack)) }; + x +} + +#[inline] +pub fn get_ccompare2() -> u32 { + let x: u32; + unsafe { asm!("rsr.ccompare2 {0}", out(reg) x, options(nostack)) }; + x +} + +#[inline] +pub fn get_ccompare3() -> u32 { + let x: u32; + unsafe { asm!("rsr.ccompare3 {0}", out(reg) x, options(nostack)) }; + x +} + +#[inline] +pub fn set_ccompare0(val: u32) { + unsafe { + asm!(" + wsr.ccompare0 {0} + isync + ", in(reg) val, options(nostack)) + }; +} + +#[inline] +pub fn set_ccompare1(val: u32) { + unsafe { + asm!(" + wsr.ccompare1 {0} + isync + ", in(reg) val, options(nostack)) + }; +} + +#[inline] +pub fn set_ccompare2(val: u32) { + unsafe { + asm!(" + wsr.ccompare2 {0} + isync + ", in(reg) val, options(nostack)) + }; +} + +#[inline] +pub fn set_ccompare3(val: u32) { + unsafe { + asm!(" + wsr.ccompare3 {0} + isync + ", in(reg) val, options(nostack)) + }; +} + +/// Get the core cycle count +#[inline] +pub fn get_cycle_count() -> u32 { + let x: u32; + unsafe { asm!("rsr.ccount {0}", out(reg) x, options(nostack)) }; + x +} + +/// cycle accurate delay using the cycle counter register +#[inline] +pub fn delay(clocks: u32) { + let start = get_cycle_count(); + loop { + if get_cycle_count().wrapping_sub(start) >= clocks { + break; + } + } +}