Introduce esp-metadata-generated (#3754)

* Move macros to new crate

* Generate a single file

* Pre-generate esp-metadata-generated

* Move saving code to xtask

* Format with both rustfmt and prettyplease

* Fix doc build

* Unhide macros

* Fix doc string

* Update semver-check baseline
This commit is contained in:
Dániel Buga 2025-07-07 17:37:05 +02:00 committed by GitHub
parent d28bf16777
commit 692a768b3a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
75 changed files with 11012 additions and 414 deletions

View File

@ -13,6 +13,7 @@ exclude = [
"esp-ieee802154",
"esp-lp-hal",
"esp-metadata",
"esp-metadata-generated",
"esp-println",
"esp-riscv-rt",
"esp-wifi",

View File

@ -18,6 +18,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Removed
- Removed support for ESP32-P4 (#3754)
## [v0.16.0] - 2025-06-03

View File

@ -28,7 +28,6 @@ semihosting = { version = "0.1.20", optional = true }
[build-dependencies]
esp-config = { version = "0.4.0", path = "../esp-config", features = ["build"] }
esp-metadata = { version = "0.7.0", path = "../esp-metadata" }
[features]
default = ["colors"]
@ -38,7 +37,6 @@ esp32c2 = ["esp-println?/esp32c2"]
esp32c3 = ["esp-println?/esp32c3"]
esp32c6 = ["esp-println?/esp32c6"]
esp32h2 = ["esp-println?/esp32h2"]
esp32p4 = ["esp-println?/esp32p4"]
esp32s2 = ["esp-println?/esp32s2", "semihosting?/openocd-semihosting"]
esp32s3 = ["esp-println?/esp32s3", "semihosting?/openocd-semihosting", "print-float-registers"]

View File

@ -12,9 +12,6 @@ macro_rules! assert_unique_used_features {
}
fn main() {
// Ensure that only a single chip is specified:
let _ = esp_metadata::Chip::from_cargo_feature().unwrap();
// Ensure that exactly a backend is selected:
assert_unique_used_features!("defmt", "println");

View File

@ -33,7 +33,6 @@ md-5 = { version = "0.10.6", default-features = false, optional = true }
[build-dependencies]
jiff = { version = "0.2.13", default-features = false, features = ["std"] }
esp-config = { version = "0.4.0", path = "../esp-config", features = ["build"] }
esp-metadata = { version = "0.7.0", path = "../esp-metadata" }
[features]
default = ["validation"]

View File

@ -39,11 +39,5 @@ fn main() -> Result<(), Box<dyn Error>> {
.expect("Failed to read esp_config.yml for esp-bootloader-esp-idf");
generate_config_from_yaml_definition(&cfg_yaml, true, true, None).unwrap();
#[cfg(not(feature = "std"))]
{
// Ensure that exactly one chip has been specified:
let _chip = esp_metadata::Chip::from_cargo_feature()?;
}
Ok(())
}

View File

@ -23,7 +23,8 @@ document-features = "0.2.11"
serde = { version = "1.0.197", default-features = false, features = ["derive"], optional = true }
serde_yaml = { version = "0.9", optional = true }
evalexpr = { version = "12.0.2", optional = true }
esp-metadata = { version = "0.7.0", path = "../esp-metadata", default-features = true, optional = true }
esp-metadata = { version = "0.7.0", path = "../esp-metadata", features = ["clap"], optional = true }
esp-metadata-generated = { version = "0.0.1", path = "../esp-metadata-generated", features = ["build-script"], optional = true }
# used by the `tui` feature
clap = { version = "4.5.32", features = ["derive"], optional = true }
@ -41,7 +42,7 @@ pretty_assertions = "1.4.1"
[features]
## Enable the generation and parsing of a config
build = ["dep:serde", "dep:serde_yaml", "dep:evalexpr", "dep:esp-metadata"]
build = ["dep:serde", "dep:serde_yaml", "dep:evalexpr", "dep:esp-metadata-generated"]
## The TUI
tui = [
@ -53,6 +54,7 @@ tui = [
"dep:toml_edit",
"dep:tui-textarea",
"dep:cargo_metadata",
"esp-metadata?/clap",
"dep:esp-metadata",
"dep:esp-metadata-generated",
"build",
]

View File

@ -211,14 +211,14 @@ fn parse_configs(
}
let mut configs = Vec::new();
let chip = esp_metadata::Config::for_chip(chip.as_ref().unwrap());
let chip = esp_metadata_generated::Chip::from_str(chip.unwrap().as_ref()).unwrap();
let features = vec![];
for krate in meta.packages {
let maybe_cfg = krate.manifest_path.parent().unwrap().join("esp_config.yml");
if maybe_cfg.exists() {
let yaml = std::fs::read_to_string(&maybe_cfg)?;
let (cfg, options) =
esp_config::evaluate_yaml_config(&yaml, Some(chip.clone()), features.clone(), true)
esp_config::evaluate_yaml_config(&yaml, Some(chip), features.clone(), true)
.map_err(|e| {
format!(
"Error evaluating YAML config for crate {}: {}",

View File

@ -134,7 +134,7 @@ pub fn generate_config_from_yaml_definition(
yaml: &str,
enable_unstable: bool,
emit_md_tables: bool,
chip: Option<esp_metadata::Config>,
chip: Option<esp_metadata_generated::Chip>,
) -> Result<HashMap<String, Value>, Error> {
let features: Vec<String> = env::vars()
.filter(|(k, _)| k.starts_with("CARGO_FEATURE_"))
@ -186,16 +186,19 @@ pub fn do_checks(checks: Option<&Vec<String>>, cfg: &HashMap<String, Value>) ->
/// Evaluate the given YAML representation of a config definition.
pub fn evaluate_yaml_config(
yaml: &str,
chip: Option<esp_metadata::Config>,
chip: Option<esp_metadata_generated::Chip>,
features: Vec<String>,
ignore_feature_gates: bool,
) -> Result<(Config, Vec<ConfigOption>), Error> {
let config: Config = serde_yaml::from_str(yaml).map_err(|err| Error::Parse(err.to_string()))?;
let mut options = Vec::new();
let mut eval_ctx = evalexpr::HashMapContext::<evalexpr::DefaultNumericTypes>::new();
if let Some(config) = chip {
if let Some(chip) = chip {
eval_ctx
.set_value("chip".into(), evalexpr::Value::String(config.name()))
.set_value(
"chip".into(),
evalexpr::Value::String(chip.name().to_string()),
)
.map_err(|err| Error::Parse(err.to_string()))?;
eval_ctx
@ -203,7 +206,7 @@ pub fn evaluate_yaml_config(
"feature".into(),
evalexpr::Function::<evalexpr::DefaultNumericTypes>::new(move |arg| {
if let evalexpr::Value::String(which) = arg {
let res = config.contains(which);
let res = chip.contains(which);
Ok(evalexpr::Value::Boolean(res))
} else {
Err(evalexpr::EvalexprError::CustomMessage(format!(
@ -1044,7 +1047,7 @@ options:
let (cfg, options) = evaluate_yaml_config(
yml,
Some(esp_metadata::Config::for_chip(&esp_metadata::Chip::Esp32c6).clone()),
Some(esp_metadata_generated::Chip::Esp32c6),
vec![],
false,
)
@ -1114,7 +1117,7 @@ options:
let (cfg, options) = evaluate_yaml_config(
yml,
Some(esp_metadata::Config::for_chip(&esp_metadata::Chip::Esp32c3).clone()),
Some(esp_metadata_generated::Chip::Esp32c3),
vec![],
false,
)
@ -1166,7 +1169,7 @@ options:
let (cfg, options) = evaluate_yaml_config(
yml,
Some(esp_metadata::Config::for_chip(&esp_metadata::Chip::Esp32).clone()),
Some(esp_metadata_generated::Chip::Esp32),
vec![],
false,
)

View File

@ -43,7 +43,7 @@ log-04 = { package = "log", version = "0.4.27", optional = tr
[build-dependencies]
esp-config = { version = "0.4.0", path = "../esp-config", features = ["build"] }
esp-metadata = { version = "0.7.0", path = "../esp-metadata" }
esp-metadata-generated = { version = "0.0.1", path = "../esp-metadata-generated", features = ["build-script"] }
[features]
default = ["executors"]

View File

@ -1,22 +1,20 @@
use std::error::Error as StdError;
use esp_config::{Value, generate_config_from_yaml_definition};
use esp_metadata::{Chip, Config};
fn main() -> Result<(), Box<dyn StdError>> {
// Load the configuration file for the configured device:
let chip = Chip::from_cargo_feature()?;
let config = Config::for_chip(&chip);
// Load the configuration for the configured device:
let chip = esp_metadata_generated::Chip::from_cargo_feature()?;
// Define all necessary configuration symbols for the configured device:
config.define_symbols();
chip.define_cfgs();
// emit config
println!("cargo:rerun-if-changed=./esp_config.yml");
let cfg_yaml = std::fs::read_to_string("./esp_config.yml")
.expect("Failed to read esp_config.yml for esp-hal-embassy");
let crate_config =
generate_config_from_yaml_definition(&cfg_yaml, true, true, Some(config.clone())).unwrap();
generate_config_from_yaml_definition(&cfg_yaml, true, true, Some(chip)).unwrap();
println!("cargo:rustc-check-cfg=cfg(integrated_timers)");
println!("cargo:rustc-check-cfg=cfg(single_queue)");

View File

@ -44,6 +44,7 @@ instability = "0.3.7"
strum = { version = "0.27.1", default-features = false, features = ["derive"] }
esp-config = { version = "0.4.0", path = "../esp-config" }
esp-metadata-generated = { version = "0.0.1", path = "../esp-metadata-generated" }
procmacros = { version = "0.18.0", package = "esp-hal-procmacros", path = "../esp-hal-procmacros" }
# Dependencies that are optional because they are used by unstable drivers.
@ -90,7 +91,7 @@ xtensa-lx-rt = { version = "0.19.0", path = "../xtensa-lx-rt" }
[build-dependencies]
cfg-if = "1.0.0"
esp-metadata = { version = "0.7.0", path = "../esp-metadata" }
esp-metadata-generated = { version = "0.0.1", path = "../esp-metadata-generated", features = ["build-script"] }
esp-config = { version = "0.4.0", path = "../esp-config", features = ["build"] }
serde = { version = "1.0.219", default-features = false, features = ["derive"] }
@ -121,12 +122,14 @@ esp32 = [
"dep:esp32",
"procmacros/rtc-slow",
"esp-rom-sys/esp32",
"esp-metadata-generated/esp32",
]
# Target the ESP32-C2.
esp32c2 = [
"dep:esp32c2",
"portable-atomic/unsafe-assume-single-core",
"esp-rom-sys/esp32c2",
"esp-metadata-generated/esp32c2",
]
# Target the ESP32-C3.
esp32c3 = [
@ -134,6 +137,7 @@ esp32c3 = [
"esp-riscv-rt/rtc-ram",
"portable-atomic/unsafe-assume-single-core",
"esp-rom-sys/esp32c3",
"esp-metadata-generated/esp32c3",
]
# Target the ESP32-C6.
esp32c6 = [
@ -141,12 +145,14 @@ esp32c6 = [
"esp-riscv-rt/rtc-ram",
"procmacros/has-lp-core",
"esp-rom-sys/esp32c6",
"esp-metadata-generated/esp32c6",
]
# Target the ESP32-H2.
esp32h2 = [
"dep:esp32h2",
"esp-riscv-rt/rtc-ram",
"esp-rom-sys/esp32h2",
"esp-metadata-generated/esp32h2",
]
# Target the ESP32-S2.
esp32s2 = [
@ -156,6 +162,7 @@ esp32s2 = [
"procmacros/rtc-slow",
"__usb_otg",
"esp-rom-sys/esp32s2",
"esp-metadata-generated/esp32s2",
]
# Target the ESP32-S3.
esp32s3 = [
@ -164,6 +171,7 @@ esp32s3 = [
"procmacros/rtc-slow",
"__usb_otg",
"esp-rom-sys/esp32s3",
"esp-metadata-generated/esp32s3",
]

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -8,7 +8,6 @@ use std::{
};
use esp_config::{Value, generate_config_from_yaml_definition};
use esp_metadata::{Chip, Config};
#[macro_export]
macro_rules! assert_unique_features {
@ -35,7 +34,7 @@ fn main() -> Result<(), Box<dyn Error>> {
assert_unique_features!("log-04", "defmt");
// Ensure that exactly one chip has been specified:
let chip = Chip::from_cargo_feature()?;
let chip = esp_metadata_generated::Chip::from_cargo_feature()?;
if chip.target() != std::env::var("TARGET").unwrap_or_default().as_str() {
panic!("
@ -46,12 +45,8 @@ fn main() -> Result<(), Box<dyn Error>> {
");
}
// Load the configuration file for the configured device:
let config = Config::for_chip(&chip);
// Define all necessary configuration symbols for the configured device:
config.define_symbols();
config.generate_metadata();
chip.define_cfgs();
// Place all linker scripts in `OUT_DIR`, and instruct Cargo how to find these
// files:
@ -62,17 +57,16 @@ fn main() -> Result<(), Box<dyn Error>> {
println!("cargo:rerun-if-changed=./esp_config.yml");
let cfg_yaml = std::fs::read_to_string("./esp_config.yml")
.expect("Failed to read esp_config.yml for esp-hal");
let cfg =
generate_config_from_yaml_definition(&cfg_yaml, true, true, Some(config.clone())).unwrap();
let cfg = generate_config_from_yaml_definition(&cfg_yaml, true, true, Some(chip)).unwrap();
// RISC-V and Xtensa devices each require some special handling and processing
// of linker scripts:
let mut config_symbols = config.all().to_vec();
let mut config_symbols = chip.all_symbols().to_vec();
for (key, value) in &cfg {
if let Value::Bool(true) = value {
config_symbols.push(key.to_string());
config_symbols.push(key.as_str());
}
}
@ -119,7 +113,7 @@ fn main() -> Result<(), Box<dyn Error>> {
// With the architecture-specific linker scripts taken care of, we can copy all
// remaining linker scripts which are common to all devices:
copy_dir_all(&config_symbols, &cfg, "ld/sections", &out)?;
copy_dir_all(&config_symbols, &cfg, format!("ld/{chip}"), &out)?;
copy_dir_all(&config_symbols, &cfg, format!("ld/{}", chip.name()), &out)?;
Ok(())
}
@ -128,7 +122,7 @@ fn main() -> Result<(), Box<dyn Error>> {
// Helper Functions
fn copy_dir_all(
config_symbols: &[String],
config_symbols: &[&str],
cfg: &HashMap<String, Value>,
src: impl AsRef<Path>,
dst: impl AsRef<Path>,
@ -158,7 +152,7 @@ fn copy_dir_all(
/// A naive pre-processor for linker scripts
fn preprocess_file(
config: &[String],
config: &[&str],
cfg: &HashMap<String, Value>,
src: impl AsRef<Path>,
dst: impl AsRef<Path>,
@ -177,7 +171,7 @@ fn preprocess_file(
if let Some(condition) = trimmed.strip_prefix("#IF ") {
let should_take = take.iter().all(|v| *v);
let should_take = should_take && config.iter().any(|c| c.as_str() == condition);
let should_take = should_take && config.contains(&condition);
take.push(should_take);
continue;
} else if trimmed == "#ELSE" {

View File

@ -77,14 +77,15 @@ pub use placeholder::NoPin;
use portable_atomic::AtomicU32;
use strum::EnumCount;
pub use crate::soc::gpio::*;
use crate::{
asynch::AtomicWaker,
interrupt::{InterruptHandler, Priority},
peripherals::{GPIO, IO_MUX, Interrupt, impl_for_pin_type, io_mux_reg},
peripherals::{GPIO, IO_MUX, Interrupt, io_mux_reg},
private::{self, Sealed},
};
define_io_mux_signals!();
/// Represents a pin-peripheral connection that, when dropped, disconnects the
/// peripheral from the pin.
///
@ -880,7 +881,7 @@ macro_rules! gpio {
pub(crate) fn is_output(&self) -> bool {
match self.pin {
$(
$gpionum => $crate::peripherals::if_pin_is_type!($peri, Output, { true } else { false }),
$gpionum => if_pin_is_type!($peri, Output, { true } else { false }),
)+
_ => false,
}

View File

@ -3237,7 +3237,7 @@ fn estimate_ack_failed_reason(_register_block: &RegisterBlock) -> AcknowledgeChe
}
}
crate::peripherals::for_each_i2c_master!(
for_each_i2c_master!(
($inst:ident, $peri:ident, $scl:ident, $sda:ident) => {
impl Instance for crate::peripherals::$inst<'_> {
fn parts(&self) -> (&Info, &State) {

View File

@ -183,20 +183,11 @@
mod fmt;
#[macro_use]
/// This module contains code generated by `esp-metadata`.
///
/// The main API is the [`property!`] macro, which takes a string key and
/// returns a value. This macro is available anywhere inside esp-hal, without
/// additional imports. Note that this macro can't be used in public macros, as
/// they will fail to compile.
mod _generated {
// This must go before other code, so that they can see macros.
// Generated by esp-metadata.
include!(concat!(env!("OUT_DIR"), "/_generated.rs"));
}
extern crate esp_metadata_generated;
use core::marker::PhantomData;
pub use esp_metadata_generated::chip;
use esp_rom_sys as _;
metadata!("build_info", CHIP_NAME, chip!());

View File

@ -119,9 +119,6 @@ macro_rules! create_peripheral {
};
}
include!(concat!(env!("OUT_DIR"), "/_generated_peris.rs"));
include!(concat!(env!("OUT_DIR"), "/_generated_gpio.rs"));
for_each_gpio! {
($n:literal, $pin_peri:ident $af_ins:tt $af_outs:tt ($($attr:ident)*)) => {
$(

View File

@ -28,8 +28,6 @@
//! registers for both the `PRO CPU` and `APP CPU`. The implementation uses the
//! `gpio` peripheral to access the appropriate registers.
include!(concat!(env!("OUT_DIR"), "/_generated_iomux_signals.rs"));
macro_rules! rtcio_analog {
(
$pin_num:expr, $rtc_pin:expr, $pin_reg:expr, $prefix:pat, $hold:ident $(, $rue:literal)?

View File

@ -26,8 +26,6 @@
//! registers for both the `PRO CPU` and `APP CPU`. The implementation uses the
//! `gpio` peripheral to access the appropriate registers.
include!(concat!(env!("OUT_DIR"), "/_generated_iomux_signals.rs"));
macro_rules! rtc_pins {
( $( $pin_num:expr )+ ) => {
$(

View File

@ -26,8 +26,6 @@
//! registers for both the `PRO CPU` and `APP CPU`. The implementation uses the
//! `gpio` peripheral to access the appropriate registers.
include!(concat!(env!("OUT_DIR"), "/_generated_iomux_signals.rs"));
macro_rules! rtc_pins {
( $( $pin_num:expr )+ ) => {
$(

View File

@ -26,8 +26,6 @@
//! registers for both the `PRO CPU` and `APP CPU`. The implementation uses the
//! `gpio` peripheral to access the appropriate registers.
include!(concat!(env!("OUT_DIR"), "/_generated_iomux_signals.rs"));
crate::gpio::lp_io::lp_gpio! {
0
1

View File

@ -25,5 +25,3 @@
//! This trait provides functions to read the interrupt status and NMI status
//! registers for both the `PRO CPU` and `APP CPU`. The implementation uses the
//! `gpio` peripheral to access the appropriate registers.
include!(concat!(env!("OUT_DIR"), "/_generated_iomux_signals.rs"));

View File

@ -35,8 +35,6 @@
//! registers for both the `PRO CPU` and `APP CPU`. The implementation uses the
//! `gpio` peripheral to access the appropriate registers.
include!(concat!(env!("OUT_DIR"), "/_generated_iomux_signals.rs"));
macro_rules! rtcio_analog {
($pin_num:expr, $pin_reg:expr, $hold:ident) => {
paste::paste!{

View File

@ -26,8 +26,6 @@
//! registers for both the `PRO CPU` and `APP CPU`. The implementation uses the
//! `gpio` peripheral to access the appropriate registers.
include!(concat!(env!("OUT_DIR"), "/_generated_iomux_signals.rs"));
macro_rules! rtcio_analog {
($pin_num:expr, $pin_reg:expr, $hold:ident) => {
paste::paste! {

View File

@ -3853,7 +3853,7 @@ impl PartialEq for Info {
unsafe impl Sync for Info {}
crate::peripherals::for_each_spi_master! {
for_each_spi_master! {
($peri:ident, $sys:ident, $sclk:ident [$($cs:ident),+] [$($sio:ident),*] $(, $is_qspi:tt)?) => {
impl Instance for crate::peripherals::$peri<'_> {
#[inline(always)]

View File

@ -787,7 +787,7 @@ impl PartialEq for Info {
unsafe impl Sync for Info {}
crate::peripherals::for_each_spi_slave! {
for_each_spi_slave! {
($peri:ident, $sys:ident, $sclk:ident, $mosi:ident, $miso:ident, $cs:ident) => {
impl Instance for crate::peripherals::$peri<'_> {
#[inline(always)]

View File

@ -3381,7 +3381,7 @@ impl PartialEq for Info {
unsafe impl Sync for Info {}
crate::peripherals::for_each_uart! {
for_each_uart! {
($inst:ident, $peri:ident, $rxd:ident, $txd:ident, $cts:ident, $rts:ident) => {
impl Instance for crate::peripherals::$inst<'_> {
fn parts(&self) -> (&'static Info, &'static State) {

View File

@ -0,0 +1,24 @@
[package]
name = "esp-metadata-generated"
version = "0.0.1"
edition = "2024"
rust-version = "1.86.0"
description = "Generated metadata for Espressif devices"
documentation = "https://docs.espressif.com/projects/rust/esp-metadata/latest/"
repository = "https://github.com/esp-rs/esp-hal"
license = "MIT OR Apache-2.0"
[dependencies]
[build-dependencies]
esp-metadata = { version = "0.7.0", path = "../esp-metadata" } # TODO: remove
[features]
build-script = []
esp32 = []
esp32c2 = []
esp32c3 = []
esp32c6 = []
esp32h2 = []
esp32s2 = []
esp32s3 = []

View File

@ -0,0 +1,32 @@
# esp-metadata
[![Crates.io](https://img.shields.io/crates/v/esp-metadata?labelColor=1C2C2E&color=C96329&logo=Rust&style=flat-square)](https://crates.io/crates/esp-metadata)
[![docs.rs](https://img.shields.io/docsrs/esp-metadata?labelColor=1C2C2E&color=C96329&logo=rust&style=flat-square)](https://docs.espressif.com/projects/rust/esp-metadata/latest/)
![MSRV](https://img.shields.io/badge/MSRV-1.86.0-blue?labelColor=1C2C2E&style=flat-square)
![Crates.io](https://img.shields.io/crates/l/esp-metadata?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)
The generated output of `esp-metadata`, intended for use in [build scripts] and HAL crates alike.
[build scripts]: https://doc.rust-lang.org/cargo/reference/build-scripts.html
## [Documentation](https://docs.espressif.com/projects/rust/esp-metadata/latest/)
## Minimum Supported Rust Version (MSRV)
This crate is guaranteed to compile when using the latest stable Rust version at the time of the crate's release. It _might_ compile with older versions, but that may change in any new release, including patches.
## 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.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,744 @@
/// The name of the chip as `&str`
#[macro_export]
macro_rules! chip {
() => {
"esp32c2"
};
}
/// The properties of this chip and its drivers.
#[macro_export]
macro_rules! property {
("chip") => {
"esp32c2"
};
("arch") => {
"riscv"
};
("cores") => {
1
};
("cores", str) => {
stringify!(1)
};
("trm") => {
"https://www.espressif.com/sites/default/files/documentation/esp8684_technical_reference_manual_en.pdf"
};
("assist_debug.has_sp_monitor") => {
true
};
("assist_debug.has_region_monitor") => {
false
};
("gpio.has_bank_1") => {
false
};
("gpio.gpio_function") => {
1
};
("gpio.gpio_function", str) => {
stringify!(1)
};
("gpio.input_signal_max") => {
100
};
("gpio.input_signal_max", str) => {
stringify!(100)
};
("gpio.output_signal_max") => {
128
};
("gpio.output_signal_max", str) => {
stringify!(128)
};
("gpio.constant_0_input") => {
31
};
("gpio.constant_0_input", str) => {
stringify!(31)
};
("gpio.constant_1_input") => {
30
};
("gpio.constant_1_input", str) => {
stringify!(30)
};
("gpio.remap_iomux_pin_registers") => {
false
};
("gpio.func_in_sel_offset") => {
0
};
("gpio.func_in_sel_offset", str) => {
stringify!(0)
};
("i2c_master.has_fsm_timeouts") => {
true
};
("i2c_master.has_hw_bus_clear") => {
true
};
("i2c_master.has_bus_timeout_enable") => {
true
};
("i2c_master.separate_filter_config_registers") => {
false
};
("i2c_master.can_estimate_nack_reason") => {
false
};
("i2c_master.has_conf_update") => {
true
};
("i2c_master.has_reliable_fsm_reset") => {
false
};
("i2c_master.has_arbitration_en") => {
true
};
("i2c_master.has_tx_fifo_watermark") => {
true
};
("i2c_master.bus_timeout_is_exponential") => {
true
};
("i2c_master.max_bus_timeout") => {
31
};
("i2c_master.max_bus_timeout", str) => {
stringify!(31)
};
("i2c_master.ll_intr_mask") => {
262143
};
("i2c_master.ll_intr_mask", str) => {
stringify!(262143)
};
("i2c_master.fifo_size") => {
16
};
("i2c_master.fifo_size", str) => {
stringify!(16)
};
("interrupts.status_registers") => {
2
};
("interrupts.status_registers", str) => {
stringify!(2)
};
("spi_master.has_octal") => {
false
};
("timergroup.timg_has_timer1") => {
false
};
("wifi.has_wifi6") => {
false
};
}
/// Macro to get the address range of the given memory region.
#[macro_export]
macro_rules! memory_range {
("DRAM") => {
1070202880..1070465024
};
}
#[macro_export]
macro_rules! for_each_i2c_master {
($($pattern:tt => $code:tt;)*) => {
macro_rules! _for_each_inner { $(($pattern) => $code;)* ($other : tt) => {} }
_for_each_inner!((I2C0, I2cExt0, I2CEXT0_SCL, I2CEXT0_SDA));
_for_each_inner!((all(I2C0, I2cExt0, I2CEXT0_SCL, I2CEXT0_SDA)));
};
}
#[macro_export]
macro_rules! for_each_uart {
($($pattern:tt => $code:tt;)*) => {
macro_rules! _for_each_inner { $(($pattern) => $code;)* ($other : tt) => {} }
_for_each_inner!((UART0, Uart0, U0RXD, U0TXD, U0CTS, U0RTS));
_for_each_inner!((UART1, Uart1, U1RXD, U1TXD, U1CTS, U1RTS));
_for_each_inner!((all(UART0, Uart0, U0RXD, U0TXD, U0CTS, U0RTS), (UART1, Uart1,
U1RXD, U1TXD, U1CTS, U1RTS)));
};
}
#[macro_export]
macro_rules! for_each_spi_master {
($($pattern:tt => $code:tt;)*) => {
macro_rules! _for_each_inner { $(($pattern) => $code;)* ($other : tt) => {} }
_for_each_inner!((SPI2, Spi2, FSPICLK[FSPICS0, FSPICS1, FSPICS2, FSPICS3,
FSPICS4, FSPICS5] [FSPID, FSPIQ, FSPIWP, FSPIHD], true));
_for_each_inner!((all(SPI2, Spi2, FSPICLK[FSPICS0, FSPICS1, FSPICS2, FSPICS3,
FSPICS4, FSPICS5] [FSPID, FSPIQ, FSPIWP, FSPIHD], true)));
};
}
#[macro_export]
macro_rules! for_each_spi_slave {
($($pattern:tt => $code:tt;)*) => {
macro_rules! _for_each_inner { $(($pattern) => $code;)* ($other : tt) => {} }
_for_each_inner!((SPI2, Spi2, FSPICLK, FSPID, FSPIQ, FSPICS0));
_for_each_inner!((all(SPI2, Spi2, FSPICLK, FSPID, FSPIQ, FSPICS0)));
};
}
#[macro_export]
macro_rules! for_each_peripheral {
($($pattern:tt => $code:tt;)*) => {
macro_rules! _for_each_inner { $(($pattern) => $code;)* ($other : tt) => {} }
_for_each_inner!((GPIO0 <= virtual())); _for_each_inner!((GPIO1 <= virtual()));
_for_each_inner!((GPIO2 <= virtual())); _for_each_inner!((GPIO3 <= virtual()));
_for_each_inner!((GPIO4 <= virtual())); _for_each_inner!((GPIO5 <= virtual()));
_for_each_inner!((GPIO6 <= virtual())); _for_each_inner!((GPIO7 <= virtual()));
_for_each_inner!((GPIO8 <= virtual())); _for_each_inner!((GPIO9 <= virtual()));
_for_each_inner!((GPIO10 <= virtual())); _for_each_inner!((GPIO11 <= virtual()));
_for_each_inner!((GPIO12 <= virtual())); _for_each_inner!((GPIO13 <= virtual()));
_for_each_inner!((GPIO14 <= virtual())); _for_each_inner!((GPIO15 <= virtual()));
_for_each_inner!((GPIO16 <= virtual())); _for_each_inner!((GPIO17 <= virtual()));
_for_each_inner!((GPIO18 <= virtual())); _for_each_inner!((GPIO19 <= virtual()));
_for_each_inner!((GPIO20 <= virtual())); _for_each_inner!((APB_CTRL <= APB_CTRL()
(unstable))); _for_each_inner!((APB_SARADC <= APB_SARADC() (unstable)));
_for_each_inner!((BB <= BB() (unstable))); _for_each_inner!((ASSIST_DEBUG <=
ASSIST_DEBUG() (unstable))); _for_each_inner!((DMA <= DMA() (unstable)));
_for_each_inner!((ECC <= ECC() (unstable))); _for_each_inner!((EFUSE <= EFUSE()
(unstable))); _for_each_inner!((EXTMEM <= EXTMEM() (unstable)));
_for_each_inner!((GPIO <= GPIO() (unstable))); _for_each_inner!((I2C_ANA_MST <=
I2C_ANA_MST() (unstable))); _for_each_inner!((I2C0 <= I2C0(I2C_EXT0 : {
bind_peri_interrupt, enable_peri_interrupt, disable_peri_interrupt })));
_for_each_inner!((INTERRUPT_CORE0 <= INTERRUPT_CORE0() (unstable)));
_for_each_inner!((IO_MUX <= IO_MUX() (unstable))); _for_each_inner!((LEDC <=
LEDC() (unstable))); _for_each_inner!((RNG <= RNG() (unstable)));
_for_each_inner!((LPWR <= RTC_CNTL() (unstable))); _for_each_inner!((MODEM_CLKRST
<= MODEM_CLKRST() (unstable))); _for_each_inner!((SENSITIVE <= SENSITIVE()
(unstable))); _for_each_inner!((SHA <= SHA() (unstable))); _for_each_inner!((SPI0
<= SPI0() (unstable))); _for_each_inner!((SPI1 <= SPI1() (unstable)));
_for_each_inner!((SPI2 <= SPI2(SPI2 : { bind_peri_interrupt,
enable_peri_interrupt, disable_peri_interrupt }))); _for_each_inner!((SYSTEM <=
SYSTEM() (unstable))); _for_each_inner!((SYSTIMER <= SYSTIMER() (unstable)));
_for_each_inner!((TIMG0 <= TIMG0() (unstable))); _for_each_inner!((UART0 <=
UART0(UART0 : { bind_peri_interrupt, enable_peri_interrupt,
disable_peri_interrupt }))); _for_each_inner!((UART1 <= UART1(UART1 : {
bind_peri_interrupt, enable_peri_interrupt, disable_peri_interrupt })));
_for_each_inner!((XTS_AES <= XTS_AES() (unstable))); _for_each_inner!((DMA_CH0 <=
virtual() (unstable))); _for_each_inner!((ADC1 <= virtual() (unstable)));
_for_each_inner!((BT <= virtual() (unstable))); _for_each_inner!((RADIO_CLK <=
virtual() (unstable))); _for_each_inner!((SW_INTERRUPT <= virtual() (unstable)));
_for_each_inner!((WIFI <= virtual() (unstable))); _for_each_inner!((MEM2MEM1 <=
virtual() (unstable))); _for_each_inner!((MEM2MEM2 <= virtual() (unstable)));
_for_each_inner!((MEM2MEM3 <= virtual() (unstable))); _for_each_inner!((MEM2MEM4
<= virtual() (unstable))); _for_each_inner!((MEM2MEM5 <= virtual() (unstable)));
_for_each_inner!((MEM2MEM6 <= virtual() (unstable))); _for_each_inner!((MEM2MEM7
<= virtual() (unstable))); _for_each_inner!((MEM2MEM8 <= virtual() (unstable)));
_for_each_inner!((all(GPIO0 <= virtual()), (GPIO1 <= virtual()), (GPIO2 <=
virtual()), (GPIO3 <= virtual()), (GPIO4 <= virtual()), (GPIO5 <= virtual()),
(GPIO6 <= virtual()), (GPIO7 <= virtual()), (GPIO8 <= virtual()), (GPIO9 <=
virtual()), (GPIO10 <= virtual()), (GPIO11 <= virtual()), (GPIO12 <= virtual()),
(GPIO13 <= virtual()), (GPIO14 <= virtual()), (GPIO15 <= virtual()), (GPIO16 <=
virtual()), (GPIO17 <= virtual()), (GPIO18 <= virtual()), (GPIO19 <= virtual()),
(GPIO20 <= virtual()), (APB_CTRL <= APB_CTRL() (unstable)), (APB_SARADC <=
APB_SARADC() (unstable)), (BB <= BB() (unstable)), (ASSIST_DEBUG <=
ASSIST_DEBUG() (unstable)), (DMA <= DMA() (unstable)), (ECC <= ECC() (unstable)),
(EFUSE <= EFUSE() (unstable)), (EXTMEM <= EXTMEM() (unstable)), (GPIO <= GPIO()
(unstable)), (I2C_ANA_MST <= I2C_ANA_MST() (unstable)), (I2C0 <= I2C0(I2C_EXT0 :
{ bind_peri_interrupt, enable_peri_interrupt, disable_peri_interrupt })),
(INTERRUPT_CORE0 <= INTERRUPT_CORE0() (unstable)), (IO_MUX <= IO_MUX()
(unstable)), (LEDC <= LEDC() (unstable)), (RNG <= RNG() (unstable)), (LPWR <=
RTC_CNTL() (unstable)), (MODEM_CLKRST <= MODEM_CLKRST() (unstable)), (SENSITIVE
<= SENSITIVE() (unstable)), (SHA <= SHA() (unstable)), (SPI0 <= SPI0()
(unstable)), (SPI1 <= SPI1() (unstable)), (SPI2 <= SPI2(SPI2 : {
bind_peri_interrupt, enable_peri_interrupt, disable_peri_interrupt })), (SYSTEM
<= SYSTEM() (unstable)), (SYSTIMER <= SYSTIMER() (unstable)), (TIMG0 <= TIMG0()
(unstable)), (UART0 <= UART0(UART0 : { bind_peri_interrupt,
enable_peri_interrupt, disable_peri_interrupt })), (UART1 <= UART1(UART1 : {
bind_peri_interrupt, enable_peri_interrupt, disable_peri_interrupt })), (XTS_AES
<= XTS_AES() (unstable)), (DMA_CH0 <= virtual() (unstable)), (ADC1 <= virtual()
(unstable)), (BT <= virtual() (unstable)), (RADIO_CLK <= virtual() (unstable)),
(SW_INTERRUPT <= virtual() (unstable)), (WIFI <= virtual() (unstable)), (MEM2MEM1
<= virtual() (unstable)), (MEM2MEM2 <= virtual() (unstable)), (MEM2MEM3 <=
virtual() (unstable)), (MEM2MEM4 <= virtual() (unstable)), (MEM2MEM5 <= virtual()
(unstable)), (MEM2MEM6 <= virtual() (unstable)), (MEM2MEM7 <= virtual()
(unstable)), (MEM2MEM8 <= virtual() (unstable))));
};
}
#[macro_export]
macro_rules! for_each_gpio {
($($pattern:tt => $code:tt;)*) => {
macro_rules! _for_each_inner { $(($pattern) => $code;)* ($other : tt) => {} }
_for_each_inner!((0, GPIO0() () (Input Output Analog RtcIo RtcIoOutput)));
_for_each_inner!((1, GPIO1() () (Input Output Analog RtcIo RtcIoOutput)));
_for_each_inner!((2, GPIO2(_2 => FSPIQ) (_2 => FSPIQ) (Input Output Analog RtcIo
RtcIoOutput))); _for_each_inner!((3, GPIO3() () (Input Output Analog RtcIo
RtcIoOutput))); _for_each_inner!((4, GPIO4(_0 => MTMS _2 => FSPIHD) (_2 =>
FSPIHD) (Input Output Analog RtcIo RtcIoOutput))); _for_each_inner!((5, GPIO5(_0
=> MTDI _2 => FSPIWP) (_2 => FSPIWP) (Input Output Analog RtcIo RtcIoOutput)));
_for_each_inner!((6, GPIO6(_0 => MTCK _2 => FSPICLK) (_2 => FSPICLK) (Input
Output))); _for_each_inner!((7, GPIO7(_2 => FSPID) (_0 => MTDO _2 => FSPID)
(Input Output))); _for_each_inner!((8, GPIO8() () (Input Output)));
_for_each_inner!((9, GPIO9() () (Input Output))); _for_each_inner!((10, GPIO10()
() (Input Output))); _for_each_inner!((11, GPIO11(_0 => SPIHD) (_0 => SPIHD)
(Input Output))); _for_each_inner!((12, GPIO12(_0 => SPIHD) (_0 => SPIHD) (Input
Output))); _for_each_inner!((13, GPIO13(_0 => SPIWP) (_0 => SPIWP) (Input
Output))); _for_each_inner!((14, GPIO14() (_0 => SPICS0) (Input Output)));
_for_each_inner!((15, GPIO15() (_0 => SPICLK) (Input Output)));
_for_each_inner!((16, GPIO16(_0 => SPID) (_0 => SPID) (Input Output)));
_for_each_inner!((17, GPIO17(_0 => SPIQ) (_0 => SPIQ) (Input Output)));
_for_each_inner!((18, GPIO18() () (Input Output))); _for_each_inner!((19,
GPIO19(_0 => U0RXD) () (Input Output))); _for_each_inner!((20, GPIO20() (_0 =>
U0TXD) (Input Output))); _for_each_inner!((all(0, GPIO0() () (Input Output Analog
RtcIo RtcIoOutput)), (1, GPIO1() () (Input Output Analog RtcIo RtcIoOutput)), (2,
GPIO2(_2 => FSPIQ) (_2 => FSPIQ) (Input Output Analog RtcIo RtcIoOutput)), (3,
GPIO3() () (Input Output Analog RtcIo RtcIoOutput)), (4, GPIO4(_0 => MTMS _2 =>
FSPIHD) (_2 => FSPIHD) (Input Output Analog RtcIo RtcIoOutput)), (5, GPIO5(_0 =>
MTDI _2 => FSPIWP) (_2 => FSPIWP) (Input Output Analog RtcIo RtcIoOutput)), (6,
GPIO6(_0 => MTCK _2 => FSPICLK) (_2 => FSPICLK) (Input Output)), (7, GPIO7(_2 =>
FSPID) (_0 => MTDO _2 => FSPID) (Input Output)), (8, GPIO8() () (Input Output)),
(9, GPIO9() () (Input Output)), (10, GPIO10() () (Input Output)), (11, GPIO11(_0
=> SPIHD) (_0 => SPIHD) (Input Output)), (12, GPIO12(_0 => SPIHD) (_0 => SPIHD)
(Input Output)), (13, GPIO13(_0 => SPIWP) (_0 => SPIWP) (Input Output)), (14,
GPIO14() (_0 => SPICS0) (Input Output)), (15, GPIO15() (_0 => SPICLK) (Input
Output)), (16, GPIO16(_0 => SPID) (_0 => SPID) (Input Output)), (17, GPIO17(_0 =>
SPIQ) (_0 => SPIQ) (Input Output)), (18, GPIO18() () (Input Output)), (19,
GPIO19(_0 => U0RXD) () (Input Output)), (20, GPIO20() (_0 => U0TXD) (Input
Output))));
};
}
#[macro_export]
macro_rules! if_pin_is_type {
(GPIO0, Input, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO0, Output, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO0, Analog, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO0, RtcIo, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO0, RtcIoOutput, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO0, $t:tt, $then_tt:tt else $else_tt:tt) => {
$else_tt
};
(GPIO1, Input, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO1, Output, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO1, Analog, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO1, RtcIo, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO1, RtcIoOutput, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO1, $t:tt, $then_tt:tt else $else_tt:tt) => {
$else_tt
};
(GPIO2, Input, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO2, Output, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO2, Analog, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO2, RtcIo, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO2, RtcIoOutput, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO2, $t:tt, $then_tt:tt else $else_tt:tt) => {
$else_tt
};
(GPIO3, Input, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO3, Output, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO3, Analog, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO3, RtcIo, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO3, RtcIoOutput, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO3, $t:tt, $then_tt:tt else $else_tt:tt) => {
$else_tt
};
(GPIO4, Input, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO4, Output, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO4, Analog, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO4, RtcIo, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO4, RtcIoOutput, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO4, $t:tt, $then_tt:tt else $else_tt:tt) => {
$else_tt
};
(GPIO5, Input, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO5, Output, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO5, Analog, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO5, RtcIo, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO5, RtcIoOutput, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO5, $t:tt, $then_tt:tt else $else_tt:tt) => {
$else_tt
};
(GPIO6, Input, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO6, Output, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO6, $t:tt, $then_tt:tt else $else_tt:tt) => {
$else_tt
};
(GPIO7, Input, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO7, Output, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO7, $t:tt, $then_tt:tt else $else_tt:tt) => {
$else_tt
};
(GPIO8, Input, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO8, Output, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO8, $t:tt, $then_tt:tt else $else_tt:tt) => {
$else_tt
};
(GPIO9, Input, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO9, Output, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO9, $t:tt, $then_tt:tt else $else_tt:tt) => {
$else_tt
};
(GPIO10, Input, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO10, Output, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO10, $t:tt, $then_tt:tt else $else_tt:tt) => {
$else_tt
};
(GPIO11, Input, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO11, Output, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO11, $t:tt, $then_tt:tt else $else_tt:tt) => {
$else_tt
};
(GPIO12, Input, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO12, Output, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO12, $t:tt, $then_tt:tt else $else_tt:tt) => {
$else_tt
};
(GPIO13, Input, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO13, Output, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO13, $t:tt, $then_tt:tt else $else_tt:tt) => {
$else_tt
};
(GPIO14, Input, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO14, Output, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO14, $t:tt, $then_tt:tt else $else_tt:tt) => {
$else_tt
};
(GPIO15, Input, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO15, Output, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO15, $t:tt, $then_tt:tt else $else_tt:tt) => {
$else_tt
};
(GPIO16, Input, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO16, Output, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO16, $t:tt, $then_tt:tt else $else_tt:tt) => {
$else_tt
};
(GPIO17, Input, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO17, Output, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO17, $t:tt, $then_tt:tt else $else_tt:tt) => {
$else_tt
};
(GPIO18, Input, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO18, Output, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO18, $t:tt, $then_tt:tt else $else_tt:tt) => {
$else_tt
};
(GPIO19, Input, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO19, Output, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO19, $t:tt, $then_tt:tt else $else_tt:tt) => {
$else_tt
};
(GPIO20, Input, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO20, Output, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO20, $t:tt, $then_tt:tt else $else_tt:tt) => {
$else_tt
};
}
#[macro_export]
#[expect(clippy::crate_in_macro_def)]
macro_rules! impl_for_pin_type {
($any_pin:ident, $inner_ident:ident, $on_type:tt, $code:tt else $otherwise:tt) => {
match $any_pin .number() { 0 => if_pin_is_type!(GPIO0, $on_type, { {
#[allow(unused_unsafe, unused_mut)] let mut $inner_ident = unsafe { crate
::peripherals::GPIO0::steal() }; #[allow(unused_braces)] $code } } else {
$otherwise }), 1 => if_pin_is_type!(GPIO1, $on_type, { { #[allow(unused_unsafe,
unused_mut)] let mut $inner_ident = unsafe { crate ::peripherals::GPIO1::steal()
}; #[allow(unused_braces)] $code } } else { $otherwise }), 2 =>
if_pin_is_type!(GPIO2, $on_type, { { #[allow(unused_unsafe, unused_mut)] let mut
$inner_ident = unsafe { crate ::peripherals::GPIO2::steal() };
#[allow(unused_braces)] $code } } else { $otherwise }), 3 =>
if_pin_is_type!(GPIO3, $on_type, { { #[allow(unused_unsafe, unused_mut)] let mut
$inner_ident = unsafe { crate ::peripherals::GPIO3::steal() };
#[allow(unused_braces)] $code } } else { $otherwise }), 4 =>
if_pin_is_type!(GPIO4, $on_type, { { #[allow(unused_unsafe, unused_mut)] let mut
$inner_ident = unsafe { crate ::peripherals::GPIO4::steal() };
#[allow(unused_braces)] $code } } else { $otherwise }), 5 =>
if_pin_is_type!(GPIO5, $on_type, { { #[allow(unused_unsafe, unused_mut)] let mut
$inner_ident = unsafe { crate ::peripherals::GPIO5::steal() };
#[allow(unused_braces)] $code } } else { $otherwise }), 6 =>
if_pin_is_type!(GPIO6, $on_type, { { #[allow(unused_unsafe, unused_mut)] let mut
$inner_ident = unsafe { crate ::peripherals::GPIO6::steal() };
#[allow(unused_braces)] $code } } else { $otherwise }), 7 =>
if_pin_is_type!(GPIO7, $on_type, { { #[allow(unused_unsafe, unused_mut)] let mut
$inner_ident = unsafe { crate ::peripherals::GPIO7::steal() };
#[allow(unused_braces)] $code } } else { $otherwise }), 8 =>
if_pin_is_type!(GPIO8, $on_type, { { #[allow(unused_unsafe, unused_mut)] let mut
$inner_ident = unsafe { crate ::peripherals::GPIO8::steal() };
#[allow(unused_braces)] $code } } else { $otherwise }), 9 =>
if_pin_is_type!(GPIO9, $on_type, { { #[allow(unused_unsafe, unused_mut)] let mut
$inner_ident = unsafe { crate ::peripherals::GPIO9::steal() };
#[allow(unused_braces)] $code } } else { $otherwise }), 10 =>
if_pin_is_type!(GPIO10, $on_type, { { #[allow(unused_unsafe, unused_mut)] let mut
$inner_ident = unsafe { crate ::peripherals::GPIO10::steal() };
#[allow(unused_braces)] $code } } else { $otherwise }), 11 =>
if_pin_is_type!(GPIO11, $on_type, { { #[allow(unused_unsafe, unused_mut)] let mut
$inner_ident = unsafe { crate ::peripherals::GPIO11::steal() };
#[allow(unused_braces)] $code } } else { $otherwise }), 12 =>
if_pin_is_type!(GPIO12, $on_type, { { #[allow(unused_unsafe, unused_mut)] let mut
$inner_ident = unsafe { crate ::peripherals::GPIO12::steal() };
#[allow(unused_braces)] $code } } else { $otherwise }), 13 =>
if_pin_is_type!(GPIO13, $on_type, { { #[allow(unused_unsafe, unused_mut)] let mut
$inner_ident = unsafe { crate ::peripherals::GPIO13::steal() };
#[allow(unused_braces)] $code } } else { $otherwise }), 14 =>
if_pin_is_type!(GPIO14, $on_type, { { #[allow(unused_unsafe, unused_mut)] let mut
$inner_ident = unsafe { crate ::peripherals::GPIO14::steal() };
#[allow(unused_braces)] $code } } else { $otherwise }), 15 =>
if_pin_is_type!(GPIO15, $on_type, { { #[allow(unused_unsafe, unused_mut)] let mut
$inner_ident = unsafe { crate ::peripherals::GPIO15::steal() };
#[allow(unused_braces)] $code } } else { $otherwise }), 16 =>
if_pin_is_type!(GPIO16, $on_type, { { #[allow(unused_unsafe, unused_mut)] let mut
$inner_ident = unsafe { crate ::peripherals::GPIO16::steal() };
#[allow(unused_braces)] $code } } else { $otherwise }), 17 =>
if_pin_is_type!(GPIO17, $on_type, { { #[allow(unused_unsafe, unused_mut)] let mut
$inner_ident = unsafe { crate ::peripherals::GPIO17::steal() };
#[allow(unused_braces)] $code } } else { $otherwise }), 18 =>
if_pin_is_type!(GPIO18, $on_type, { { #[allow(unused_unsafe, unused_mut)] let mut
$inner_ident = unsafe { crate ::peripherals::GPIO18::steal() };
#[allow(unused_braces)] $code } } else { $otherwise }), 19 =>
if_pin_is_type!(GPIO19, $on_type, { { #[allow(unused_unsafe, unused_mut)] let mut
$inner_ident = unsafe { crate ::peripherals::GPIO19::steal() };
#[allow(unused_braces)] $code } } else { $otherwise }), 20 =>
if_pin_is_type!(GPIO20, $on_type, { { #[allow(unused_unsafe, unused_mut)] let mut
$inner_ident = unsafe { crate ::peripherals::GPIO20::steal() };
#[allow(unused_braces)] $code } } else { $otherwise }), _ => $otherwise, }
};
($any_pin:ident, $inner_ident:ident, $on_type:tt, $code:tt) => {
impl_for_pin_type!($any_pin, $inner_ident, $on_type, $code else {
panic!("Unsupported") })
};
}
#[macro_export]
macro_rules! define_io_mux_signals {
() => {
#[allow(non_camel_case_types, clippy::upper_case_acronyms)]
#[derive(Debug, PartialEq, Copy, Clone)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[doc(hidden)]
pub enum InputSignal {
SPIQ = 0,
SPID = 1,
SPIHD = 2,
SPIWP = 3,
U0RXD = 6,
U0CTS = 7,
U0DSR = 8,
U1RXD = 9,
U1CTS = 10,
U1DSR = 11,
CPU_GPIO_0 = 28,
CPU_GPIO_1 = 29,
CPU_GPIO_2 = 30,
CPU_GPIO_3 = 31,
CPU_GPIO_4 = 32,
CPU_GPIO_5 = 33,
CPU_GPIO_6 = 34,
CPU_GPIO_7 = 35,
EXT_ADC_START = 45,
RMT_SIG_0 = 51,
RMT_SIG_1 = 52,
I2CEXT0_SCL = 53,
I2CEXT0_SDA = 54,
FSPICLK = 63,
FSPIQ = 64,
FSPID = 65,
FSPIHD = 66,
FSPIWP = 67,
FSPICS0 = 68,
SIG_FUNC_97 = 97,
SIG_FUNC_98 = 98,
SIG_FUNC_99 = 99,
SIG_FUNC_100 = 100,
MTCK,
MTMS,
MTDI,
}
#[allow(non_camel_case_types, clippy::upper_case_acronyms)]
#[derive(Debug, PartialEq, Copy, Clone)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[doc(hidden)]
pub enum OutputSignal {
SPIQ = 0,
SPID = 1,
SPIHD = 2,
SPIWP = 3,
SPICLK = 4,
SPICS0 = 5,
U0TXD = 6,
U0RTS = 7,
U0DTR = 8,
U1TXD = 9,
U1RTS = 10,
U1DTR = 11,
SPIQ_MONITOR = 15,
SPID_MONITOR = 16,
SPIHD_MONITOR = 17,
SPIWP_MONITOR = 18,
SPICS1 = 19,
CPU_GPIO_0 = 28,
CPU_GPIO_1 = 29,
CPU_GPIO_2 = 30,
CPU_GPIO_3 = 31,
CPU_GPIO_4 = 32,
CPU_GPIO_5 = 33,
CPU_GPIO_6 = 34,
CPU_GPIO_7 = 35,
LEDC_LS_SIG0 = 45,
LEDC_LS_SIG1 = 46,
LEDC_LS_SIG2 = 47,
LEDC_LS_SIG3 = 48,
LEDC_LS_SIG4 = 49,
LEDC_LS_SIG5 = 50,
RMT_SIG_0 = 51,
RMT_SIG_1 = 52,
I2CEXT0_SCL = 53,
I2CEXT0_SDA = 54,
FSPICLK = 63,
FSPIQ = 64,
FSPID = 65,
FSPIHD = 66,
FSPIWP = 67,
FSPICS0 = 68,
FSPICS1 = 69,
FSPICS3 = 70,
FSPICS2 = 71,
FSPICS4 = 72,
FSPICS5 = 73,
ANT_SEL0 = 89,
ANT_SEL1 = 90,
ANT_SEL2 = 91,
ANT_SEL3 = 92,
ANT_SEL4 = 93,
ANT_SEL5 = 94,
ANT_SEL6 = 95,
ANT_SEL7 = 96,
SIG_FUNC_97 = 97,
SIG_FUNC_98 = 98,
SIG_FUNC_99 = 99,
SIG_FUNC_100 = 100,
CLK_OUT1 = 123,
CLK_OUT2 = 124,
CLK_OUT3 = 125,
GPIO = 128,
MTDO,
}
};
}
#[macro_export]
#[expect(clippy::crate_in_macro_def)]
macro_rules! define_io_mux_reg {
() => {
pub(crate) fn io_mux_reg(gpio_num: u8) -> &'static crate::pac::io_mux::GPIO {
crate::peripherals::IO_MUX::regs().gpio(gpio_num as usize)
}
};
}

View File

@ -0,0 +1,816 @@
/// The name of the chip as `&str`
#[macro_export]
macro_rules! chip {
() => {
"esp32c3"
};
}
/// The properties of this chip and its drivers.
#[macro_export]
macro_rules! property {
("chip") => {
"esp32c3"
};
("arch") => {
"riscv"
};
("cores") => {
1
};
("cores", str) => {
stringify!(1)
};
("trm") => {
"https://www.espressif.com/sites/default/files/documentation/esp32-c3_technical_reference_manual_en.pdf"
};
("assist_debug.has_sp_monitor") => {
true
};
("assist_debug.has_region_monitor") => {
true
};
("gpio.has_bank_1") => {
false
};
("gpio.gpio_function") => {
1
};
("gpio.gpio_function", str) => {
stringify!(1)
};
("gpio.input_signal_max") => {
100
};
("gpio.input_signal_max", str) => {
stringify!(100)
};
("gpio.output_signal_max") => {
128
};
("gpio.output_signal_max", str) => {
stringify!(128)
};
("gpio.constant_0_input") => {
31
};
("gpio.constant_0_input", str) => {
stringify!(31)
};
("gpio.constant_1_input") => {
30
};
("gpio.constant_1_input", str) => {
stringify!(30)
};
("gpio.remap_iomux_pin_registers") => {
false
};
("gpio.func_in_sel_offset") => {
0
};
("gpio.func_in_sel_offset", str) => {
stringify!(0)
};
("i2c_master.has_fsm_timeouts") => {
true
};
("i2c_master.has_hw_bus_clear") => {
true
};
("i2c_master.has_bus_timeout_enable") => {
true
};
("i2c_master.separate_filter_config_registers") => {
false
};
("i2c_master.can_estimate_nack_reason") => {
false
};
("i2c_master.has_conf_update") => {
true
};
("i2c_master.has_reliable_fsm_reset") => {
false
};
("i2c_master.has_arbitration_en") => {
true
};
("i2c_master.has_tx_fifo_watermark") => {
true
};
("i2c_master.bus_timeout_is_exponential") => {
true
};
("i2c_master.max_bus_timeout") => {
31
};
("i2c_master.max_bus_timeout", str) => {
stringify!(31)
};
("i2c_master.ll_intr_mask") => {
262143
};
("i2c_master.ll_intr_mask", str) => {
stringify!(262143)
};
("i2c_master.fifo_size") => {
32
};
("i2c_master.fifo_size", str) => {
stringify!(32)
};
("interrupts.status_registers") => {
2
};
("interrupts.status_registers", str) => {
stringify!(2)
};
("rmt.ram_start") => {
1610703872
};
("rmt.ram_start", str) => {
stringify!(1610703872)
};
("rmt.channel_ram_size") => {
48
};
("rmt.channel_ram_size", str) => {
stringify!(48)
};
("spi_master.has_octal") => {
false
};
("timergroup.timg_has_timer1") => {
false
};
("wifi.has_wifi6") => {
false
};
}
/// Macro to get the address range of the given memory region.
#[macro_export]
macro_rules! memory_range {
("DRAM") => {
1070071808..1070465024
};
}
#[macro_export]
macro_rules! for_each_i2c_master {
($($pattern:tt => $code:tt;)*) => {
macro_rules! _for_each_inner { $(($pattern) => $code;)* ($other : tt) => {} }
_for_each_inner!((I2C0, I2cExt0, I2CEXT0_SCL, I2CEXT0_SDA));
_for_each_inner!((all(I2C0, I2cExt0, I2CEXT0_SCL, I2CEXT0_SDA)));
};
}
#[macro_export]
macro_rules! for_each_uart {
($($pattern:tt => $code:tt;)*) => {
macro_rules! _for_each_inner { $(($pattern) => $code;)* ($other : tt) => {} }
_for_each_inner!((UART0, Uart0, U0RXD, U0TXD, U0CTS, U0RTS));
_for_each_inner!((UART1, Uart1, U1RXD, U1TXD, U1CTS, U1RTS));
_for_each_inner!((all(UART0, Uart0, U0RXD, U0TXD, U0CTS, U0RTS), (UART1, Uart1,
U1RXD, U1TXD, U1CTS, U1RTS)));
};
}
#[macro_export]
macro_rules! for_each_spi_master {
($($pattern:tt => $code:tt;)*) => {
macro_rules! _for_each_inner { $(($pattern) => $code;)* ($other : tt) => {} }
_for_each_inner!((SPI2, Spi2, FSPICLK[FSPICS0, FSPICS1, FSPICS2, FSPICS3,
FSPICS4, FSPICS5] [FSPID, FSPIQ, FSPIWP, FSPIHD], true));
_for_each_inner!((all(SPI2, Spi2, FSPICLK[FSPICS0, FSPICS1, FSPICS2, FSPICS3,
FSPICS4, FSPICS5] [FSPID, FSPIQ, FSPIWP, FSPIHD], true)));
};
}
#[macro_export]
macro_rules! for_each_spi_slave {
($($pattern:tt => $code:tt;)*) => {
macro_rules! _for_each_inner { $(($pattern) => $code;)* ($other : tt) => {} }
_for_each_inner!((SPI2, Spi2, FSPICLK, FSPID, FSPIQ, FSPICS0));
_for_each_inner!((all(SPI2, Spi2, FSPICLK, FSPID, FSPIQ, FSPICS0)));
};
}
#[macro_export]
macro_rules! for_each_peripheral {
($($pattern:tt => $code:tt;)*) => {
macro_rules! _for_each_inner { $(($pattern) => $code;)* ($other : tt) => {} }
_for_each_inner!((GPIO0 <= virtual())); _for_each_inner!((GPIO1 <= virtual()));
_for_each_inner!((GPIO2 <= virtual())); _for_each_inner!((GPIO3 <= virtual()));
_for_each_inner!((GPIO4 <= virtual())); _for_each_inner!((GPIO5 <= virtual()));
_for_each_inner!((GPIO6 <= virtual())); _for_each_inner!((GPIO7 <= virtual()));
_for_each_inner!((GPIO8 <= virtual())); _for_each_inner!((GPIO9 <= virtual()));
_for_each_inner!((GPIO10 <= virtual())); _for_each_inner!((GPIO11 <= virtual()));
_for_each_inner!((GPIO12 <= virtual())); _for_each_inner!((GPIO13 <= virtual()));
_for_each_inner!((GPIO14 <= virtual())); _for_each_inner!((GPIO15 <= virtual()));
_for_each_inner!((GPIO16 <= virtual())); _for_each_inner!((GPIO17 <= virtual()));
_for_each_inner!((GPIO18 <= virtual())); _for_each_inner!((GPIO19 <= virtual()));
_for_each_inner!((GPIO20 <= virtual())); _for_each_inner!((GPIO21 <= virtual()));
_for_each_inner!((AES <= AES() (unstable))); _for_each_inner!((APB_CTRL <=
APB_CTRL() (unstable))); _for_each_inner!((APB_SARADC <= APB_SARADC()
(unstable))); _for_each_inner!((ASSIST_DEBUG <= ASSIST_DEBUG() (unstable)));
_for_each_inner!((BB <= BB() (unstable))); _for_each_inner!((DMA <= DMA()
(unstable))); _for_each_inner!((DS <= DS() (unstable))); _for_each_inner!((EFUSE
<= EFUSE() (unstable))); _for_each_inner!((EXTMEM <= EXTMEM() (unstable)));
_for_each_inner!((FE <= FE() (unstable))); _for_each_inner!((FE2 <= FE2()
(unstable))); _for_each_inner!((GPIO <= GPIO() (unstable)));
_for_each_inner!((GPIO_SD <= GPIO_SD() (unstable))); _for_each_inner!((HMAC <=
HMAC() (unstable))); _for_each_inner!((I2C_ANA_MST <= I2C_ANA_MST() (unstable)));
_for_each_inner!((I2C0 <= I2C0(I2C_EXT0 : { bind_peri_interrupt,
enable_peri_interrupt, disable_peri_interrupt }))); _for_each_inner!((I2S0 <=
I2S0(I2S0 : { bind_peri_interrupt, enable_peri_interrupt, disable_peri_interrupt
}) (unstable))); _for_each_inner!((INTERRUPT_CORE0 <= INTERRUPT_CORE0()
(unstable))); _for_each_inner!((IO_MUX <= IO_MUX() (unstable)));
_for_each_inner!((LEDC <= LEDC() (unstable))); _for_each_inner!((NRX <= NRX()
(unstable))); _for_each_inner!((RMT <= RMT() (unstable))); _for_each_inner!((RNG
<= RNG() (unstable))); _for_each_inner!((RSA <= RSA() (unstable)));
_for_each_inner!((LPWR <= RTC_CNTL() (unstable))); _for_each_inner!((SENSITIVE <=
SENSITIVE() (unstable))); _for_each_inner!((SHA <= SHA() (unstable)));
_for_each_inner!((SPI0 <= SPI0() (unstable))); _for_each_inner!((SPI1 <= SPI1()
(unstable))); _for_each_inner!((SPI2 <= SPI2(SPI2 : { bind_peri_interrupt,
enable_peri_interrupt, disable_peri_interrupt }))); _for_each_inner!((SYSTEM <=
SYSTEM() (unstable))); _for_each_inner!((SYSTIMER <= SYSTIMER() (unstable)));
_for_each_inner!((TIMG0 <= TIMG0() (unstable))); _for_each_inner!((TIMG1 <=
TIMG1() (unstable))); _for_each_inner!((TWAI0 <= TWAI0() (unstable)));
_for_each_inner!((UART0 <= UART0(UART0 : { bind_peri_interrupt,
enable_peri_interrupt, disable_peri_interrupt }))); _for_each_inner!((UART1 <=
UART1(UART1 : { bind_peri_interrupt, enable_peri_interrupt,
disable_peri_interrupt }))); _for_each_inner!((UHCI0 <= UHCI0() (unstable)));
_for_each_inner!((UHCI1 <= UHCI1() (unstable))); _for_each_inner!((USB_DEVICE <=
USB_DEVICE(USB_DEVICE : { bind_peri_interrupt, enable_peri_interrupt,
disable_peri_interrupt }) (unstable))); _for_each_inner!((XTS_AES <= XTS_AES()
(unstable))); _for_each_inner!((DMA_CH0 <= virtual() (unstable)));
_for_each_inner!((DMA_CH1 <= virtual() (unstable))); _for_each_inner!((DMA_CH2 <=
virtual() (unstable))); _for_each_inner!((ADC1 <= virtual() (unstable)));
_for_each_inner!((ADC2 <= virtual() (unstable))); _for_each_inner!((BT <=
virtual() (unstable))); _for_each_inner!((RADIO_CLK <= virtual() (unstable)));
_for_each_inner!((SW_INTERRUPT <= virtual() (unstable))); _for_each_inner!((TSENS
<= virtual() (unstable))); _for_each_inner!((WIFI <= virtual() (unstable)));
_for_each_inner!((all(GPIO0 <= virtual()), (GPIO1 <= virtual()), (GPIO2 <=
virtual()), (GPIO3 <= virtual()), (GPIO4 <= virtual()), (GPIO5 <= virtual()),
(GPIO6 <= virtual()), (GPIO7 <= virtual()), (GPIO8 <= virtual()), (GPIO9 <=
virtual()), (GPIO10 <= virtual()), (GPIO11 <= virtual()), (GPIO12 <= virtual()),
(GPIO13 <= virtual()), (GPIO14 <= virtual()), (GPIO15 <= virtual()), (GPIO16 <=
virtual()), (GPIO17 <= virtual()), (GPIO18 <= virtual()), (GPIO19 <= virtual()),
(GPIO20 <= virtual()), (GPIO21 <= virtual()), (AES <= AES() (unstable)),
(APB_CTRL <= APB_CTRL() (unstable)), (APB_SARADC <= APB_SARADC() (unstable)),
(ASSIST_DEBUG <= ASSIST_DEBUG() (unstable)), (BB <= BB() (unstable)), (DMA <=
DMA() (unstable)), (DS <= DS() (unstable)), (EFUSE <= EFUSE() (unstable)),
(EXTMEM <= EXTMEM() (unstable)), (FE <= FE() (unstable)), (FE2 <= FE2()
(unstable)), (GPIO <= GPIO() (unstable)), (GPIO_SD <= GPIO_SD() (unstable)),
(HMAC <= HMAC() (unstable)), (I2C_ANA_MST <= I2C_ANA_MST() (unstable)), (I2C0 <=
I2C0(I2C_EXT0 : { bind_peri_interrupt, enable_peri_interrupt,
disable_peri_interrupt })), (I2S0 <= I2S0(I2S0 : { bind_peri_interrupt,
enable_peri_interrupt, disable_peri_interrupt }) (unstable)), (INTERRUPT_CORE0 <=
INTERRUPT_CORE0() (unstable)), (IO_MUX <= IO_MUX() (unstable)), (LEDC <= LEDC()
(unstable)), (NRX <= NRX() (unstable)), (RMT <= RMT() (unstable)), (RNG <= RNG()
(unstable)), (RSA <= RSA() (unstable)), (LPWR <= RTC_CNTL() (unstable)),
(SENSITIVE <= SENSITIVE() (unstable)), (SHA <= SHA() (unstable)), (SPI0 <= SPI0()
(unstable)), (SPI1 <= SPI1() (unstable)), (SPI2 <= SPI2(SPI2 : {
bind_peri_interrupt, enable_peri_interrupt, disable_peri_interrupt })), (SYSTEM
<= SYSTEM() (unstable)), (SYSTIMER <= SYSTIMER() (unstable)), (TIMG0 <= TIMG0()
(unstable)), (TIMG1 <= TIMG1() (unstable)), (TWAI0 <= TWAI0() (unstable)), (UART0
<= UART0(UART0 : { bind_peri_interrupt, enable_peri_interrupt,
disable_peri_interrupt })), (UART1 <= UART1(UART1 : { bind_peri_interrupt,
enable_peri_interrupt, disable_peri_interrupt })), (UHCI0 <= UHCI0() (unstable)),
(UHCI1 <= UHCI1() (unstable)), (USB_DEVICE <= USB_DEVICE(USB_DEVICE : {
bind_peri_interrupt, enable_peri_interrupt, disable_peri_interrupt })
(unstable)), (XTS_AES <= XTS_AES() (unstable)), (DMA_CH0 <= virtual()
(unstable)), (DMA_CH1 <= virtual() (unstable)), (DMA_CH2 <= virtual()
(unstable)), (ADC1 <= virtual() (unstable)), (ADC2 <= virtual() (unstable)), (BT
<= virtual() (unstable)), (RADIO_CLK <= virtual() (unstable)), (SW_INTERRUPT <=
virtual() (unstable)), (TSENS <= virtual() (unstable)), (WIFI <= virtual()
(unstable))));
};
}
#[macro_export]
macro_rules! for_each_gpio {
($($pattern:tt => $code:tt;)*) => {
macro_rules! _for_each_inner { $(($pattern) => $code;)* ($other : tt) => {} }
_for_each_inner!((0, GPIO0() () (Input Output Analog RtcIo RtcIoOutput)));
_for_each_inner!((1, GPIO1() () (Input Output Analog RtcIo RtcIoOutput)));
_for_each_inner!((2, GPIO2(_2 => FSPIQ) (_2 => FSPIQ) (Input Output Analog RtcIo
RtcIoOutput))); _for_each_inner!((3, GPIO3() () (Input Output Analog RtcIo
RtcIoOutput))); _for_each_inner!((4, GPIO4(_0 => MTMS _2 => FSPIHD) (_2 =>
FSPIHD) (Input Output Analog RtcIo RtcIoOutput))); _for_each_inner!((5, GPIO5(_0
=> MTDI _2 => FSPIWP) (_2 => FSPIWP) (Input Output Analog RtcIo RtcIoOutput)));
_for_each_inner!((6, GPIO6(_0 => MTCK _2 => FSPICLK) (_2 => FSPICLK) (Input
Output))); _for_each_inner!((7, GPIO7(_2 => FSPID) (_0 => MTDO _2 => FSPID)
(Input Output))); _for_each_inner!((8, GPIO8() () (Input Output)));
_for_each_inner!((9, GPIO9() () (Input Output))); _for_each_inner!((10, GPIO10(_2
=> FSPICS0) (_2 => FSPICS0) (Input Output))); _for_each_inner!((11, GPIO11() ()
(Input Output))); _for_each_inner!((12, GPIO12(_0 => SPIHD) (_0 => SPIHD) (Input
Output))); _for_each_inner!((13, GPIO13(_0 => SPIWP) (_0 => SPIWP) (Input
Output))); _for_each_inner!((14, GPIO14() (_0 => SPICS0) (Input Output)));
_for_each_inner!((15, GPIO15() (_0 => SPICLK) (Input Output)));
_for_each_inner!((16, GPIO16(_0 => SPID) (_0 => SPID) (Input Output)));
_for_each_inner!((17, GPIO17(_0 => SPIQ) (_0 => SPIQ) (Input Output)));
_for_each_inner!((18, GPIO18() () (Input Output UsbDevice)));
_for_each_inner!((19, GPIO19() () (Input Output UsbDevice)));
_for_each_inner!((20, GPIO20(_0 => U0RXD) () (Input Output)));
_for_each_inner!((21, GPIO21() (_0 => U0TXD) (Input Output)));
_for_each_inner!((all(0, GPIO0() () (Input Output Analog RtcIo RtcIoOutput)), (1,
GPIO1() () (Input Output Analog RtcIo RtcIoOutput)), (2, GPIO2(_2 => FSPIQ) (_2
=> FSPIQ) (Input Output Analog RtcIo RtcIoOutput)), (3, GPIO3() () (Input Output
Analog RtcIo RtcIoOutput)), (4, GPIO4(_0 => MTMS _2 => FSPIHD) (_2 => FSPIHD)
(Input Output Analog RtcIo RtcIoOutput)), (5, GPIO5(_0 => MTDI _2 => FSPIWP) (_2
=> FSPIWP) (Input Output Analog RtcIo RtcIoOutput)), (6, GPIO6(_0 => MTCK _2 =>
FSPICLK) (_2 => FSPICLK) (Input Output)), (7, GPIO7(_2 => FSPID) (_0 => MTDO _2
=> FSPID) (Input Output)), (8, GPIO8() () (Input Output)), (9, GPIO9() () (Input
Output)), (10, GPIO10(_2 => FSPICS0) (_2 => FSPICS0) (Input Output)), (11,
GPIO11() () (Input Output)), (12, GPIO12(_0 => SPIHD) (_0 => SPIHD) (Input
Output)), (13, GPIO13(_0 => SPIWP) (_0 => SPIWP) (Input Output)), (14, GPIO14()
(_0 => SPICS0) (Input Output)), (15, GPIO15() (_0 => SPICLK) (Input Output)),
(16, GPIO16(_0 => SPID) (_0 => SPID) (Input Output)), (17, GPIO17(_0 => SPIQ) (_0
=> SPIQ) (Input Output)), (18, GPIO18() () (Input Output UsbDevice)), (19,
GPIO19() () (Input Output UsbDevice)), (20, GPIO20(_0 => U0RXD) () (Input
Output)), (21, GPIO21() (_0 => U0TXD) (Input Output))));
};
}
#[macro_export]
macro_rules! if_pin_is_type {
(GPIO0, Input, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO0, Output, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO0, Analog, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO0, RtcIo, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO0, RtcIoOutput, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO0, $t:tt, $then_tt:tt else $else_tt:tt) => {
$else_tt
};
(GPIO1, Input, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO1, Output, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO1, Analog, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO1, RtcIo, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO1, RtcIoOutput, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO1, $t:tt, $then_tt:tt else $else_tt:tt) => {
$else_tt
};
(GPIO2, Input, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO2, Output, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO2, Analog, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO2, RtcIo, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO2, RtcIoOutput, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO2, $t:tt, $then_tt:tt else $else_tt:tt) => {
$else_tt
};
(GPIO3, Input, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO3, Output, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO3, Analog, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO3, RtcIo, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO3, RtcIoOutput, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO3, $t:tt, $then_tt:tt else $else_tt:tt) => {
$else_tt
};
(GPIO4, Input, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO4, Output, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO4, Analog, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO4, RtcIo, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO4, RtcIoOutput, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO4, $t:tt, $then_tt:tt else $else_tt:tt) => {
$else_tt
};
(GPIO5, Input, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO5, Output, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO5, Analog, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO5, RtcIo, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO5, RtcIoOutput, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO5, $t:tt, $then_tt:tt else $else_tt:tt) => {
$else_tt
};
(GPIO6, Input, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO6, Output, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO6, $t:tt, $then_tt:tt else $else_tt:tt) => {
$else_tt
};
(GPIO7, Input, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO7, Output, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO7, $t:tt, $then_tt:tt else $else_tt:tt) => {
$else_tt
};
(GPIO8, Input, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO8, Output, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO8, $t:tt, $then_tt:tt else $else_tt:tt) => {
$else_tt
};
(GPIO9, Input, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO9, Output, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO9, $t:tt, $then_tt:tt else $else_tt:tt) => {
$else_tt
};
(GPIO10, Input, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO10, Output, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO10, $t:tt, $then_tt:tt else $else_tt:tt) => {
$else_tt
};
(GPIO11, Input, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO11, Output, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO11, $t:tt, $then_tt:tt else $else_tt:tt) => {
$else_tt
};
(GPIO12, Input, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO12, Output, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO12, $t:tt, $then_tt:tt else $else_tt:tt) => {
$else_tt
};
(GPIO13, Input, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO13, Output, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO13, $t:tt, $then_tt:tt else $else_tt:tt) => {
$else_tt
};
(GPIO14, Input, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO14, Output, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO14, $t:tt, $then_tt:tt else $else_tt:tt) => {
$else_tt
};
(GPIO15, Input, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO15, Output, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO15, $t:tt, $then_tt:tt else $else_tt:tt) => {
$else_tt
};
(GPIO16, Input, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO16, Output, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO16, $t:tt, $then_tt:tt else $else_tt:tt) => {
$else_tt
};
(GPIO17, Input, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO17, Output, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO17, $t:tt, $then_tt:tt else $else_tt:tt) => {
$else_tt
};
(GPIO18, Input, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO18, Output, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO18, UsbDevice, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO18, $t:tt, $then_tt:tt else $else_tt:tt) => {
$else_tt
};
(GPIO19, Input, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO19, Output, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO19, UsbDevice, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO19, $t:tt, $then_tt:tt else $else_tt:tt) => {
$else_tt
};
(GPIO20, Input, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO20, Output, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO20, $t:tt, $then_tt:tt else $else_tt:tt) => {
$else_tt
};
(GPIO21, Input, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO21, Output, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO21, $t:tt, $then_tt:tt else $else_tt:tt) => {
$else_tt
};
}
#[macro_export]
#[expect(clippy::crate_in_macro_def)]
macro_rules! impl_for_pin_type {
($any_pin:ident, $inner_ident:ident, $on_type:tt, $code:tt else $otherwise:tt) => {
match $any_pin .number() { 0 => if_pin_is_type!(GPIO0, $on_type, { {
#[allow(unused_unsafe, unused_mut)] let mut $inner_ident = unsafe { crate
::peripherals::GPIO0::steal() }; #[allow(unused_braces)] $code } } else {
$otherwise }), 1 => if_pin_is_type!(GPIO1, $on_type, { { #[allow(unused_unsafe,
unused_mut)] let mut $inner_ident = unsafe { crate ::peripherals::GPIO1::steal()
}; #[allow(unused_braces)] $code } } else { $otherwise }), 2 =>
if_pin_is_type!(GPIO2, $on_type, { { #[allow(unused_unsafe, unused_mut)] let mut
$inner_ident = unsafe { crate ::peripherals::GPIO2::steal() };
#[allow(unused_braces)] $code } } else { $otherwise }), 3 =>
if_pin_is_type!(GPIO3, $on_type, { { #[allow(unused_unsafe, unused_mut)] let mut
$inner_ident = unsafe { crate ::peripherals::GPIO3::steal() };
#[allow(unused_braces)] $code } } else { $otherwise }), 4 =>
if_pin_is_type!(GPIO4, $on_type, { { #[allow(unused_unsafe, unused_mut)] let mut
$inner_ident = unsafe { crate ::peripherals::GPIO4::steal() };
#[allow(unused_braces)] $code } } else { $otherwise }), 5 =>
if_pin_is_type!(GPIO5, $on_type, { { #[allow(unused_unsafe, unused_mut)] let mut
$inner_ident = unsafe { crate ::peripherals::GPIO5::steal() };
#[allow(unused_braces)] $code } } else { $otherwise }), 6 =>
if_pin_is_type!(GPIO6, $on_type, { { #[allow(unused_unsafe, unused_mut)] let mut
$inner_ident = unsafe { crate ::peripherals::GPIO6::steal() };
#[allow(unused_braces)] $code } } else { $otherwise }), 7 =>
if_pin_is_type!(GPIO7, $on_type, { { #[allow(unused_unsafe, unused_mut)] let mut
$inner_ident = unsafe { crate ::peripherals::GPIO7::steal() };
#[allow(unused_braces)] $code } } else { $otherwise }), 8 =>
if_pin_is_type!(GPIO8, $on_type, { { #[allow(unused_unsafe, unused_mut)] let mut
$inner_ident = unsafe { crate ::peripherals::GPIO8::steal() };
#[allow(unused_braces)] $code } } else { $otherwise }), 9 =>
if_pin_is_type!(GPIO9, $on_type, { { #[allow(unused_unsafe, unused_mut)] let mut
$inner_ident = unsafe { crate ::peripherals::GPIO9::steal() };
#[allow(unused_braces)] $code } } else { $otherwise }), 10 =>
if_pin_is_type!(GPIO10, $on_type, { { #[allow(unused_unsafe, unused_mut)] let mut
$inner_ident = unsafe { crate ::peripherals::GPIO10::steal() };
#[allow(unused_braces)] $code } } else { $otherwise }), 11 =>
if_pin_is_type!(GPIO11, $on_type, { { #[allow(unused_unsafe, unused_mut)] let mut
$inner_ident = unsafe { crate ::peripherals::GPIO11::steal() };
#[allow(unused_braces)] $code } } else { $otherwise }), 12 =>
if_pin_is_type!(GPIO12, $on_type, { { #[allow(unused_unsafe, unused_mut)] let mut
$inner_ident = unsafe { crate ::peripherals::GPIO12::steal() };
#[allow(unused_braces)] $code } } else { $otherwise }), 13 =>
if_pin_is_type!(GPIO13, $on_type, { { #[allow(unused_unsafe, unused_mut)] let mut
$inner_ident = unsafe { crate ::peripherals::GPIO13::steal() };
#[allow(unused_braces)] $code } } else { $otherwise }), 14 =>
if_pin_is_type!(GPIO14, $on_type, { { #[allow(unused_unsafe, unused_mut)] let mut
$inner_ident = unsafe { crate ::peripherals::GPIO14::steal() };
#[allow(unused_braces)] $code } } else { $otherwise }), 15 =>
if_pin_is_type!(GPIO15, $on_type, { { #[allow(unused_unsafe, unused_mut)] let mut
$inner_ident = unsafe { crate ::peripherals::GPIO15::steal() };
#[allow(unused_braces)] $code } } else { $otherwise }), 16 =>
if_pin_is_type!(GPIO16, $on_type, { { #[allow(unused_unsafe, unused_mut)] let mut
$inner_ident = unsafe { crate ::peripherals::GPIO16::steal() };
#[allow(unused_braces)] $code } } else { $otherwise }), 17 =>
if_pin_is_type!(GPIO17, $on_type, { { #[allow(unused_unsafe, unused_mut)] let mut
$inner_ident = unsafe { crate ::peripherals::GPIO17::steal() };
#[allow(unused_braces)] $code } } else { $otherwise }), 18 =>
if_pin_is_type!(GPIO18, $on_type, { { #[allow(unused_unsafe, unused_mut)] let mut
$inner_ident = unsafe { crate ::peripherals::GPIO18::steal() };
#[allow(unused_braces)] $code } } else { $otherwise }), 19 =>
if_pin_is_type!(GPIO19, $on_type, { { #[allow(unused_unsafe, unused_mut)] let mut
$inner_ident = unsafe { crate ::peripherals::GPIO19::steal() };
#[allow(unused_braces)] $code } } else { $otherwise }), 20 =>
if_pin_is_type!(GPIO20, $on_type, { { #[allow(unused_unsafe, unused_mut)] let mut
$inner_ident = unsafe { crate ::peripherals::GPIO20::steal() };
#[allow(unused_braces)] $code } } else { $otherwise }), 21 =>
if_pin_is_type!(GPIO21, $on_type, { { #[allow(unused_unsafe, unused_mut)] let mut
$inner_ident = unsafe { crate ::peripherals::GPIO21::steal() };
#[allow(unused_braces)] $code } } else { $otherwise }), _ => $otherwise, }
};
($any_pin:ident, $inner_ident:ident, $on_type:tt, $code:tt) => {
impl_for_pin_type!($any_pin, $inner_ident, $on_type, $code else {
panic!("Unsupported") })
};
}
#[macro_export]
macro_rules! define_io_mux_signals {
() => {
#[allow(non_camel_case_types, clippy::upper_case_acronyms)]
#[derive(Debug, PartialEq, Copy, Clone)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[doc(hidden)]
pub enum InputSignal {
SPIQ = 0,
SPID = 1,
SPIHD = 2,
SPIWP = 3,
U0RXD = 6,
U0CTS = 7,
U0DSR = 8,
U1RXD = 9,
U1CTS = 10,
U1DSR = 11,
I2S_MCLK = 12,
I2SO_BCK = 13,
I2SO_WS = 14,
I2SI_SD = 15,
I2SI_BCK = 16,
I2SI_WS = 17,
GPIO_BT_PRIORITY = 18,
GPIO_BT_ACTIVE = 19,
CPU_GPIO_0 = 28,
CPU_GPIO_1 = 29,
CPU_GPIO_2 = 30,
CPU_GPIO_3 = 31,
CPU_GPIO_4 = 32,
CPU_GPIO_5 = 33,
CPU_GPIO_6 = 34,
CPU_GPIO_7 = 35,
EXT_ADC_START = 45,
RMT_SIG_0 = 51,
RMT_SIG_1 = 52,
I2CEXT0_SCL = 53,
I2CEXT0_SDA = 54,
FSPICLK = 63,
FSPIQ = 64,
FSPID = 65,
FSPIHD = 66,
FSPIWP = 67,
FSPICS0 = 68,
TWAI_RX = 74,
SIG_FUNC_97 = 97,
SIG_FUNC_98 = 98,
SIG_FUNC_99 = 99,
SIG_FUNC_100 = 100,
MTCK,
MTMS,
MTDI,
}
#[allow(non_camel_case_types, clippy::upper_case_acronyms)]
#[derive(Debug, PartialEq, Copy, Clone)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[doc(hidden)]
pub enum OutputSignal {
SPIQ = 0,
SPID = 1,
SPIHD = 2,
SPIWP = 3,
SPICLK = 4,
SPICS0 = 5,
U0TXD = 6,
U0RTS = 7,
U0DTR = 8,
U1TXD = 9,
U1RTS = 10,
U1DTR = 11,
I2S_MCLK = 12,
I2SO_BCK = 13,
I2SO_WS = 14,
I2SO_SD = 15,
I2SI_BCK = 16,
I2SI_WS = 17,
GPIO_WLAN_PRIO = 18,
GPIO_WLAN_ACTIVE = 19,
CPU_GPIO_0 = 28,
CPU_GPIO_1 = 29,
CPU_GPIO_2 = 30,
CPU_GPIO_3 = 31,
CPU_GPIO_4 = 32,
CPU_GPIO_5 = 33,
CPU_GPIO_6 = 34,
CPU_GPIO_7 = 35,
USB_JTAG_TCK = 36,
USB_JTAG_TMS = 37,
USB_JTAG_TDI = 38,
USB_JTAG_TDO = 39,
LEDC_LS_SIG0 = 45,
LEDC_LS_SIG1 = 46,
LEDC_LS_SIG2 = 47,
LEDC_LS_SIG3 = 48,
LEDC_LS_SIG4 = 49,
LEDC_LS_SIG5 = 50,
RMT_SIG_0 = 51,
RMT_SIG_1 = 52,
I2CEXT0_SCL = 53,
I2CEXT0_SDA = 54,
GPIO_SD0 = 55,
GPIO_SD1 = 56,
GPIO_SD2 = 57,
GPIO_SD3 = 58,
I2SO_SD1 = 59,
FSPICLK = 63,
FSPIQ = 64,
FSPID = 65,
FSPIHD = 66,
FSPIWP = 67,
FSPICS0 = 68,
FSPICS1 = 69,
FSPICS3 = 70,
FSPICS2 = 71,
FSPICS4 = 72,
FSPICS5 = 73,
TWAI_TX = 74,
TWAI_BUS_OFF_ON = 75,
TWAI_CLKOUT = 76,
ANT_SEL0 = 89,
ANT_SEL1 = 90,
ANT_SEL2 = 91,
ANT_SEL3 = 92,
ANT_SEL4 = 93,
ANT_SEL5 = 94,
ANT_SEL6 = 95,
ANT_SEL7 = 96,
SIG_FUNC_97 = 97,
SIG_FUNC_98 = 98,
SIG_FUNC_99 = 99,
SIG_FUNC_100 = 100,
CLK_OUT1 = 123,
CLK_OUT2 = 124,
CLK_OUT3 = 125,
SPICS1 = 126,
USB_JTAG_TRST = 127,
GPIO = 128,
MTDO,
}
};
}
#[macro_export]
#[expect(clippy::crate_in_macro_def)]
macro_rules! define_io_mux_reg {
() => {
pub(crate) fn io_mux_reg(gpio_num: u8) -> &'static crate::pac::io_mux::GPIO {
crate::peripherals::IO_MUX::regs().gpio(gpio_num as usize)
}
};
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,848 @@
/// The name of the chip as `&str`
#[macro_export]
macro_rules! chip {
() => {
"esp32h2"
};
}
/// The properties of this chip and its drivers.
#[macro_export]
macro_rules! property {
("chip") => {
"esp32h2"
};
("arch") => {
"riscv"
};
("cores") => {
1
};
("cores", str) => {
stringify!(1)
};
("trm") => {
"https://www.espressif.com/sites/default/files/documentation/esp32-h2_technical_reference_manual_en.pdf"
};
("assist_debug.has_sp_monitor") => {
true
};
("assist_debug.has_region_monitor") => {
true
};
("gpio.has_bank_1") => {
false
};
("gpio.gpio_function") => {
1
};
("gpio.gpio_function", str) => {
stringify!(1)
};
("gpio.input_signal_max") => {
124
};
("gpio.input_signal_max", str) => {
stringify!(124)
};
("gpio.output_signal_max") => {
128
};
("gpio.output_signal_max", str) => {
stringify!(128)
};
("gpio.constant_0_input") => {
60
};
("gpio.constant_0_input", str) => {
stringify!(60)
};
("gpio.constant_1_input") => {
56
};
("gpio.constant_1_input", str) => {
stringify!(56)
};
("gpio.remap_iomux_pin_registers") => {
false
};
("gpio.func_in_sel_offset") => {
0
};
("gpio.func_in_sel_offset", str) => {
stringify!(0)
};
("i2c_master.has_fsm_timeouts") => {
true
};
("i2c_master.has_hw_bus_clear") => {
true
};
("i2c_master.has_bus_timeout_enable") => {
true
};
("i2c_master.separate_filter_config_registers") => {
false
};
("i2c_master.can_estimate_nack_reason") => {
true
};
("i2c_master.has_conf_update") => {
true
};
("i2c_master.has_reliable_fsm_reset") => {
true
};
("i2c_master.has_arbitration_en") => {
true
};
("i2c_master.has_tx_fifo_watermark") => {
true
};
("i2c_master.bus_timeout_is_exponential") => {
true
};
("i2c_master.max_bus_timeout") => {
31
};
("i2c_master.max_bus_timeout", str) => {
stringify!(31)
};
("i2c_master.ll_intr_mask") => {
262143
};
("i2c_master.ll_intr_mask", str) => {
stringify!(262143)
};
("i2c_master.fifo_size") => {
32
};
("i2c_master.fifo_size", str) => {
stringify!(32)
};
("interrupts.status_registers") => {
2
};
("interrupts.status_registers", str) => {
stringify!(2)
};
("rmt.ram_start") => {
1610642432
};
("rmt.ram_start", str) => {
stringify!(1610642432)
};
("rmt.channel_ram_size") => {
48
};
("rmt.channel_ram_size", str) => {
stringify!(48)
};
("spi_master.has_octal") => {
false
};
("timergroup.timg_has_timer1") => {
false
};
}
/// Macro to get the address range of the given memory region.
#[macro_export]
macro_rules! memory_range {
("DRAM") => {
1082130432..1082458112
};
}
#[macro_export]
macro_rules! for_each_i2c_master {
($($pattern:tt => $code:tt;)*) => {
macro_rules! _for_each_inner { $(($pattern) => $code;)* ($other : tt) => {} }
_for_each_inner!((I2C0, I2cExt0, I2CEXT0_SCL, I2CEXT0_SDA));
_for_each_inner!((I2C1, I2cExt1, I2CEXT1_SCL, I2CEXT1_SDA));
_for_each_inner!((all(I2C0, I2cExt0, I2CEXT0_SCL, I2CEXT0_SDA), (I2C1, I2cExt1,
I2CEXT1_SCL, I2CEXT1_SDA)));
};
}
#[macro_export]
macro_rules! for_each_uart {
($($pattern:tt => $code:tt;)*) => {
macro_rules! _for_each_inner { $(($pattern) => $code;)* ($other : tt) => {} }
_for_each_inner!((UART0, Uart0, U0RXD, U0TXD, U0CTS, U0RTS));
_for_each_inner!((UART1, Uart1, U1RXD, U1TXD, U1CTS, U1RTS));
_for_each_inner!((all(UART0, Uart0, U0RXD, U0TXD, U0CTS, U0RTS), (UART1, Uart1,
U1RXD, U1TXD, U1CTS, U1RTS)));
};
}
#[macro_export]
macro_rules! for_each_spi_master {
($($pattern:tt => $code:tt;)*) => {
macro_rules! _for_each_inner { $(($pattern) => $code;)* ($other : tt) => {} }
_for_each_inner!((SPI2, Spi2, FSPICLK[FSPICS0, FSPICS1, FSPICS2, FSPICS3,
FSPICS4, FSPICS5] [FSPID, FSPIQ, FSPIWP, FSPIHD], true));
_for_each_inner!((all(SPI2, Spi2, FSPICLK[FSPICS0, FSPICS1, FSPICS2, FSPICS3,
FSPICS4, FSPICS5] [FSPID, FSPIQ, FSPIWP, FSPIHD], true)));
};
}
#[macro_export]
macro_rules! for_each_spi_slave {
($($pattern:tt => $code:tt;)*) => {
macro_rules! _for_each_inner { $(($pattern) => $code;)* ($other : tt) => {} }
_for_each_inner!((SPI2, Spi2, FSPICLK, FSPID, FSPIQ, FSPICS0));
_for_each_inner!((all(SPI2, Spi2, FSPICLK, FSPID, FSPIQ, FSPICS0)));
};
}
#[macro_export]
macro_rules! for_each_peripheral {
($($pattern:tt => $code:tt;)*) => {
macro_rules! _for_each_inner { $(($pattern) => $code;)* ($other : tt) => {} }
_for_each_inner!((GPIO0 <= virtual())); _for_each_inner!((GPIO1 <= virtual()));
_for_each_inner!((GPIO2 <= virtual())); _for_each_inner!((GPIO3 <= virtual()));
_for_each_inner!((GPIO4 <= virtual())); _for_each_inner!((GPIO5 <= virtual()));
_for_each_inner!((GPIO6 <= virtual())); _for_each_inner!((GPIO7 <= virtual()));
_for_each_inner!((GPIO8 <= virtual())); _for_each_inner!((GPIO9 <= virtual()));
_for_each_inner!((GPIO10 <= virtual())); _for_each_inner!((GPIO11 <= virtual()));
_for_each_inner!((GPIO12 <= virtual())); _for_each_inner!((GPIO13 <= virtual()));
_for_each_inner!((GPIO14 <= virtual())); _for_each_inner!((GPIO22 <= virtual()));
_for_each_inner!((GPIO23 <= virtual())); _for_each_inner!((GPIO24 <= virtual()));
_for_each_inner!((GPIO25 <= virtual())); _for_each_inner!((GPIO26 <= virtual()));
_for_each_inner!((GPIO27 <= virtual())); _for_each_inner!((AES <= AES()
(unstable))); _for_each_inner!((APB_SARADC <= APB_SARADC() (unstable)));
_for_each_inner!((ASSIST_DEBUG <= ASSIST_DEBUG() (unstable)));
_for_each_inner!((DMA <= DMA() (unstable))); _for_each_inner!((DS <= DS()
(unstable))); _for_each_inner!((ECC <= ECC() (unstable)));
_for_each_inner!((EFUSE <= EFUSE() (unstable))); _for_each_inner!((GPIO <= GPIO()
(unstable))); _for_each_inner!((GPIO_SD <= GPIO_SD() (unstable)));
_for_each_inner!((HMAC <= HMAC() (unstable))); _for_each_inner!((HP_APM <=
HP_APM() (unstable))); _for_each_inner!((HP_SYS <= HP_SYS() (unstable)));
_for_each_inner!((I2C_ANA_MST <= I2C_ANA_MST() (unstable)));
_for_each_inner!((I2C0 <= I2C0(I2C_EXT0 : { bind_peri_interrupt,
enable_peri_interrupt, disable_peri_interrupt }))); _for_each_inner!((I2C1 <=
I2C1(I2C_EXT1 : { bind_peri_interrupt, enable_peri_interrupt,
disable_peri_interrupt }))); _for_each_inner!((I2S0 <= I2S0(I2S0 : {
bind_peri_interrupt, enable_peri_interrupt, disable_peri_interrupt })
(unstable))); _for_each_inner!((IEEE802154 <= IEEE802154() (unstable)));
_for_each_inner!((INTERRUPT_CORE0 <= INTERRUPT_CORE0() (unstable)));
_for_each_inner!((INTPRI <= INTPRI() (unstable))); _for_each_inner!((IO_MUX <=
IO_MUX() (unstable))); _for_each_inner!((LEDC <= LEDC() (unstable)));
_for_each_inner!((LPWR <= LP_CLKRST() (unstable))); _for_each_inner!((LP_ANA <=
LP_ANA() (unstable))); _for_each_inner!((LP_AON <= LP_AON() (unstable)));
_for_each_inner!((LP_APM <= LP_APM() (unstable))); _for_each_inner!((LP_APM0 <=
LP_APM0() (unstable))); _for_each_inner!((LP_CLKRST <= LP_CLKRST() (unstable)));
_for_each_inner!((LP_PERI <= LP_PERI() (unstable))); _for_each_inner!((LP_TIMER
<= LP_TIMER() (unstable))); _for_each_inner!((LP_WDT <= LP_WDT() (unstable)));
_for_each_inner!((MCPWM0 <= MCPWM0() (unstable))); _for_each_inner!((MEM_MONITOR
<= MEM_MONITOR() (unstable))); _for_each_inner!((MODEM_LPCON <= MODEM_LPCON()
(unstable))); _for_each_inner!((MODEM_SYSCON <= MODEM_SYSCON() (unstable)));
_for_each_inner!((OTP_DEBUG <= OTP_DEBUG() (unstable)));
_for_each_inner!((PARL_IO <= PARL_IO(PARL_IO_RX : { bind_rx_interrupt,
enable_rx_interrupt, disable_rx_interrupt }, PARL_IO_TX : { bind_tx_interrupt,
enable_tx_interrupt, disable_tx_interrupt }) (unstable))); _for_each_inner!((PAU
<= PAU() (unstable))); _for_each_inner!((PCNT <= PCNT() (unstable)));
_for_each_inner!((PCR <= PCR() (unstable))); _for_each_inner!((PLIC_MX <=
PLIC_MX() (unstable))); _for_each_inner!((PMU <= PMU() (unstable)));
_for_each_inner!((RMT <= RMT() (unstable))); _for_each_inner!((RNG <= RNG()
(unstable))); _for_each_inner!((RSA <= RSA() (unstable))); _for_each_inner!((SHA
<= SHA() (unstable))); _for_each_inner!((ETM <= SOC_ETM() (unstable)));
_for_each_inner!((SPI0 <= SPI0() (unstable))); _for_each_inner!((SPI1 <= SPI1()
(unstable))); _for_each_inner!((SPI2 <= SPI2(SPI2 : { bind_peri_interrupt,
enable_peri_interrupt, disable_peri_interrupt }))); _for_each_inner!((SYSTEM <=
PCR() (unstable))); _for_each_inner!((SYSTIMER <= SYSTIMER() (unstable)));
_for_each_inner!((TEE <= TEE() (unstable))); _for_each_inner!((TIMG0 <= TIMG0()
(unstable))); _for_each_inner!((TIMG1 <= TIMG1() (unstable)));
_for_each_inner!((TRACE0 <= TRACE() (unstable))); _for_each_inner!((TWAI0 <=
TWAI0() (unstable))); _for_each_inner!((UART0 <= UART0(UART0 : {
bind_peri_interrupt, enable_peri_interrupt, disable_peri_interrupt })));
_for_each_inner!((UART1 <= UART1(UART1 : { bind_peri_interrupt,
enable_peri_interrupt, disable_peri_interrupt }))); _for_each_inner!((UHCI0 <=
UHCI0() (unstable))); _for_each_inner!((USB_DEVICE <= USB_DEVICE(USB_DEVICE : {
bind_peri_interrupt, enable_peri_interrupt, disable_peri_interrupt })
(unstable))); _for_each_inner!((DMA_CH0 <= virtual() (unstable)));
_for_each_inner!((DMA_CH1 <= virtual() (unstable))); _for_each_inner!((DMA_CH2 <=
virtual() (unstable))); _for_each_inner!((ADC1 <= virtual() (unstable)));
_for_each_inner!((BT <= virtual() (unstable))); _for_each_inner!((RADIO_CLK <=
virtual() (unstable))); _for_each_inner!((SW_INTERRUPT <= virtual() (unstable)));
_for_each_inner!((MEM2MEM1 <= virtual() (unstable))); _for_each_inner!((MEM2MEM4
<= virtual() (unstable))); _for_each_inner!((MEM2MEM5 <= virtual() (unstable)));
_for_each_inner!((MEM2MEM10 <= virtual() (unstable)));
_for_each_inner!((MEM2MEM11 <= virtual() (unstable)));
_for_each_inner!((MEM2MEM12 <= virtual() (unstable)));
_for_each_inner!((MEM2MEM13 <= virtual() (unstable)));
_for_each_inner!((MEM2MEM14 <= virtual() (unstable)));
_for_each_inner!((MEM2MEM15 <= virtual() (unstable)));
_for_each_inner!((all(GPIO0 <= virtual()), (GPIO1 <= virtual()), (GPIO2 <=
virtual()), (GPIO3 <= virtual()), (GPIO4 <= virtual()), (GPIO5 <= virtual()),
(GPIO6 <= virtual()), (GPIO7 <= virtual()), (GPIO8 <= virtual()), (GPIO9 <=
virtual()), (GPIO10 <= virtual()), (GPIO11 <= virtual()), (GPIO12 <= virtual()),
(GPIO13 <= virtual()), (GPIO14 <= virtual()), (GPIO22 <= virtual()), (GPIO23 <=
virtual()), (GPIO24 <= virtual()), (GPIO25 <= virtual()), (GPIO26 <= virtual()),
(GPIO27 <= virtual()), (AES <= AES() (unstable)), (APB_SARADC <= APB_SARADC()
(unstable)), (ASSIST_DEBUG <= ASSIST_DEBUG() (unstable)), (DMA <= DMA()
(unstable)), (DS <= DS() (unstable)), (ECC <= ECC() (unstable)), (EFUSE <=
EFUSE() (unstable)), (GPIO <= GPIO() (unstable)), (GPIO_SD <= GPIO_SD()
(unstable)), (HMAC <= HMAC() (unstable)), (HP_APM <= HP_APM() (unstable)),
(HP_SYS <= HP_SYS() (unstable)), (I2C_ANA_MST <= I2C_ANA_MST() (unstable)), (I2C0
<= I2C0(I2C_EXT0 : { bind_peri_interrupt, enable_peri_interrupt,
disable_peri_interrupt })), (I2C1 <= I2C1(I2C_EXT1 : { bind_peri_interrupt,
enable_peri_interrupt, disable_peri_interrupt })), (I2S0 <= I2S0(I2S0 : {
bind_peri_interrupt, enable_peri_interrupt, disable_peri_interrupt })
(unstable)), (IEEE802154 <= IEEE802154() (unstable)), (INTERRUPT_CORE0 <=
INTERRUPT_CORE0() (unstable)), (INTPRI <= INTPRI() (unstable)), (IO_MUX <=
IO_MUX() (unstable)), (LEDC <= LEDC() (unstable)), (LPWR <= LP_CLKRST()
(unstable)), (LP_ANA <= LP_ANA() (unstable)), (LP_AON <= LP_AON() (unstable)),
(LP_APM <= LP_APM() (unstable)), (LP_APM0 <= LP_APM0() (unstable)), (LP_CLKRST <=
LP_CLKRST() (unstable)), (LP_PERI <= LP_PERI() (unstable)), (LP_TIMER <=
LP_TIMER() (unstable)), (LP_WDT <= LP_WDT() (unstable)), (MCPWM0 <= MCPWM0()
(unstable)), (MEM_MONITOR <= MEM_MONITOR() (unstable)), (MODEM_LPCON <=
MODEM_LPCON() (unstable)), (MODEM_SYSCON <= MODEM_SYSCON() (unstable)),
(OTP_DEBUG <= OTP_DEBUG() (unstable)), (PARL_IO <= PARL_IO(PARL_IO_RX : {
bind_rx_interrupt, enable_rx_interrupt, disable_rx_interrupt }, PARL_IO_TX : {
bind_tx_interrupt, enable_tx_interrupt, disable_tx_interrupt }) (unstable)), (PAU
<= PAU() (unstable)), (PCNT <= PCNT() (unstable)), (PCR <= PCR() (unstable)),
(PLIC_MX <= PLIC_MX() (unstable)), (PMU <= PMU() (unstable)), (RMT <= RMT()
(unstable)), (RNG <= RNG() (unstable)), (RSA <= RSA() (unstable)), (SHA <= SHA()
(unstable)), (ETM <= SOC_ETM() (unstable)), (SPI0 <= SPI0() (unstable)), (SPI1 <=
SPI1() (unstable)), (SPI2 <= SPI2(SPI2 : { bind_peri_interrupt,
enable_peri_interrupt, disable_peri_interrupt })), (SYSTEM <= PCR() (unstable)),
(SYSTIMER <= SYSTIMER() (unstable)), (TEE <= TEE() (unstable)), (TIMG0 <= TIMG0()
(unstable)), (TIMG1 <= TIMG1() (unstable)), (TRACE0 <= TRACE() (unstable)),
(TWAI0 <= TWAI0() (unstable)), (UART0 <= UART0(UART0 : { bind_peri_interrupt,
enable_peri_interrupt, disable_peri_interrupt })), (UART1 <= UART1(UART1 : {
bind_peri_interrupt, enable_peri_interrupt, disable_peri_interrupt })), (UHCI0 <=
UHCI0() (unstable)), (USB_DEVICE <= USB_DEVICE(USB_DEVICE : {
bind_peri_interrupt, enable_peri_interrupt, disable_peri_interrupt })
(unstable)), (DMA_CH0 <= virtual() (unstable)), (DMA_CH1 <= virtual()
(unstable)), (DMA_CH2 <= virtual() (unstable)), (ADC1 <= virtual() (unstable)),
(BT <= virtual() (unstable)), (RADIO_CLK <= virtual() (unstable)), (SW_INTERRUPT
<= virtual() (unstable)), (MEM2MEM1 <= virtual() (unstable)), (MEM2MEM4 <=
virtual() (unstable)), (MEM2MEM5 <= virtual() (unstable)), (MEM2MEM10 <=
virtual() (unstable)), (MEM2MEM11 <= virtual() (unstable)), (MEM2MEM12 <=
virtual() (unstable)), (MEM2MEM13 <= virtual() (unstable)), (MEM2MEM14 <=
virtual() (unstable)), (MEM2MEM15 <= virtual() (unstable))));
};
}
#[macro_export]
macro_rules! for_each_gpio {
($($pattern:tt => $code:tt;)*) => {
macro_rules! _for_each_inner { $(($pattern) => $code;)* ($other : tt) => {} }
_for_each_inner!((0, GPIO0(_2 => FSPIQ) (_2 => FSPIQ) (Input Output Analog)));
_for_each_inner!((1, GPIO1(_2 => FSPICS0) (_2 => FSPICS0) (Input Output
Analog))); _for_each_inner!((2, GPIO2(_0 => MTMS _2 => FSPIWP) (_2 => FSPIWP)
(Input Output Analog))); _for_each_inner!((3, GPIO3(_0 => MTDI _2 => FSPIHD) (_2
=> FSPIHD) (Input Output Analog))); _for_each_inner!((4, GPIO4(_0 => MTCK _2 =>
FSPICLK) (_2 => FSPICLK) (Input Output Analog))); _for_each_inner!((5, GPIO5(_2
=> FSPID) (_0 => MTDO _2 => FSPID) (Input Output Analog))); _for_each_inner!((6,
GPIO6() () (Input Output))); _for_each_inner!((7, GPIO7() () (Input Output)));
_for_each_inner!((8, GPIO8() () (Input Output))); _for_each_inner!((9, GPIO9() ()
(Input Output))); _for_each_inner!((10, GPIO10() () (Input Output)));
_for_each_inner!((11, GPIO11() () (Input Output))); _for_each_inner!((12,
GPIO12() () (Input Output))); _for_each_inner!((13, GPIO13() () (Input Output)));
_for_each_inner!((14, GPIO14() () (Input Output))); _for_each_inner!((22,
GPIO22() () (Input Output))); _for_each_inner!((23, GPIO23(_0 => U0RXD) (_2 =>
FSPICS1) (Input Output))); _for_each_inner!((24, GPIO24() (_0 => U0TXD _2 =>
FSPICS2) (Input Output))); _for_each_inner!((25, GPIO25() (_2 => FSPICS3) (Input
Output))); _for_each_inner!((26, GPIO26() (_2 => FSPICS4) (Input Output
UsbDevice))); _for_each_inner!((27, GPIO27() (_2 => FSPICS5) (Input Output
UsbDevice))); _for_each_inner!((all(0, GPIO0(_2 => FSPIQ) (_2 => FSPIQ) (Input
Output Analog)), (1, GPIO1(_2 => FSPICS0) (_2 => FSPICS0) (Input Output Analog)),
(2, GPIO2(_0 => MTMS _2 => FSPIWP) (_2 => FSPIWP) (Input Output Analog)), (3,
GPIO3(_0 => MTDI _2 => FSPIHD) (_2 => FSPIHD) (Input Output Analog)), (4,
GPIO4(_0 => MTCK _2 => FSPICLK) (_2 => FSPICLK) (Input Output Analog)), (5,
GPIO5(_2 => FSPID) (_0 => MTDO _2 => FSPID) (Input Output Analog)), (6, GPIO6()
() (Input Output)), (7, GPIO7() () (Input Output)), (8, GPIO8() () (Input
Output)), (9, GPIO9() () (Input Output)), (10, GPIO10() () (Input Output)), (11,
GPIO11() () (Input Output)), (12, GPIO12() () (Input Output)), (13, GPIO13() ()
(Input Output)), (14, GPIO14() () (Input Output)), (22, GPIO22() () (Input
Output)), (23, GPIO23(_0 => U0RXD) (_2 => FSPICS1) (Input Output)), (24, GPIO24()
(_0 => U0TXD _2 => FSPICS2) (Input Output)), (25, GPIO25() (_2 => FSPICS3) (Input
Output)), (26, GPIO26() (_2 => FSPICS4) (Input Output UsbDevice)), (27, GPIO27()
(_2 => FSPICS5) (Input Output UsbDevice))));
};
}
#[macro_export]
macro_rules! if_pin_is_type {
(GPIO0, Input, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO0, Output, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO0, Analog, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO0, $t:tt, $then_tt:tt else $else_tt:tt) => {
$else_tt
};
(GPIO1, Input, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO1, Output, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO1, Analog, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO1, $t:tt, $then_tt:tt else $else_tt:tt) => {
$else_tt
};
(GPIO2, Input, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO2, Output, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO2, Analog, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO2, $t:tt, $then_tt:tt else $else_tt:tt) => {
$else_tt
};
(GPIO3, Input, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO3, Output, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO3, Analog, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO3, $t:tt, $then_tt:tt else $else_tt:tt) => {
$else_tt
};
(GPIO4, Input, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO4, Output, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO4, Analog, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO4, $t:tt, $then_tt:tt else $else_tt:tt) => {
$else_tt
};
(GPIO5, Input, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO5, Output, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO5, Analog, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO5, $t:tt, $then_tt:tt else $else_tt:tt) => {
$else_tt
};
(GPIO6, Input, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO6, Output, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO6, $t:tt, $then_tt:tt else $else_tt:tt) => {
$else_tt
};
(GPIO7, Input, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO7, Output, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO7, $t:tt, $then_tt:tt else $else_tt:tt) => {
$else_tt
};
(GPIO8, Input, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO8, Output, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO8, $t:tt, $then_tt:tt else $else_tt:tt) => {
$else_tt
};
(GPIO9, Input, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO9, Output, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO9, $t:tt, $then_tt:tt else $else_tt:tt) => {
$else_tt
};
(GPIO10, Input, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO10, Output, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO10, $t:tt, $then_tt:tt else $else_tt:tt) => {
$else_tt
};
(GPIO11, Input, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO11, Output, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO11, $t:tt, $then_tt:tt else $else_tt:tt) => {
$else_tt
};
(GPIO12, Input, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO12, Output, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO12, $t:tt, $then_tt:tt else $else_tt:tt) => {
$else_tt
};
(GPIO13, Input, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO13, Output, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO13, $t:tt, $then_tt:tt else $else_tt:tt) => {
$else_tt
};
(GPIO14, Input, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO14, Output, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO14, $t:tt, $then_tt:tt else $else_tt:tt) => {
$else_tt
};
(GPIO22, Input, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO22, Output, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO22, $t:tt, $then_tt:tt else $else_tt:tt) => {
$else_tt
};
(GPIO23, Input, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO23, Output, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO23, $t:tt, $then_tt:tt else $else_tt:tt) => {
$else_tt
};
(GPIO24, Input, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO24, Output, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO24, $t:tt, $then_tt:tt else $else_tt:tt) => {
$else_tt
};
(GPIO25, Input, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO25, Output, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO25, $t:tt, $then_tt:tt else $else_tt:tt) => {
$else_tt
};
(GPIO26, Input, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO26, Output, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO26, UsbDevice, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO26, $t:tt, $then_tt:tt else $else_tt:tt) => {
$else_tt
};
(GPIO27, Input, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO27, Output, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO27, UsbDevice, $then_tt:tt else $else_tt:tt) => {
$then_tt
};
(GPIO27, $t:tt, $then_tt:tt else $else_tt:tt) => {
$else_tt
};
}
#[macro_export]
#[expect(clippy::crate_in_macro_def)]
macro_rules! impl_for_pin_type {
($any_pin:ident, $inner_ident:ident, $on_type:tt, $code:tt else $otherwise:tt) => {
match $any_pin .number() { 0 => if_pin_is_type!(GPIO0, $on_type, { {
#[allow(unused_unsafe, unused_mut)] let mut $inner_ident = unsafe { crate
::peripherals::GPIO0::steal() }; #[allow(unused_braces)] $code } } else {
$otherwise }), 1 => if_pin_is_type!(GPIO1, $on_type, { { #[allow(unused_unsafe,
unused_mut)] let mut $inner_ident = unsafe { crate ::peripherals::GPIO1::steal()
}; #[allow(unused_braces)] $code } } else { $otherwise }), 2 =>
if_pin_is_type!(GPIO2, $on_type, { { #[allow(unused_unsafe, unused_mut)] let mut
$inner_ident = unsafe { crate ::peripherals::GPIO2::steal() };
#[allow(unused_braces)] $code } } else { $otherwise }), 3 =>
if_pin_is_type!(GPIO3, $on_type, { { #[allow(unused_unsafe, unused_mut)] let mut
$inner_ident = unsafe { crate ::peripherals::GPIO3::steal() };
#[allow(unused_braces)] $code } } else { $otherwise }), 4 =>
if_pin_is_type!(GPIO4, $on_type, { { #[allow(unused_unsafe, unused_mut)] let mut
$inner_ident = unsafe { crate ::peripherals::GPIO4::steal() };
#[allow(unused_braces)] $code } } else { $otherwise }), 5 =>
if_pin_is_type!(GPIO5, $on_type, { { #[allow(unused_unsafe, unused_mut)] let mut
$inner_ident = unsafe { crate ::peripherals::GPIO5::steal() };
#[allow(unused_braces)] $code } } else { $otherwise }), 6 =>
if_pin_is_type!(GPIO6, $on_type, { { #[allow(unused_unsafe, unused_mut)] let mut
$inner_ident = unsafe { crate ::peripherals::GPIO6::steal() };
#[allow(unused_braces)] $code } } else { $otherwise }), 7 =>
if_pin_is_type!(GPIO7, $on_type, { { #[allow(unused_unsafe, unused_mut)] let mut
$inner_ident = unsafe { crate ::peripherals::GPIO7::steal() };
#[allow(unused_braces)] $code } } else { $otherwise }), 8 =>
if_pin_is_type!(GPIO8, $on_type, { { #[allow(unused_unsafe, unused_mut)] let mut
$inner_ident = unsafe { crate ::peripherals::GPIO8::steal() };
#[allow(unused_braces)] $code } } else { $otherwise }), 9 =>
if_pin_is_type!(GPIO9, $on_type, { { #[allow(unused_unsafe, unused_mut)] let mut
$inner_ident = unsafe { crate ::peripherals::GPIO9::steal() };
#[allow(unused_braces)] $code } } else { $otherwise }), 10 =>
if_pin_is_type!(GPIO10, $on_type, { { #[allow(unused_unsafe, unused_mut)] let mut
$inner_ident = unsafe { crate ::peripherals::GPIO10::steal() };
#[allow(unused_braces)] $code } } else { $otherwise }), 11 =>
if_pin_is_type!(GPIO11, $on_type, { { #[allow(unused_unsafe, unused_mut)] let mut
$inner_ident = unsafe { crate ::peripherals::GPIO11::steal() };
#[allow(unused_braces)] $code } } else { $otherwise }), 12 =>
if_pin_is_type!(GPIO12, $on_type, { { #[allow(unused_unsafe, unused_mut)] let mut
$inner_ident = unsafe { crate ::peripherals::GPIO12::steal() };
#[allow(unused_braces)] $code } } else { $otherwise }), 13 =>
if_pin_is_type!(GPIO13, $on_type, { { #[allow(unused_unsafe, unused_mut)] let mut
$inner_ident = unsafe { crate ::peripherals::GPIO13::steal() };
#[allow(unused_braces)] $code } } else { $otherwise }), 14 =>
if_pin_is_type!(GPIO14, $on_type, { { #[allow(unused_unsafe, unused_mut)] let mut
$inner_ident = unsafe { crate ::peripherals::GPIO14::steal() };
#[allow(unused_braces)] $code } } else { $otherwise }), 22 =>
if_pin_is_type!(GPIO22, $on_type, { { #[allow(unused_unsafe, unused_mut)] let mut
$inner_ident = unsafe { crate ::peripherals::GPIO22::steal() };
#[allow(unused_braces)] $code } } else { $otherwise }), 23 =>
if_pin_is_type!(GPIO23, $on_type, { { #[allow(unused_unsafe, unused_mut)] let mut
$inner_ident = unsafe { crate ::peripherals::GPIO23::steal() };
#[allow(unused_braces)] $code } } else { $otherwise }), 24 =>
if_pin_is_type!(GPIO24, $on_type, { { #[allow(unused_unsafe, unused_mut)] let mut
$inner_ident = unsafe { crate ::peripherals::GPIO24::steal() };
#[allow(unused_braces)] $code } } else { $otherwise }), 25 =>
if_pin_is_type!(GPIO25, $on_type, { { #[allow(unused_unsafe, unused_mut)] let mut
$inner_ident = unsafe { crate ::peripherals::GPIO25::steal() };
#[allow(unused_braces)] $code } } else { $otherwise }), 26 =>
if_pin_is_type!(GPIO26, $on_type, { { #[allow(unused_unsafe, unused_mut)] let mut
$inner_ident = unsafe { crate ::peripherals::GPIO26::steal() };
#[allow(unused_braces)] $code } } else { $otherwise }), 27 =>
if_pin_is_type!(GPIO27, $on_type, { { #[allow(unused_unsafe, unused_mut)] let mut
$inner_ident = unsafe { crate ::peripherals::GPIO27::steal() };
#[allow(unused_braces)] $code } } else { $otherwise }), _ => $otherwise, }
};
($any_pin:ident, $inner_ident:ident, $on_type:tt, $code:tt) => {
impl_for_pin_type!($any_pin, $inner_ident, $on_type, $code else {
panic!("Unsupported") })
};
}
#[macro_export]
macro_rules! define_io_mux_signals {
() => {
#[allow(non_camel_case_types, clippy::upper_case_acronyms)]
#[derive(Debug, PartialEq, Copy, Clone)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[doc(hidden)]
pub enum InputSignal {
EXT_ADC_START = 0,
U0RXD = 6,
U0CTS = 7,
U0DSR = 8,
U1RXD = 9,
U1CTS = 10,
U1DSR = 11,
I2S_MCLK = 12,
I2SO_BCK = 13,
I2SO_WS = 14,
I2SI_SD = 15,
I2SI_BCK = 16,
I2SI_WS = 17,
USB_JTAG_TDO_BRIDGE = 19,
CPU_GPIO0 = 28,
CPU_GPIO1 = 29,
CPU_GPIO2 = 30,
CPU_GPIO3 = 31,
CPU_GPIO4 = 32,
CPU_GPIO5 = 33,
CPU_GPIO6 = 34,
CPU_GPIO7 = 35,
I2CEXT0_SCL = 45,
I2CEXT0_SDA = 46,
PARL_RX_DATA0 = 47,
PARL_RX_DATA1 = 48,
PARL_RX_DATA2 = 49,
PARL_RX_DATA3 = 50,
PARL_RX_DATA4 = 51,
PARL_RX_DATA5 = 52,
PARL_RX_DATA6 = 53,
PARL_RX_DATA7 = 54,
I2CEXT1_SCL = 55,
I2CEXT1_SDA = 56,
FSPICLK = 63,
FSPIQ = 64,
FSPID = 65,
FSPIHD = 66,
FSPIWP = 67,
FSPICS0 = 68,
PARL_RX_CLK = 69,
PARL_TX_CLK = 70,
RMT_SIG_0 = 71,
RMT_SIG_1 = 72,
TWAI0_RX = 73,
PWM0_SYNC0 = 87,
PWM0_SYNC1 = 88,
PWM0_SYNC2 = 89,
PWM0_F0 = 90,
PWM0_F1 = 91,
PWM0_F2 = 92,
PWM0_CAP0 = 93,
PWM0_CAP1 = 94,
PWM0_CAP2 = 95,
SIG_FUNC_97 = 97,
SIG_FUNC_98 = 98,
SIG_FUNC_99 = 99,
SIG_FUNC_100 = 100,
PCNT0_SIG_CH0 = 101,
PCNT0_SIG_CH1 = 102,
PCNT0_CTRL_CH0 = 103,
PCNT0_CTRL_CH1 = 104,
PCNT1_SIG_CH0 = 105,
PCNT1_SIG_CH1 = 106,
PCNT1_CTRL_CH0 = 107,
PCNT1_CTRL_CH1 = 108,
PCNT2_SIG_CH0 = 109,
PCNT2_SIG_CH1 = 110,
PCNT2_CTRL_CH0 = 111,
PCNT2_CTRL_CH1 = 112,
PCNT3_SIG_CH0 = 113,
PCNT3_SIG_CH1 = 114,
PCNT3_CTRL_CH0 = 115,
PCNT3_CTRL_CH1 = 116,
SPIQ = 121,
SPID = 122,
SPIHD = 123,
SPIWP = 124,
MTDI,
MTCK,
MTMS,
}
#[allow(non_camel_case_types, clippy::upper_case_acronyms)]
#[derive(Debug, PartialEq, Copy, Clone)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[doc(hidden)]
pub enum OutputSignal {
LEDC_LS_SIG0 = 0,
LEDC_LS_SIG1 = 1,
LEDC_LS_SIG2 = 2,
LEDC_LS_SIG3 = 3,
LEDC_LS_SIG4 = 4,
LEDC_LS_SIG5 = 5,
U0TXD = 6,
U0RTS = 7,
U0DTR = 8,
U1TXD = 9,
U1RTS = 10,
U1DTR = 11,
I2S_MCLK = 12,
I2SO_BCK = 13,
I2SO_WS = 14,
I2SO_SD = 15,
I2SI_BCK = 16,
I2SI_WS = 17,
I2SO_SD1 = 18,
USB_JTAG_TRST = 19,
CPU_GPIO_OUT0 = 28,
CPU_GPIO_OUT1 = 29,
CPU_GPIO_OUT2 = 30,
CPU_GPIO_OUT3 = 31,
CPU_GPIO_OUT4 = 32,
CPU_GPIO_OUT5 = 33,
CPU_GPIO_OUT6 = 34,
CPU_GPIO_OUT7 = 35,
I2CEXT0_SCL = 45,
I2CEXT0_SDA = 46,
PARL_TX_DATA0 = 47,
PARL_TX_DATA1 = 48,
PARL_TX_DATA2 = 49,
PARL_TX_DATA3 = 50,
PARL_TX_DATA4 = 51,
PARL_TX_DATA5 = 52,
PARL_TX_DATA6 = 53,
PARL_TX_DATA7 = 54,
I2CEXT1_SCL = 55,
I2CEXT1_SDA = 56,
FSPICLK = 63,
FSPIQ = 64,
FSPID = 65,
FSPIHD = 66,
FSPIWP = 67,
FSPICS0 = 68,
PARL_RX_CLK = 69,
PARL_TX_CLK = 70,
RMT_SIG_0 = 71,
RMT_SIG_1 = 72,
TWAI0_TX = 73,
TWAI0_BUS_OFF_ON = 74,
TWAI0_CLKOUT = 75,
TWAI0_STANDBY = 76,
CTE_ANT7 = 78,
CTE_ANT8 = 79,
CTE_ANT9 = 80,
GPIO_SD0 = 83,
GPIO_SD1 = 84,
GPIO_SD2 = 85,
GPIO_SD3 = 86,
PWM0_0A = 87,
PWM0_0B = 88,
PWM0_1A = 89,
PWM0_1B = 90,
PWM0_2A = 91,
PWM0_2B = 92,
SIG_IN_FUNC97 = 97,
SIG_IN_FUNC98 = 98,
SIG_IN_FUNC99 = 99,
SIG_IN_FUNC100 = 100,
FSPICS1 = 101,
FSPICS2 = 102,
FSPICS3 = 103,
FSPICS4 = 104,
FSPICS5 = 105,
CTE_ANT10 = 106,
CTE_ANT11 = 107,
CTE_ANT12 = 108,
CTE_ANT13 = 109,
CTE_ANT14 = 110,
CTE_ANT15 = 111,
SPICLK = 114,
SPICS0 = 115,
SPICS1 = 116,
SPIQ = 121,
SPID = 122,
SPIHD = 123,
SPIWP = 124,
CLK_OUT_OUT1 = 125,
CLK_OUT_OUT2 = 126,
CLK_OUT_OUT3 = 127,
GPIO = 128,
MTDO,
}
};
}
#[macro_export]
#[expect(clippy::crate_in_macro_def)]
macro_rules! define_io_mux_reg {
() => {
pub(crate) fn io_mux_reg(gpio_num: u8) -> &'static crate::pac::io_mux::GPIO {
crate::peripherals::IO_MUX::regs().gpio(gpio_num as usize)
}
};
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,17 @@
#![cfg_attr(not(feature = "build-script"), no_std)]
#[cfg(all(not(feature = "build-script"), feature = "esp32"))]
include!("_generated_esp32.rs");
#[cfg(all(not(feature = "build-script"), feature = "esp32c2"))]
include!("_generated_esp32c2.rs");
#[cfg(all(not(feature = "build-script"), feature = "esp32c3"))]
include!("_generated_esp32c3.rs");
#[cfg(all(not(feature = "build-script"), feature = "esp32c6"))]
include!("_generated_esp32c6.rs");
#[cfg(all(not(feature = "build-script"), feature = "esp32h2"))]
include!("_generated_esp32h2.rs");
#[cfg(all(not(feature = "build-script"), feature = "esp32s2"))]
include!("_generated_esp32s2.rs");
#[cfg(all(not(feature = "build-script"), feature = "esp32s3"))]
include!("_generated_esp32s3.rs");
#[cfg(feature = "build-script")]
include!("_build_script_utils.rs");

View File

@ -14,12 +14,9 @@ clap = { version = "4.5.37", features = ["derive"], optional = true }
basic-toml = { version = "0.1.10" }
serde = { version = "1.0.219", default-features = false, features = ["derive"] }
strum = { version = "0.27.1", features = ["derive"] }
syn = { version = "2", default-features = false, features = ["full", "parsing"], optional = true }
proc-macro2 = { version = "1.0.36" }
quote = { version = "1.0.15" }
prettyplease = { version = "0.2.34", optional = true }
[features]
default = []
clap = ["dep:clap"]
pretty = ["dep:prettyplease", "dep:syn"]

View File

@ -6,10 +6,11 @@
# update the table in the esp-hal README.
[device]
name = "esp32"
arch = "xtensa"
cores = 2
trm = "https://www.espressif.com/sites/default/files/documentation/esp32_technical_reference_manual_en.pdf"
name = "esp32"
arch = "xtensa"
target = "xtensa-esp32-none-elf"
cores = 2
trm = "https://www.espressif.com/sites/default/files/documentation/esp32_technical_reference_manual_en.pdf"
peripherals = [
{ name = "AES" },

View File

@ -6,10 +6,11 @@
# update the table in the esp-hal README.
[device]
name = "esp32c2"
arch = "riscv"
cores = 1
trm = "https://www.espressif.com/sites/default/files/documentation/esp8684_technical_reference_manual_en.pdf"
name = "esp32c2"
arch = "riscv"
target = "riscv32imc-unknown-none-elf"
cores = 1
trm = "https://www.espressif.com/sites/default/files/documentation/esp8684_technical_reference_manual_en.pdf"
peripherals = [
{ name = "APB_CTRL" },

View File

@ -6,10 +6,11 @@
# update the table in the esp-hal README.
[device]
name = "esp32c3"
arch = "riscv"
cores = 1
trm = "https://www.espressif.com/sites/default/files/documentation/esp32-c3_technical_reference_manual_en.pdf"
name = "esp32c3"
arch = "riscv"
target = "riscv32imc-unknown-none-elf"
cores = 1
trm = "https://www.espressif.com/sites/default/files/documentation/esp32-c3_technical_reference_manual_en.pdf"
peripherals = [
{ name = "AES" },

View File

@ -6,10 +6,11 @@
# update the table in the esp-hal README.
[device]
name = "esp32c6"
arch = "riscv"
cores = 1
trm = "https://www.espressif.com/sites/default/files/documentation/esp32-c6_technical_reference_manual_en.pdf"
name = "esp32c6"
arch = "riscv"
target = "riscv32imac-unknown-none-elf"
cores = 1
trm = "https://www.espressif.com/sites/default/files/documentation/esp32-c6_technical_reference_manual_en.pdf"
peripherals = [
{ name = "AES" },

View File

@ -6,10 +6,11 @@
# update the table in the esp-hal README.
[device]
name = "esp32h2"
arch = "riscv"
cores = 1
trm = "https://www.espressif.com/sites/default/files/documentation/esp32-h2_technical_reference_manual_en.pdf"
name = "esp32h2"
arch = "riscv"
target = "riscv32imac-unknown-none-elf"
cores = 1
trm = "https://www.espressif.com/sites/default/files/documentation/esp32-h2_technical_reference_manual_en.pdf"
peripherals = [
{ name = "AES" },

View File

@ -6,10 +6,11 @@
# update the table in the esp-hal README.
[device]
name = "esp32s2"
arch = "xtensa"
cores = 1
trm = "https://www.espressif.com/sites/default/files/documentation/esp32-s2_technical_reference_manual_en.pdf"
name = "esp32s2"
arch = "xtensa"
target = "xtensa-esp32s2-none-elf"
cores = 1
trm = "https://www.espressif.com/sites/default/files/documentation/esp32-s2_technical_reference_manual_en.pdf"
peripherals = [
{ name = "AES" },

View File

@ -6,10 +6,11 @@
# update the table in the esp-hal README.
[device]
name = "esp32s3"
arch = "xtensa"
cores = 2
trm = "https://www.espressif.com/sites/default/files/documentation/esp32-s3_technical_reference_manual_en.pdf"
name = "esp32s3"
arch = "xtensa"
target = "xtensa-esp32s3-none-elf"
cores = 2
trm = "https://www.espressif.com/sites/default/files/documentation/esp32-s3_technical_reference_manual_en.pdf"
peripherals = [
{ name = "AES" },

View File

@ -263,11 +263,10 @@ pub(crate) fn generate_gpios(gpio: &super::GpioProperties) -> TokenStream {
}
quote::quote! {
#[macro_export]
macro_rules! if_pin_is_type {
#(#branches)*
}
pub(crate) use if_pin_is_type;
}
};
@ -280,9 +279,9 @@ pub(crate) fn generate_gpios(gpio: &super::GpioProperties) -> TokenStream {
let mut impl_branches = vec![];
for (gpionum, peri) in pin_numbers.iter().zip(pin_peris.iter()) {
impl_branches.push(quote::quote! {
#gpionum => $crate::peripherals::if_pin_is_type!(#peri, $on_type, {{
#gpionum => if_pin_is_type!(#peri, $on_type, {{
#[allow(unused_unsafe, unused_mut)]
let mut $inner_ident = unsafe { $crate::peripherals::#peri::steal() };
let mut $inner_ident = unsafe { crate::peripherals::#peri::steal() };
#[allow(unused_braces)]
$code
}} else {
@ -292,6 +291,8 @@ pub(crate) fn generate_gpios(gpio: &super::GpioProperties) -> TokenStream {
}
quote::quote! {
#[macro_export]
#[expect(clippy::crate_in_macro_def)]
macro_rules! impl_for_pin_type {
($any_pin:ident, $inner_ident:ident, $on_type:tt, $code:tt else $otherwise:tt) => {
match $any_pin.number() {
@ -303,7 +304,6 @@ pub(crate) fn generate_gpios(gpio: &super::GpioProperties) -> TokenStream {
impl_for_pin_type!($any_pin, $inner_ident, $on_type, $code else { panic!("Unsupported") })
};
}
pub(crate) use impl_for_pin_type;
}
};
@ -320,6 +320,8 @@ pub(crate) fn generate_gpios(gpio: &super::GpioProperties) -> TokenStream {
}
let for_each = generate_for_each_macro("gpio", &branches);
let input_signals = render_signals("InputSignal", &gpio.pins_and_signals.input_signals);
let output_signals = render_signals("OutputSignal", &gpio.pins_and_signals.output_signals);
quote::quote! {
#for_each
@ -327,6 +329,16 @@ pub(crate) fn generate_gpios(gpio: &super::GpioProperties) -> TokenStream {
#if_pin_is_type
#impl_for_pin_type
#[macro_export]
macro_rules! define_io_mux_signals {
() => {
#input_signals
#output_signals
};
}
#[macro_export]
#[expect(clippy::crate_in_macro_def)]
macro_rules! define_io_mux_reg {
() => {
#io_mux_accessor
@ -335,16 +347,6 @@ pub(crate) fn generate_gpios(gpio: &super::GpioProperties) -> TokenStream {
}
}
pub(crate) fn generate_iomux_signals(gpio: &super::GpioProperties) -> TokenStream {
let input_signals = render_signals("InputSignal", &gpio.pins_and_signals.input_signals);
let output_signals = render_signals("OutputSignal", &gpio.pins_and_signals.output_signals);
quote::quote! {
#input_signals
#output_signals
}
}
fn render_signals(enum_name: &str, signals: &[IoMuxSignal]) -> TokenStream {
if signals.is_empty() {
// If there are no signals, we don't need to generate an enum.

View File

@ -2,12 +2,12 @@
mod cfg;
use core::str::FromStr;
use std::{collections::HashMap, fmt::Write, path::Path, sync::OnceLock};
use std::{collections::HashMap, fmt::Write, sync::OnceLock};
use anyhow::{Result, bail, ensure};
use cfg::PeriConfig;
use proc_macro2::TokenStream;
use quote::format_ident;
pub use proc_macro2::TokenStream;
use quote::{format_ident, quote};
use strum::IntoEnumIterator;
use crate::cfg::{SupportItem, SupportStatus, Value};
@ -141,16 +141,8 @@ impl Chip {
Ok(Self::from_str(chip.as_str()).unwrap())
}
pub fn target(&self) -> &'static str {
use Chip::*;
match self {
Esp32 => "xtensa-esp32-none-elf",
Esp32c2 | Esp32c3 => "riscv32imc-unknown-none-elf",
Esp32c6 | Esp32h2 => "riscv32imac-unknown-none-elf",
Esp32s2 => "xtensa-esp32s2-none-elf",
Esp32s3 => "xtensa-esp32s3-none-elf",
}
pub fn target(&self) -> String {
Config::for_chip(self).device.target.clone()
}
pub fn has_lp_core(&self) -> bool {
@ -160,12 +152,22 @@ impl Chip {
}
pub fn lp_target(&self) -> Result<&'static str> {
use Chip::*;
match self {
Esp32c6 => Ok("riscv32imac-unknown-none-elf"),
Esp32s2 | Esp32s3 => Ok("riscv32imc-unknown-none-elf"),
_ => bail!("Chip does not contain an LP core: '{}'", self),
Chip::Esp32c6 => Ok("riscv32imac-unknown-none-elf"),
Chip::Esp32s2 | Chip::Esp32s3 => Ok("riscv32imc-unknown-none-elf"),
_ => bail!("Chip does not contain an LP core: '{self}'"),
}
}
pub fn name(&self) -> &str {
match self {
Chip::Esp32 => "Esp32",
Chip::Esp32c2 => "Esp32c2",
Chip::Esp32c3 => "Esp32c3",
Chip::Esp32c6 => "Esp32c6",
Chip::Esp32h2 => "Esp32h2",
Chip::Esp32s2 => "Esp32s2",
Chip::Esp32s3 => "Esp32s3",
}
}
@ -188,6 +190,48 @@ impl Chip {
pub fn is_riscv(&self) -> bool {
!self.is_xtensa()
}
pub fn list_of_check_cfgs() -> Vec<String> {
let mut cfgs = vec![];
// Used by our documentation builds to prevent the huge red warning banner.
cfgs.push(String::from("cargo:rustc-check-cfg=cfg(not_really_docsrs)"));
let mut cfg_values: HashMap<String, Vec<String>> = HashMap::new();
for chip in Chip::iter() {
let config = Config::for_chip(&chip);
for symbol in config.all() {
if let Some((symbol_name, symbol_value)) = symbol.split_once('=') {
// cfg's with values need special syntax, so let's collect all
// of them separately.
let symbol_name = symbol_name.replace('.', "_");
let entry = cfg_values.entry(symbol_name).or_default();
// Avoid duplicates in the same cfg.
if !entry.contains(&symbol_value.to_string()) {
entry.push(symbol_value.to_string());
}
} else {
// https://doc.rust-lang.org/cargo/reference/build-scripts.html#rustc-check-cfg
let cfg = format!("cargo:rustc-check-cfg=cfg({})", symbol.replace('.', "_"));
if !cfgs.contains(&cfg) {
cfgs.push(cfg);
}
}
}
}
// Now output all cfgs with values.
for (symbol_name, symbol_values) in cfg_values {
cfgs.push(format!(
"cargo:rustc-check-cfg=cfg({symbol_name}, values({}))",
symbol_values.join(",")
));
}
cfgs
}
}
#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
@ -222,6 +266,7 @@ impl PeripheralDef {
struct Device {
name: String,
arch: Arch,
target: String,
cores: usize,
trm: String,
@ -266,10 +311,11 @@ impl Config {
pub fn empty() -> Self {
Self {
device: Device {
name: "".to_owned(),
name: String::new(),
arch: Arch::RiscV,
target: String::new(),
cores: 1,
trm: "".to_owned(),
trm: String::new(),
peripherals: Vec::new(),
symbols: Vec::new(),
memory: Vec::new(),
@ -369,36 +415,24 @@ impl Config {
self.all().iter().any(|i| i == item)
}
/// Define all symbols for a given configuration.
pub fn define_symbols(&self) {
define_all_possible_symbols();
// Define all necessary configuration symbols for the configured device:
for symbol in self.all() {
println!("cargo:rustc-cfg={}", symbol.replace('.', "_"));
}
pub fn generate_metadata(&self) -> TokenStream {
let properties = self.generate_properties();
let peris = self.generate_peripherals();
let gpios = self.generate_gpios();
// Define env-vars for all memory regions
for memory in self.memory() {
println!("cargo:rustc-cfg=has_{}_region", memory.name.to_lowercase());
quote! {
#properties
#peris
#gpios
}
}
pub fn generate_metadata(&self) {
let out_dir = std::env::var_os("OUT_DIR").unwrap();
let out_dir = Path::new(&out_dir);
self.generate_properties(out_dir, "_generated.rs");
self.generate_gpios(out_dir, "_generated_gpio.rs");
self.generate_iomux_signals(out_dir, "_generated_iomux_signals.rs");
self.generate_peripherals(out_dir, "_generated_peris.rs");
}
fn generate_properties(&self, out_dir: &Path, file_name: &str) {
let mut g = TokenStream::new();
fn generate_properties(&self) -> TokenStream {
let mut tokens = TokenStream::new();
let chip_name = self.name();
// Public API, can't use a private macro:
g.extend(quote::quote! {
tokens.extend(quote! {
/// The name of the chip as `&str`
#[macro_export]
macro_rules! chip {
@ -416,23 +450,22 @@ impl Config {
.peri_config
.properties()
.flat_map(|(name, value)| match value {
Value::Unset => quote::quote! {},
Value::Unset => quote! {},
Value::Number(value) => {
let value = number(value); // ensure no numeric suffix is added
quote::quote! {
quote! {
(#name) => { #value };
(#name, str) => { stringify!(#value) };
}
}
Value::Boolean(value) => quote::quote! {
Value::Boolean(value) => quote! {
(#name) => { #value };
},
});
// Not public API, can use a private macro:
g.extend(quote::quote! {
/// A link to the Technical Reference Manual (TRM) for the chip.
#[doc(hidden)]
tokens.extend(quote! {
/// The properties of this chip and its drivers.
#[macro_export]
macro_rules! property {
("chip") => { #chip_name };
@ -449,48 +482,34 @@ impl Config {
let start = number(region.start as usize);
let end = number(region.end as usize);
quote::quote! {
quote! {
( #name ) => {
#start .. #end
};
}
});
g.extend(quote::quote! {
tokens.extend(quote! {
/// Macro to get the address range of the given memory region.
#[macro_export]
#[doc(hidden)]
macro_rules! memory_range {
#(#region_branches)*
}
});
save(out_dir.join(file_name), g);
tokens
}
fn generate_gpios(&self, out_dir: &Path, file_name: &str) {
fn generate_gpios(&self) -> TokenStream {
let Some(gpio) = self.device.peri_config.gpio.as_ref() else {
// No GPIOs defined, nothing to do.
return;
return quote! {};
};
let tokens = cfg::generate_gpios(gpio);
save(out_dir.join(file_name), tokens);
cfg::generate_gpios(gpio)
}
fn generate_iomux_signals(&self, out_dir: &Path, file_name: &str) {
let Some(gpio) = self.device.peri_config.gpio.as_ref() else {
// No GPIOs defined, nothing to do.
return;
};
let tokens = cfg::generate_iomux_signals(gpio);
save(out_dir.join(file_name), tokens);
}
fn generate_peripherals(&self, out_dir: &Path, file_name: &str) {
fn generate_peripherals(&self) -> TokenStream {
let mut tokens = TokenStream::new();
// TODO: repeat for all drivers that have Instance traits
@ -509,7 +528,7 @@ impl Config {
tokens.extend(self.generate_peripherals_macro());
save(out_dir.join(file_name), tokens);
tokens
}
fn generate_peripherals_macro(&self) -> TokenStream {
@ -534,10 +553,10 @@ impl Config {
if let Some(gpio) = self.device.peri_config.gpio.as_ref() {
for pin in gpio.pins_and_signals.pins.iter() {
let pin = format_ident!("GPIO{}", pin.pin);
let tokens = quote::quote! {
let tokens = quote! {
#pin <= virtual ()
};
all_peripherals.push(quote::quote! { #tokens });
all_peripherals.push(quote! { #tokens });
stable.push(tokens);
}
}
@ -557,33 +576,57 @@ impl Config {
let bind = format_ident!("bind_{k}_interrupt");
let enable = format_ident!("enable_{k}_interrupt");
let disable = format_ident!("disable_{k}_interrupt");
quote::quote! { #pac_interrupt_name: { #bind, #enable, #disable } }
quote! { #pac_interrupt_name: { #bind, #enable, #disable } }
});
let tokens = quote::quote! {
let tokens = quote! {
#hal <= #pac ( #(#interrupts),* )
};
if stable_peris
.iter()
.any(|p| peri.name.eq_ignore_ascii_case(p))
{
all_peripherals.push(quote::quote! { #tokens });
all_peripherals.push(quote! { #tokens });
stable.push(tokens);
} else {
all_peripherals.push(quote::quote! { #tokens (unstable) });
all_peripherals.push(quote! { #tokens (unstable) });
unstable.push(tokens);
}
}
generate_for_each_macro("peripheral", &all_peripherals)
}
pub fn active_cfgs(&self) -> Vec<String> {
let mut cfgs = vec![];
// Define all necessary configuration symbols for the configured device:
for symbol in self.all() {
cfgs.push(symbol.replace('.', "_"));
}
// Define env-vars for all memory regions
for memory in self.memory() {
cfgs.push(format!("has_{}_region", memory.name.to_lowercase()));
}
cfgs
}
pub fn list_of_cfgs(&self) -> Vec<String> {
self.active_cfgs()
.iter()
.map(|cfg| format!("cargo:rustc-cfg={cfg}"))
.collect()
}
}
fn generate_for_each_macro(name: &str, branches: &[TokenStream]) -> TokenStream {
let macro_name = format_ident!("for_each_{name}");
quote::quote! {
quote! {
// This macro is called in esp-hal to implement a driver's
// Instance trait for available peripherals. It works by defining, then calling an inner
// macro that substitutes the properties into the template provided by the call in esp-hal.
#[macro_export]
macro_rules! #macro_name {
(
$($pattern:tt => $code:tt;)*
@ -616,57 +659,162 @@ fn generate_for_each_macro(name: &str, branches: &[TokenStream]) -> TokenStream
_for_each_inner!((all #((#branches)),*));
};
}
pub(crate) use #macro_name;
}
}
fn save(path: impl AsRef<Path>, tokens: TokenStream) {
let source = tokens.to_string();
pub fn generate_build_script_utils() -> TokenStream {
let check_cfgs = Chip::list_of_check_cfgs();
#[cfg(feature = "pretty")]
let syntax_tree = syn::parse_file(&source).unwrap();
#[cfg(feature = "pretty")]
let source = prettyplease::unparse(&syntax_tree);
std::fs::write(path, source).unwrap();
}
/// Defines all possible symbols that _could_ be output from this crate
/// regardless of the chosen configuration.
///
/// This is required to avoid triggering the unexpected-cfgs lint.
fn define_all_possible_symbols() {
// Used by our documentation builds to prevent the huge red warning banner.
println!("cargo:rustc-check-cfg=cfg(not_really_docsrs)");
let mut cfg_values: HashMap<String, Vec<String>> = HashMap::new();
for chip in Chip::iter() {
let chip = Chip::iter()
.map(|c| format_ident!("{}", c.name()))
.collect::<Vec<_>>();
let feature_env = Chip::iter().map(|c| format!("CARGO_FEATURE_{}", c.as_ref().to_uppercase()));
let name = Chip::iter()
.map(|c| c.as_ref().to_string())
.collect::<Vec<_>>();
let all_chip_features = name.join(", ");
let config = Chip::iter().map(|chip| {
let config = Config::for_chip(&chip);
for symbol in config.all() {
if let Some((symbol_name, symbol_value)) = symbol.split_once('=') {
// cfg's with values need special syntax, so let's collect all
// of them separately.
let symbol_name = symbol_name.replace('.', "_");
let entry = cfg_values.entry(symbol_name).or_default();
// Avoid duplicates in the same cfg.
if !entry.contains(&symbol_value.to_string()) {
entry.push(symbol_value.to_string());
let symbols = config.active_cfgs();
let arch = config.device.arch.to_string();
let target = config.device.target.as_str();
let cfgs = config.list_of_cfgs();
quote! {
Config {
architecture: #arch,
target: #target,
symbols: &[
#(#symbols,)*
],
cfgs: &[
#(#cfgs,)*
],
}
}
});
let bail_message = format!(
"Expected exactly one of the following features to be enabled: {all_chip_features}"
);
quote! {
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
pub enum Chip {
#(#chip),*
}
impl core::str::FromStr for Chip {
type Err = ();
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
#( #name => Ok(Self::#chip),)*
_ => Err(()),
}
}
}
impl Chip {
pub fn from_cargo_feature() -> Result<Self, Box<dyn std::error::Error>> {
let all_chips = [
#(( #feature_env, Self::#chip )),*
];
let mut chip = None;
for (env, c) in all_chips {
if std::env::var(env).is_ok() {
if chip.is_some() {
return Err(#bail_message.into());
}
chip = Some(c);
}
}
match chip {
Some(chip) => Ok(chip),
None => Err(#bail_message.into())
}
}
pub fn is_xtensa(self) -> bool {
self.config().architecture == "xtensa"
}
pub fn target(self) -> &'static str {
self.config().target
}
pub fn name(self) -> &'static str {
match self {
#( Self::#chip => #name ),*
}
}
pub fn contains(self, symbol: &str) -> bool {
self.config().contains(symbol)
}
pub fn define_cfgs(self) {
self.config().define_cfgs()
}
pub fn all_symbols(&self) -> &'static [&'static str] {
self.config().symbols
}
pub fn iter() -> impl Iterator<Item = Chip> {
[
#( Self::#chip ),*
].into_iter()
}
pub fn config(self) -> Config {
match self {
#(Self::#chip => #config),*
}
}
}
pub struct Config {
architecture: &'static str,
target: &'static str,
symbols: &'static [&'static str],
cfgs: &'static [&'static str],
}
impl Config {
fn contains(&self, symbol: &str) -> bool {
self.symbols.contains(&symbol)
}
fn define_cfgs(&self) {
#(println!(#check_cfgs);)*
for cfg in self.cfgs {
println!("{cfg}");
}
} else {
// https://doc.rust-lang.org/cargo/reference/build-scripts.html#rustc-check-cfg
println!("cargo:rustc-check-cfg=cfg({})", symbol.replace('.', "_"));
}
}
}
}
// Now output all cfgs with values.
for (symbol_name, symbol_values) in cfg_values {
println!(
"cargo:rustc-check-cfg=cfg({symbol_name}, values({}))",
symbol_values.join(",")
);
pub fn generate_lib_rs() -> TokenStream {
let chips = Chip::iter().map(|c| {
let feature = format!("{c}");
let file = format!("_generated_{c}.rs");
quote! {
#[cfg(all(not(feature = "build-script"), feature = #feature))]
include!(#file);
}
});
quote! {
#![cfg_attr(not(feature = "build-script"), no_std)]
#(#chips)*
#[cfg(feature = "build-script")]
include!( "_build_script_utils.rs");
}
}

View File

@ -19,6 +19,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Removed
- Removed support for ESP32-P4 (#3754)
## [v0.14.0] - 2025-06-03

View File

@ -32,20 +32,19 @@ defmt = { version = "1.0.1", optional = true }
log-04 = { package = "log", version = "0.4.27", optional = true }
[build-dependencies]
esp-metadata = { version = "0.7.0", path = "../esp-metadata" }
esp-metadata-generated = { version = "0.0.1", path = "../esp-metadata-generated", features = ["build-script"] }
log-04 = { package = "log", version = "0.4.27" }
[features]
default = ["auto", "colors", "critical-section"]
esp32 = []
esp32c2 = []
esp32c3 = []
esp32c6 = []
esp32h2 = []
esp32p4 = []
esp32s2 = []
esp32s3 = []
esp32 = ["esp-metadata-generated/esp32"]
esp32c2 = ["esp-metadata-generated/esp32c2"]
esp32c3 = ["esp-metadata-generated/esp32c3"]
esp32c6 = ["esp-metadata-generated/esp32c6"]
esp32h2 = ["esp-metadata-generated/esp32h2"]
esp32s2 = ["esp-metadata-generated/esp32s2"]
esp32s3 = ["esp-metadata-generated/esp32s3"]
## Use a critical section around print calls. This ensures that the output is consistent.
critical-section = ["dep:critical-section"]

View File

@ -1,6 +1,5 @@
use std::{env, path::Path};
use esp_metadata::Chip;
use log_04::LevelFilter;
#[macro_export]
@ -14,27 +13,14 @@ macro_rules! assert_unique_used_features {
};
}
fn main() {
// Ensure that only a single chip is specified
let chip = if cfg!(feature = "esp32p4") {
None
} else {
Some(Chip::from_cargo_feature().unwrap())
};
fn main() -> Result<(), Box<dyn std::error::Error>> {
// Ensure that only a single communication method is specified
assert_unique_used_features!("jtag-serial", "uart", "auto");
let chip = esp_metadata_generated::Chip::from_cargo_feature()?;
// Ensure that, if the `jtag-serial` communication method feature is enabled,
// a compatible chip feature is also enabled.
// TODO: replace with Config once the P4 is supported by esp-hal (we're using
// Config::for_chip to reject P4 currently)
let has_jtag_serial = cfg!(feature = "esp32p4")
|| matches!(
chip,
Some(Chip::Esp32c3 | Chip::Esp32c6 | Chip::Esp32h2 | Chip::Esp32s3)
);
let has_jtag_serial = chip.contains("soc_has_usb_device");
if cfg!(feature = "jtag-serial") && !has_jtag_serial {
panic!(
@ -62,6 +48,8 @@ fn main() {
println!("cargo:rerun-if-env-changed=ESP_LOG");
println!("cargo:rustc-check-cfg=cfg(host_is_windows)");
Ok(())
}
fn generate_filter_snippet() {

View File

@ -135,7 +135,6 @@ type PrinterImpl = auto_printer::Printer;
feature = "esp32c3",
feature = "esp32c6",
feature = "esp32h2",
feature = "esp32p4", // as mentioned in 'build.rs'
feature = "esp32s3"
)
))]
@ -161,8 +160,6 @@ mod auto_printer {
const USB_DEVICE_INT_RAW: *const u32 = 0x6000f008 as *const u32;
#[cfg(feature = "esp32h2")]
const USB_DEVICE_INT_RAW: *const u32 = 0x6000f008 as *const u32;
#[cfg(feature = "esp32p4")]
const USB_DEVICE_INT_RAW: *const u32 = unimplemented!();
#[cfg(feature = "esp32s3")]
const USB_DEVICE_INT_RAW: *const u32 = 0x60038000 as *const u32;
@ -195,7 +192,6 @@ mod auto_printer {
feature = "esp32c3",
feature = "esp32c6",
feature = "esp32h2",
feature = "esp32p4",
feature = "esp32s3"
))
))]
@ -210,7 +206,6 @@ mod auto_printer {
feature = "esp32c3",
feature = "esp32c6",
feature = "esp32h2",
feature = "esp32p4",
feature = "esp32s3"
)
))]
@ -230,11 +225,6 @@ mod serial_jtag_printer {
#[cfg(any(feature = "esp32c6", feature = "esp32h2"))]
const SERIAL_JTAG_CONF_REG: usize = 0x6000_F004;
#[cfg(feature = "esp32p4")]
const SERIAL_JTAG_FIFO_REG: usize = 0x500D_2000;
#[cfg(feature = "esp32p4")]
const SERIAL_JTAG_CONF_REG: usize = 0x500D_2004;
#[cfg(feature = "esp32s3")]
const SERIAL_JTAG_FIFO_REG: usize = 0x6003_8000;
#[cfg(feature = "esp32s3")]
@ -463,23 +453,6 @@ mod uart_printer {
}
}
#[cfg(feature = "esp32p4")]
impl Functions for Device {
const TX_ONE_CHAR: usize = 0x4FC0_0054;
fn flush() {
unsafe {
const TX_FLUSH: usize = 0x4FC0_0074;
const GET_CHANNEL: usize = 0x4FC0_0038;
let tx_flush: unsafe extern "C" fn(u8) = core::mem::transmute(TX_FLUSH);
let get_channel: unsafe extern "C" fn() -> u8 = core::mem::transmute(GET_CHANNEL);
tx_flush(get_channel());
}
}
}
pub struct Printer;
impl Printer {
pub fn write_bytes_in_cs(bytes: &[u8], _token: LockToken<'_>) {

View File

@ -26,7 +26,7 @@ document-features = "0.2.11"
log-04 = { package = "log", version = "0.4.26", optional = true }
[build-dependencies]
esp-metadata = { version = "0.7.0", path = "../esp-metadata" }
esp-metadata-generated = { version = "0.0.1", path = "../esp-metadata-generated", features = ["build-script"] }
[features]
#! ### Chip selection

View File

@ -1,7 +1,5 @@
use std::{error::Error, path::Path};
use esp_metadata::{Chip, Config};
#[macro_export]
macro_rules! assert_unique_features {
($($feature:literal),+ $(,)?) => {
@ -20,28 +18,23 @@ fn main() -> Result<(), Box<dyn Error>> {
panic!("The 'esp-rom-sys' crate is not allowed to get bumped to anything above 0.1.x");
}
// Ensure that exactly one chip has been specified:
let chip = Chip::from_cargo_feature()?;
let chip = esp_metadata_generated::Chip::from_cargo_feature()?;
// Log and defmt are mutually exclusive features. The main technical reason is
// that allowing both would make the exact panicking behaviour a fragile
// implementation detail.
assert_unique_features!("log-04", "defmt");
// Load the configuration file for the configured device:
let config = Config::for_chip(&chip);
// Define all necessary configuration symbols for the configured device:
config.define_symbols();
config.generate_metadata();
chip.define_cfgs();
let out = std::path::PathBuf::from(std::env::var_os("OUT_DIR").unwrap());
println!("cargo:rustc-link-search={}", out.display());
copy_dir_all(format!("./ld/{chip}/"), &out)?;
copy_dir_all(format!("./libs/{chip}/"), &out)?;
copy_dir_all(format!("./ld/{}/", chip.name()), &out)?;
copy_dir_all(format!("./libs/{}/", chip.name()), &out)?;
include_libs(format!("./libs/{chip}/"))?;
include_libs(format!("./libs/{}/", chip.name()))?;
// exploit the fact that linkers treat an unknown library format as a linker
// script

View File

@ -28,9 +28,6 @@ esp-rom-sys = { version = "0.1.0", path = "../esp-rom-sys", optional = true
# Unstable dependencies that are not (strictly) part of the public API
document-features = "0.2.11"
[build-dependencies]
esp-metadata = { version = "0.7.0", path = "../esp-metadata" }
[features]
default = ["critical-section"]

View File

@ -1,9 +1,4 @@
fn main() -> Result<(), String> {
// Ensure that only a single chip is specified
if !cfg!(feature = "emulation") {
let _ = esp_metadata::Chip::from_cargo_feature().map_err(|e| format!("{e:?}"))?;
}
if cfg!(feature = "esp32") {
match std::env::var("OPT_LEVEL") {
Ok(level) if std::env::var("CI").is_err() => {

View File

@ -31,6 +31,7 @@ allocator-api2 = { version = "0.3.0", default-features = false, features = ["all
document-features = "0.2.11"
esp-alloc = { version = "0.8.0", path = "../esp-alloc", optional = true }
esp-config = { version = "0.4.0", path = "../esp-config" }
esp-metadata-generated = { version = "0.0.1", path = "../esp-metadata-generated" }
esp-wifi-sys = "0.7.1"
num-derive = { version = "0.4.2" }
num-traits = { version = "0.2.19", default-features = false }
@ -52,7 +53,7 @@ log-04 = { package = "log", version = "0.4.27", optional = true }
[build-dependencies]
esp-config = { version = "0.4.0", path = "../esp-config", features = ["build"] }
esp-metadata = { version = "0.7.0", path = "../esp-metadata" }
esp-metadata-generated = { version = "0.0.1", path = "../esp-metadata-generated", features = ["build-script"] }
[features]
default = ["builtin-scheduler", "esp-alloc"]
@ -62,38 +63,45 @@ default = ["builtin-scheduler", "esp-alloc"]
esp32c2 = [
"esp-hal/esp32c2",
"esp-wifi-sys/esp32c2",
"esp-metadata-generated/esp32c2",
]
# Target the ESP32-C3.
esp32c3 = [
"esp-hal/esp32c3",
"esp-wifi-sys/esp32c3",
"esp-metadata-generated/esp32c3",
]
# Target the ESP32-C6.
esp32c6 = [
"esp-hal/esp32c6",
"esp-wifi-sys/esp32c6",
"esp-metadata-generated/esp32c6",
]
# Target the ESP32-H2.
esp32h2 = [
"esp-hal/esp32h2",
"esp-wifi-sys/esp32h2",
"esp-metadata-generated/esp32h2",
]
# Target the ESP32.
esp32 = [
"esp-hal/esp32",
"esp-wifi-sys/esp32",
"esp-metadata-generated/esp32",
"xtensa-lx-rt/float-save-restore",
]
# Target the ESP32-S2.
esp32s2 = [
"esp-hal/esp32s2",
"esp-wifi-sys/esp32s2",
"esp-metadata-generated/esp32s2",
"xtensa-lx-rt/float-save-restore",
]
# Target the ESP32-S3.
esp32s3 = [
"esp-hal/esp32s3",
"esp-wifi-sys/esp32s3",
"esp-metadata-generated/esp32s3",
"xtensa-lx-rt/float-save-restore",
]

View File

@ -1,7 +1,7 @@
use std::error::Error;
use esp_config::generate_config_from_yaml_definition;
use esp_metadata::{Chip, Config};
use esp_metadata_generated::Chip;
#[macro_export]
macro_rules! assert_unique_features {
@ -17,10 +17,9 @@ macro_rules! assert_unique_features {
fn main() -> Result<(), Box<dyn Error>> {
// Load the configuration file for the configured device:
let chip = Chip::from_cargo_feature()?;
let config = Config::for_chip(&chip);
// Define all necessary configuration symbols for the configured device:
config.define_symbols();
chip.define_cfgs();
// Log and defmt are mutually exclusive features. The main technical reason is
// that allowing both would make the exact panicking behaviour a fragile
@ -28,7 +27,7 @@ fn main() -> Result<(), Box<dyn Error>> {
assert_unique_features!("log-04", "defmt");
assert!(
!cfg!(feature = "ble") || config.contains("bt"),
!cfg!(feature = "ble") || chip.contains("bt"),
r#"
BLE is not supported on this target.
@ -36,7 +35,7 @@ fn main() -> Result<(), Box<dyn Error>> {
"#
);
assert!(
!cfg!(feature = "wifi") || config.contains("wifi"),
!cfg!(feature = "wifi") || chip.contains("wifi"),
r#"
WiFi is not supported on this target.
@ -58,7 +57,7 @@ fn main() -> Result<(), Box<dyn Error>> {
#[cfg(feature = "coex")]
{
assert!(
config.contains("wifi") && config.contains("bt"),
chip.contains("wifi") && chip.contains("bt"),
r#"
WiFi/Bluetooth coexistence is not supported on this target.
@ -83,7 +82,7 @@ fn main() -> Result<(), Box<dyn Error>> {
println!("cargo:rerun-if-changed=./esp_config.yml");
let cfg_yaml = std::fs::read_to_string("./esp_config.yml")
.expect("Failed to read esp_config.yml for esp-wifi");
generate_config_from_yaml_definition(&cfg_yaml, true, true, Some(config.clone())).unwrap();
generate_config_from_yaml_definition(&cfg_yaml, true, true, Some(chip)).unwrap();
Ok(())
}

View File

@ -25,7 +25,7 @@
//! ```toml
//! [dependencies.esp-wifi]
//! # A supported chip needs to be specified, as well as specific use-case features
#![doc = concat!(r#"features = [""#, esp_hal::chip!(), r#"", "wifi", "esp-now"]"#)]
#![doc = concat!(r#"features = [""#, chip!(), r#"", "wifi", "esp-now"]"#)]
//! ```
//!
//! ### Optimization Level
@ -100,6 +100,9 @@
)
)]
#[macro_use]
extern crate esp_metadata_generated;
extern crate alloc;
// MUST be the first module

View File

@ -271,7 +271,7 @@ sha1 = { version = "0.10.6", default-features = false }
sha2 = { version = "0.10.8", default-features = false }
[build-dependencies]
esp-metadata = { path = "../esp-metadata" }
esp-metadata-generated = { path = "../esp-metadata-generated", features = ["build-script"] }
[features]
default = []
@ -288,6 +288,7 @@ esp32 = [
"esp-wifi?/esp32",
"esp-storage?/esp32",
"esp-bootloader-esp-idf/esp32",
"esp-metadata-generated/esp32",
]
esp32c2 = [
"esp-backtrace/esp32c2",
@ -296,6 +297,7 @@ esp32c2 = [
"esp-wifi?/esp32c2",
"esp-storage?/esp32c2",
"esp-bootloader-esp-idf/esp32c2",
"esp-metadata-generated/esp32c2",
]
esp32c3 = [
"esp-backtrace/esp32c3",
@ -304,6 +306,7 @@ esp32c3 = [
"esp-wifi?/esp32c3",
"esp-storage?/esp32c3",
"esp-bootloader-esp-idf/esp32c3",
"esp-metadata-generated/esp32c3",
]
esp32c6 = [
"esp-backtrace/esp32c6",
@ -312,6 +315,7 @@ esp32c6 = [
"esp-wifi?/esp32c6",
"esp-storage?/esp32c6",
"esp-bootloader-esp-idf/esp32c6",
"esp-metadata-generated/esp32c6",
]
esp32h2 = [
"esp-backtrace/esp32h2",
@ -320,6 +324,7 @@ esp32h2 = [
"esp-wifi?/esp32h2",
"esp-storage?/esp32h2",
"esp-bootloader-esp-idf/esp32h2",
"esp-metadata-generated/esp32h2",
]
esp32s2 = [
"embedded-test/xtensa-semihosting",
@ -329,6 +334,7 @@ esp32s2 = [
"esp-wifi?/esp32s2",
"esp-storage?/esp32s2",
"esp-bootloader-esp-idf/esp32s2",
"esp-metadata-generated/esp32s2",
]
esp32s3 = [
"embedded-test/xtensa-semihosting",
@ -338,6 +344,7 @@ esp32s3 = [
"esp-wifi?/esp32s3",
"esp-storage?/esp32s3",
"esp-bootloader-esp-idf/esp32s3",
"esp-metadata-generated/esp32s3",
]
# Async & Embassy:
embassy = [

View File

@ -1,14 +1,8 @@
use std::error::Error;
use esp_metadata::{Chip, Config};
fn main() -> Result<(), Box<dyn Error>> {
// Load the configuration file for the configured device:
let chip = Chip::from_cargo_feature()?;
let config = Config::for_chip(&chip);
// Define all necessary configuration symbols for the configured device:
config.define_symbols();
esp_metadata_generated::Chip::from_cargo_feature()?.define_cfgs();
Ok(())
}

View File

@ -15,12 +15,14 @@ kuchikiki = { version = "0.8.2", optional = true }
log = "0.4.22"
minijinja = { version = "2.5.0", default-features = false }
opener = { version = "0.7.2", optional = true }
prettyplease = { version = "0.2.34" }
regex = { version = "1.11.1", optional = true }
rocket = { version = "0.5.1", optional = true }
semver = { version = "1.0.23", features = ["serde"] }
serde = { version = "1.0.215", default-features = false, features = ["derive"] }
serde_json = "1.0.70"
strum = { version = "0.27.1", features = ["derive"] }
syn = { version = "2", default-features = false, features = ["full", "parsing"] }
toml_edit = "0.22.22"
walkdir = "2.5.0"

View File

@ -135,7 +135,7 @@ pub fn build_examples(
crate::execute_app(
package_path,
args.chip,
target,
&target,
example,
CargoAction::Build(out_path.to_path_buf()),
1,
@ -154,7 +154,7 @@ pub fn build_examples(
crate::execute_app(
package_path,
args.chip,
target,
&target,
example,
CargoAction::Build(out_path.to_path_buf()),
1,

View File

@ -127,7 +127,7 @@ pub fn tests(workspace: &Path, args: TestsArgs, action: CargoAction) -> Result<(
crate::execute_app(
&package_path,
args.chip,
target,
&target,
test,
action.clone(),
args.repeat,
@ -145,7 +145,7 @@ pub fn tests(workspace: &Path, args: TestsArgs, action: CargoAction) -> Result<(
if crate::execute_app(
&package_path,
args.chip,
target,
&target,
&test,
action.clone(),
args.repeat,

View File

@ -179,7 +179,7 @@ pub fn run_examples(
&& crate::execute_app(
package_path,
args.chip,
target,
&target,
&example,
CargoAction::Run,
1,

View File

@ -5,14 +5,14 @@ use std::{
path::{Path, PathBuf},
};
use anyhow::{ensure, Context as _, Result};
use anyhow::{Context as _, Result, ensure};
use clap::ValueEnum;
use esp_metadata::Config;
use minijinja::Value;
use serde::{Deserialize, Serialize};
use strum::IntoEnumIterator;
use crate::{cargo::CargoArgsBuilder, Chip, Package};
use crate::{Chip, Package, cargo::CargoArgsBuilder};
// ----------------------------------------------------------------------------
// Build Documentation
@ -210,7 +210,7 @@ fn cargo_doc(workspace: &Path, package: Package, chip: Option<Chip>) -> Result<P
.arg("--lib")
.arg("--no-deps");
if let Some(target) = target {
if let Some(ref target) = target {
builder = builder.target(target);
}
@ -239,7 +239,7 @@ fn cargo_doc(workspace: &Path, package: Package, chip: Option<Chip>) -> Result<P
workspace.join(package.to_string()).join("target")
};
if let Some(target) = target {
if let Some(ref target) = target {
docs_path = docs_path.join(target);
}
docs_path = docs_path.join("doc");

View File

@ -5,10 +5,8 @@ use std::{
use anyhow::{Result, anyhow};
use cargo::CargoAction;
use clap::ValueEnum;
use esp_metadata::{Chip, Config};
use esp_metadata::{Chip, Config, TokenStream};
use serde::{Deserialize, Serialize};
use strum::{Display, EnumIter};
use crate::{
cargo::{CargoArgsBuilder, CargoToml},
@ -34,9 +32,10 @@ pub mod semver_check;
PartialOrd,
Ord,
Hash,
Display,
EnumIter,
ValueEnum,
clap::ValueEnum,
strum::Display,
strum::EnumIter,
strum::AsRefStr,
serde::Deserialize,
serde::Serialize,
)]
@ -54,6 +53,7 @@ pub enum Package {
EspIeee802154,
EspLpHal,
EspMetadata,
EspMetadataGenerated,
EspPrintln,
EspRiscvRt,
EspStorage,
@ -77,6 +77,7 @@ impl Package {
| EspBootloaderEspIdf
| EspHal
| EspHalEmbassy
| EspMetadataGenerated
| EspRomSys
| EspIeee802154
| EspLpHal
@ -140,7 +141,13 @@ impl Package {
matches!(
self,
EspHal | EspLpHal | EspWifi | EspHalEmbassy | EspRomSys | EspBootloaderEspIdf
EspHal
| EspLpHal
| EspWifi
| EspHalEmbassy
| EspRomSys
| EspBootloaderEspIdf
| EspMetadataGenerated
)
}
@ -155,10 +162,12 @@ impl Package {
}
/// Build on host
pub fn build_on_host(&self) -> bool {
use Package::*;
matches!(self, EspConfig | EspMetadata)
pub fn build_on_host(&self, features: &[String]) -> bool {
match self {
Self::EspConfig | Self::EspMetadata => true,
Self::EspMetadataGenerated if features.iter().any(|f| f == "build-script") => true,
_ => false,
}
}
/// Given a device config, return the features which should be enabled for
@ -229,6 +238,7 @@ impl Package {
Package::EspAlloc => {
features.push("defmt".to_owned());
}
Package::EspMetadataGenerated => {}
_ => {}
}
@ -239,21 +249,27 @@ impl Package {
pub fn lint_feature_rules(&self, _config: &Config) -> Vec<Vec<String>> {
let mut cases = Vec::new();
if self == &Package::EspWifi {
// Minimal set of features that when enabled _should_ still compile:
cases.push(vec![
"esp-hal/unstable".to_owned(),
"builtin-scheduler".to_owned(),
]);
match self {
Package::EspWifi => {
// Minimal set of features that when enabled _should_ still compile:
cases.push(vec![
"esp-hal/unstable".to_owned(),
"builtin-scheduler".to_owned(),
]);
}
Package::EspMetadataGenerated => {
cases.push(vec!["build-script".to_owned()]);
}
_ => {}
}
cases
}
/// Return the target triple for a given package/chip pair.
pub fn target_triple(&self, chip: &Chip) -> Result<&'static str> {
pub fn target_triple(&self, chip: &Chip) -> Result<String> {
if *self == Package::EspLpHal {
chip.lp_target()
chip.lp_target().map(ToString::to_string)
} else {
Ok(chip.target())
}
@ -294,7 +310,7 @@ impl Package {
}
}
#[derive(Debug, Clone, Copy, Display, ValueEnum, Serialize, Deserialize)]
#[derive(Debug, Clone, Copy, strum::Display, clap::ValueEnum, Serialize, Deserialize)]
#[strum(serialize_all = "lowercase")]
pub enum Version {
Major,
@ -466,7 +482,92 @@ pub fn windows_safe_path(path: &Path) -> PathBuf {
PathBuf::from(path.to_str().unwrap().to_string().replace("\\\\?\\", ""))
}
pub fn update_chip_support_table(workspace: &Path) -> Result<()> {
pub fn format_package(workspace: &Path, package: Package, check: bool) -> Result<()> {
log::info!("Formatting package: {}", package);
let path = workspace.join(package.as_ref());
// we need to list all source files since modules in `unstable_module!` macros
// won't get picked up otherwise
let source_files = walkdir::WalkDir::new(path.join("src"))
.into_iter()
.filter_map(|entry| {
let path = entry.unwrap().into_path();
if let Some("rs") = path.extension().unwrap_or_default().to_str() {
Some(String::from(path.to_str().unwrap()))
} else {
None
}
});
let mut cargo_args = CargoArgsBuilder::default()
.toolchain("nightly")
.subcommand("fmt")
.arg("--all")
.build();
if check {
cargo_args.push("--check".into());
}
cargo_args.push("--".into());
cargo_args.push(format!(
"--config-path={}/rustfmt.toml",
workspace.display()
));
cargo_args.extend(source_files);
cargo::run(&cargo_args, &path)?;
Ok(())
}
pub fn update_metadata(workspace: &Path) -> Result<()> {
update_chip_support_table(workspace)?;
generate_metadata(workspace, save)?;
format_package(workspace, Package::EspMetadataGenerated, false)?;
Ok(())
}
fn generate_metadata(
workspace: &Path,
call_for_file: fn(&Path, TokenStream) -> Result<()>,
) -> Result<()> {
use strum::IntoEnumIterator;
let out_path = workspace.join("esp-metadata-generated").join("src");
for chip in Chip::iter() {
let config = esp_metadata::Config::for_chip(&chip);
call_for_file(
&out_path.join(format!("_generated_{chip}.rs")),
config.generate_metadata(),
)?;
}
call_for_file(
&out_path.join("_build_script_utils.rs"),
esp_metadata::generate_build_script_utils(),
)?;
call_for_file(&out_path.join("lib.rs"), esp_metadata::generate_lib_rs())?;
Ok(())
}
fn save(out_path: &Path, tokens: TokenStream) -> Result<()> {
let source = tokens.to_string();
let syntax_tree = syn::parse_file(&source)?;
let source = prettyplease::unparse(&syntax_tree);
std::fs::write(out_path, source)?;
Ok(())
}
fn update_chip_support_table(workspace: &Path) -> Result<()> {
let mut output = String::new();
let readme = std::fs::read_to_string(workspace.join("esp-hal").join("README.md"))?;

View File

@ -42,8 +42,8 @@ enum Cli {
SemverCheck(SemverCheckArgs),
/// Check the changelog for packages.
CheckChangelog(CheckChangelogArgs),
/// Re-generate the chip support table in the esp-hal README.
UpdateChipSupportTable,
/// Re-generate metadata and the chip support table in the esp-hal README.
UpdateMetadata,
}
#[derive(Debug, Args)]
@ -164,12 +164,7 @@ fn main() -> Result<()> {
Cli::LintPackages(args) => lint_packages(&workspace, args),
Cli::SemverCheck(args) => semver_checks(&workspace, args),
Cli::CheckChangelog(args) => check_changelog(&workspace, &args.packages, args.normalize),
Cli::UpdateChipSupportTable => {
// Re-generate the chip support table in the esp-hal README.
// This is a no-op if the table is already up-to-date.
xtask::update_chip_support_table(&workspace)?;
Ok(())
}
Cli::UpdateMetadata => xtask::update_metadata(&workspace),
}
}
@ -181,41 +176,7 @@ fn fmt_packages(workspace: &Path, args: FmtPackagesArgs) -> Result<()> {
packages.sort();
for package in packages {
log::info!("Formatting package: {}", package);
let path = workspace.join(package.to_string());
// we need to list all source files since modules in `unstable_module!` macros
// won't get picked up otherwise
let source_files: Vec<String> = walkdir::WalkDir::new(path.join("src"))
.into_iter()
.filter_map(|entry| {
let path = entry.unwrap().into_path();
if let Some("rs") = path.extension().unwrap_or_default().to_str() {
Some(String::from(path.to_str().unwrap()))
} else {
None
}
})
.collect();
let mut cargo_args = CargoArgsBuilder::default()
.toolchain("nightly")
.subcommand("fmt")
.arg("--all")
.build();
if args.check {
cargo_args.push("--check".into());
}
cargo_args.push("--".into());
cargo_args.push(format!(
"--config-path={}/rustfmt.toml",
workspace.display()
));
cargo_args.extend_from_slice(&source_files);
xtask::cargo::run(&cargo_args, &path)?;
xtask::format_package(workspace, package, args.check)?;
}
Ok(())
@ -299,7 +260,7 @@ fn lint_package(
let mut builder = CargoArgsBuilder::default().subcommand("clippy");
if !package.build_on_host() {
if !package.build_on_host(features) {
if chip.is_xtensa() {
// In case the user doesn't specify a toolchain, make sure we use +esp
toolchain.get_or_insert("esp");
@ -308,7 +269,7 @@ fn lint_package(
}
if let Some(toolchain) = toolchain {
if !package.build_on_host() && toolchain.starts_with("esp") {
if !package.build_on_host(features) && toolchain.starts_with("esp") {
builder = builder.arg("-Zbuild-std=core,alloc");
}
builder = builder.toolchain(toolchain);