mirror of
https://github.com/esp-rs/esp-hal.git
synced 2025-09-26 20:00:32 +00:00
Document esp-metadata-generated
(#3787)
* Try to make it more obvious how to update e-m-g * Document top level, ensure build-script docs are present * Document Chip, hide Config
This commit is contained in:
parent
9e20bc3807
commit
df7ba7d427
@ -4,7 +4,7 @@ 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/"
|
||||
documentation = "https://docs.espressif.com/projects/rust/esp-metadata-generated/latest/"
|
||||
repository = "https://github.com/esp-rs/esp-hal"
|
||||
license = "MIT OR Apache-2.0"
|
||||
|
||||
@ -15,10 +15,11 @@ esp-metadata = { version = "0.7.0", path = "../esp-metadata" } # TODO: remove
|
||||
|
||||
[features]
|
||||
build-script = []
|
||||
esp32 = []
|
||||
esp32c2 = []
|
||||
esp32c3 = []
|
||||
esp32c6 = []
|
||||
esp32h2 = []
|
||||
esp32s2 = []
|
||||
esp32s3 = []
|
||||
_device-selected = []
|
||||
esp32 = ["_device-selected"]
|
||||
esp32c2 = ["_device-selected"]
|
||||
esp32c3 = ["_device-selected"]
|
||||
esp32c6 = ["_device-selected"]
|
||||
esp32h2 = ["_device-selected"]
|
||||
esp32s2 = ["_device-selected"]
|
||||
esp32s3 = ["_device-selected"]
|
||||
|
@ -8,9 +8,11 @@
|
||||
|
||||
The generated output of `esp-metadata`, intended for use in [build scripts] and HAL crates alike.
|
||||
|
||||
The contents of this crate have been generated by running `cargo xtask update-metadata`. Do not edit by hand.
|
||||
|
||||
[build scripts]: https://doc.rust-lang.org/cargo/reference/build-scripts.html
|
||||
|
||||
## [Documentation](https://docs.espressif.com/projects/rust/esp-metadata/latest/)
|
||||
## [Documentation](https://docs.espressif.com/projects/rust/esp-metadata-generated/latest/)
|
||||
|
||||
## Minimum Supported Rust Version (MSRV)
|
||||
|
||||
|
@ -1,4 +1,12 @@
|
||||
// Do NOT edit this file directly. Make your changes to esp-metadata,
|
||||
// then run `cargo xtask update-metadata`.
|
||||
|
||||
#[cfg(docsrs)]
|
||||
macro_rules! println {
|
||||
($($any:tt)*) => {};
|
||||
}
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "build-script")))]
|
||||
pub enum Chip {
|
||||
Esp32,
|
||||
Esp32c2,
|
||||
@ -24,7 +32,10 @@ impl core::str::FromStr for Chip {
|
||||
}
|
||||
}
|
||||
impl Chip {
|
||||
pub fn from_cargo_feature() -> Result<Self, Box<dyn std::error::Error>> {
|
||||
/// Tries to extract the active chip from the active cargo features.
|
||||
///
|
||||
/// Exactly one device feature must be enabled for this function to succeed.
|
||||
pub fn from_cargo_feature() -> Result<Self, &'static str> {
|
||||
let all_chips = [
|
||||
("CARGO_FEATURE_ESP32", Self::Esp32),
|
||||
("CARGO_FEATURE_ESP32C2", Self::Esp32c2),
|
||||
@ -39,8 +50,7 @@ impl Chip {
|
||||
if std::env::var(env).is_ok() {
|
||||
if chip.is_some() {
|
||||
return Err(
|
||||
"Expected exactly one of the following features to be enabled: esp32, esp32c2, esp32c3, esp32c6, esp32h2, esp32s2, esp32s3"
|
||||
.into(),
|
||||
"Expected exactly one of the following features to be enabled: esp32, esp32c2, esp32c3, esp32c6, esp32h2, esp32s2, esp32s3",
|
||||
);
|
||||
}
|
||||
chip = Some(c);
|
||||
@ -48,20 +58,26 @@ impl Chip {
|
||||
}
|
||||
match chip {
|
||||
Some(chip) => Ok(chip),
|
||||
None => {
|
||||
Err(
|
||||
"Expected exactly one of the following features to be enabled: esp32, esp32c2, esp32c3, esp32c6, esp32h2, esp32s2, esp32s3"
|
||||
.into(),
|
||||
)
|
||||
}
|
||||
None => Err(
|
||||
"Expected exactly one of the following features to be enabled: esp32, esp32c2, esp32c3, esp32c6, esp32h2, esp32s2, esp32s3",
|
||||
),
|
||||
}
|
||||
}
|
||||
/// Returns whether the current chip uses the Tensilica Xtensa ISA.
|
||||
pub fn is_xtensa(self) -> bool {
|
||||
self.config().architecture == "xtensa"
|
||||
}
|
||||
/// The target triple of the current chip.
|
||||
pub fn target(self) -> &'static str {
|
||||
self.config().target
|
||||
}
|
||||
/// The simple name of the current chip.
|
||||
///
|
||||
/// ## Example
|
||||
///
|
||||
/// ```rust
|
||||
/// assert_eq!(Chip::Esp32s3.name(), "esp32s3");
|
||||
/// ```
|
||||
pub fn name(self) -> &'static str {
|
||||
match self {
|
||||
Self::Esp32 => "esp32",
|
||||
@ -73,15 +89,39 @@ impl Chip {
|
||||
Self::Esp32s3 => "esp32s3",
|
||||
}
|
||||
}
|
||||
/// Returns whether the chip configuration contains the given symbol.
|
||||
///
|
||||
/// This function is a short-hand for `self.all_symbols().contains(&symbol)`.
|
||||
///
|
||||
/// ## Example
|
||||
///
|
||||
/// ```rust
|
||||
/// assert!(Chip::Esp32s3.contains("soc_has_pcnt"));
|
||||
/// ```
|
||||
pub fn contains(self, symbol: &str) -> bool {
|
||||
self.config().contains(symbol)
|
||||
self.all_symbols().contains(&symbol)
|
||||
}
|
||||
/// Calling this function will define all cfg symbols for the firmware crate to use.
|
||||
pub fn define_cfgs(self) {
|
||||
self.config().define_cfgs()
|
||||
}
|
||||
/// Returns all symbols as a big slice.
|
||||
///
|
||||
/// ## Example
|
||||
///
|
||||
/// ```rust
|
||||
/// assert!(Chip::Esp32s3.all_symbols().contains("soc_has_pcnt"));
|
||||
/// ```
|
||||
pub fn all_symbols(&self) -> &'static [&'static str] {
|
||||
self.config().symbols
|
||||
}
|
||||
/// Returns an iterator over all chips.
|
||||
///
|
||||
/// ## Example
|
||||
///
|
||||
/// ```rust
|
||||
/// assert!(Chip::iter().any(|c| c == Chip::Esp32));
|
||||
/// ```
|
||||
pub fn iter() -> impl Iterator<Item = Chip> {
|
||||
[
|
||||
Self::Esp32,
|
||||
@ -94,7 +134,7 @@ impl Chip {
|
||||
]
|
||||
.into_iter()
|
||||
}
|
||||
pub fn config(self) -> Config {
|
||||
fn config(self) -> Config {
|
||||
match self {
|
||||
Self::Esp32 => Config {
|
||||
architecture: "xtensa",
|
||||
@ -2105,16 +2145,13 @@ impl Chip {
|
||||
}
|
||||
}
|
||||
}
|
||||
pub struct Config {
|
||||
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!("cargo:rustc-check-cfg=cfg(not_really_docsrs)");
|
||||
println!("cargo:rustc-check-cfg=cfg(esp32)");
|
||||
|
@ -1,3 +1,6 @@
|
||||
// Do NOT edit this file directly. Make your changes to esp-metadata,
|
||||
// then run `cargo xtask update-metadata`.
|
||||
|
||||
/// The name of the chip as `&str`
|
||||
///
|
||||
/// # Example
|
||||
@ -8,6 +11,7 @@
|
||||
#[doc = concat!("assert_eq!(chip_name, ", chip!(), ")")]
|
||||
/// ```
|
||||
#[macro_export]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
macro_rules! chip {
|
||||
() => {
|
||||
"esp32"
|
||||
@ -15,6 +19,7 @@ macro_rules! chip {
|
||||
}
|
||||
/// The properties of this chip and its drivers.
|
||||
#[macro_export]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
macro_rules! property {
|
||||
("chip") => {
|
||||
"esp32"
|
||||
@ -157,12 +162,30 @@ macro_rules! property {
|
||||
}
|
||||
/// Macro to get the address range of the given memory region.
|
||||
#[macro_export]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
macro_rules! memory_range {
|
||||
("DRAM") => {
|
||||
1073405952..1073741824
|
||||
};
|
||||
}
|
||||
/// This macro can be used to generate code for each peripheral instance of the I2C master driver.
|
||||
///
|
||||
/// For an explanation on the general syntax, as well as usage of individual/repeated
|
||||
/// matchers, refer to [the crate-level documentation][crate#for_each-macros].
|
||||
///
|
||||
/// This macro has one option for its "Individual matcher" case:
|
||||
///
|
||||
/// Syntax: `($instance:ident, $sys:ident, $scl:ident, $sda:ident)`
|
||||
///
|
||||
/// Macro fragments:
|
||||
///
|
||||
/// - `$instance`: the name of the I2C instance
|
||||
/// - `$sys`: the name of the instance as it is in the `esp_hal::system::Peripheral` enum.
|
||||
/// - `$scl`, `$sda`: peripheral signal names.
|
||||
///
|
||||
/// Example data: `(I2C0, I2cExt0, I2CEXT0_SCL, I2CEXT0_SDA)`
|
||||
#[macro_export]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
macro_rules! for_each_i2c_master {
|
||||
($($pattern:tt => $code:tt;)*) => {
|
||||
macro_rules! _for_each_inner { $(($pattern) => $code;)* ($other : tt) => {} }
|
||||
@ -172,7 +195,24 @@ macro_rules! for_each_i2c_master {
|
||||
I2CEXT1_SCL, I2CEXT1_SDA)));
|
||||
};
|
||||
}
|
||||
/// This macro can be used to generate code for each peripheral instance of the UART driver.
|
||||
///
|
||||
/// For an explanation on the general syntax, as well as usage of individual/repeated
|
||||
/// matchers, refer to [the crate-level documentation][crate#for_each-macros].
|
||||
///
|
||||
/// This macro has one option for its "Individual matcher" case:
|
||||
///
|
||||
/// Syntax: `($instance:ident, $sys:ident, $rx:ident, $tx:ident, $cts:ident, $rts:ident)`
|
||||
///
|
||||
/// Macro fragments:
|
||||
///
|
||||
/// - `$instance`: the name of the UART instance
|
||||
/// - `$sys`: the name of the instance as it is in the `esp_hal::system::Peripheral` enum.
|
||||
/// - `$rx`, `$tx`, `$cts`, `$rts`: signal names.
|
||||
///
|
||||
/// Example data: `(UART0, Uart0, U0RXD, U0TXD, U0CTS, U0RTS)`
|
||||
#[macro_export]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
macro_rules! for_each_uart {
|
||||
($($pattern:tt => $code:tt;)*) => {
|
||||
macro_rules! _for_each_inner { $(($pattern) => $code;)* ($other : tt) => {} }
|
||||
@ -183,7 +223,29 @@ macro_rules! for_each_uart {
|
||||
U1RXD, U1TXD, U1CTS, U1RTS), (UART2, Uart2, U2RXD, U2TXD, U2CTS, U2RTS)));
|
||||
};
|
||||
}
|
||||
/// This macro can be used to generate code for each peripheral instance of the SPI master driver.
|
||||
///
|
||||
/// For an explanation on the general syntax, as well as usage of individual/repeated
|
||||
/// matchers, refer to [the crate-level documentation][crate#for_each-macros].
|
||||
///
|
||||
/// This macro has one option for its "Individual matcher" case:
|
||||
///
|
||||
/// Syntax: `($instance:ident, $sys:ident, $sclk:ident, [$($cs:ident),*] [$($sio:ident),*
|
||||
/// $($is_qspi:iteral)?])`
|
||||
///
|
||||
/// Macro fragments:
|
||||
///
|
||||
/// - `$instance`: the name of the SPI instance
|
||||
/// - `$sys`: the name of the instance as it is in the `esp_hal::system::Peripheral` enum.
|
||||
/// - `$cs`, `$sio`: chip select and SIO signal names.
|
||||
/// - `$is_qspi`: a `true` literal present if the SPI instance supports QSPI.
|
||||
///
|
||||
/// Example data:
|
||||
/// - `(SPI2, Spi2, FSPICLK [FSPICS0, FSPICS1, FSPICS2, FSPICS3, FSPICS4, FSPICS5] [FSPID, FSPIQ,
|
||||
/// FSPIWP, FSPIHD, FSPIIO4, FSPIIO5, FSPIIO6, FSPIIO7], true)`
|
||||
/// - `(SPI3, Spi3, SPI3_CLK [SPI3_CS0, SPI3_CS1, SPI3_CS2] [SPI3_D, SPI3_Q])`
|
||||
#[macro_export]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
macro_rules! for_each_spi_master {
|
||||
($($pattern:tt => $code:tt;)*) => {
|
||||
macro_rules! _for_each_inner { $(($pattern) => $code;)* ($other : tt) => {} }
|
||||
@ -195,7 +257,24 @@ macro_rules! for_each_spi_master {
|
||||
true)));
|
||||
};
|
||||
}
|
||||
/// This macro can be used to generate code for each peripheral instance of the SPI slave driver.
|
||||
///
|
||||
/// For an explanation on the general syntax, as well as usage of individual/repeated
|
||||
/// matchers, refer to [the crate-level documentation][crate#for_each-macros].
|
||||
///
|
||||
/// This macro has one option for its "Individual matcher" case:
|
||||
///
|
||||
/// Syntax: `($instance:ident, $sys:ident, $sclk:ident, $mosi:ident, $miso:ident, $cs:ident)`
|
||||
///
|
||||
/// Macro fragments:
|
||||
///
|
||||
/// - `$instance`: the name of the I2C instance
|
||||
/// - `$sys`: the name of the instance as it is in the `esp_hal::system::Peripheral` enum.
|
||||
/// - `$mosi`, `$miso`, `$cs`: signal names.
|
||||
///
|
||||
/// Example data: `(SPI2, Spi2, FSPICLK, FSPID, FSPIQ, FSPICS0)`
|
||||
#[macro_export]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
macro_rules! for_each_spi_slave {
|
||||
($($pattern:tt => $code:tt;)*) => {
|
||||
macro_rules! _for_each_inner { $(($pattern) => $code;)* ($other : tt) => {} }
|
||||
@ -206,6 +285,7 @@ macro_rules! for_each_spi_slave {
|
||||
};
|
||||
}
|
||||
#[macro_export]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
macro_rules! for_each_peripheral {
|
||||
($($pattern:tt => $code:tt;)*) => {
|
||||
macro_rules! _for_each_inner { $(($pattern) => $code;)* ($other : tt) => {} }
|
||||
@ -327,56 +407,32 @@ macro_rules! for_each_peripheral {
|
||||
virtual() (unstable)), (TOUCH <= virtual() (unstable))));
|
||||
};
|
||||
}
|
||||
/// This macro can be used to generate code for each GPIOn instance.
|
||||
/// This macro can be used to generate code for each `GPIOn` instance.
|
||||
///
|
||||
/// The basic syntax of this macro looks like a macro definition with two distinct syntax options:
|
||||
/// For an explanation on the general syntax, as well as usage of individual/repeated
|
||||
/// matchers, refer to [the crate-level documentation][crate#for_each-macros].
|
||||
///
|
||||
/// ```rust, no_run
|
||||
/// for_each_gpio! {
|
||||
/// // Individual matcher, invoked separately for each GPIO
|
||||
/// ( <match arm> ) => { /* some code */ };
|
||||
/// This macro has one option for its "Individual matcher" case:
|
||||
///
|
||||
/// // Repeated matcher, invoked once with all GPIOs
|
||||
/// ( all $( (<individual match syntax>) ),* ) => { /* some code */ };
|
||||
/// }
|
||||
/// ```
|
||||
/// Syntax: `($n:literal, $gpio:ident ($($digital_input_function:ident =>
|
||||
/// $digital_input_signal:ident)*) ($($digital_output_function:ident =>
|
||||
/// $digital_output_signal:ident)*) ($($pin_attribute:ident)*))`
|
||||
///
|
||||
/// You can specify any number of matchers.
|
||||
/// Macro fragments:
|
||||
///
|
||||
/// ## Using the individual matcher
|
||||
/// - `$n`: the number of the GPIO. For `GPIO0`, `$n` is 0.
|
||||
/// - `$gpio`: the name of the GPIO.
|
||||
/// - `$digital_input_function`: the number of the digital function, as an identifier (i.e. for
|
||||
/// function 0 this is `_0`).
|
||||
/// - `$digital_input_function`: the name of the digital function, as an identifier.
|
||||
/// - `$digital_output_function`: the number of the digital function, as an identifier (i.e. for
|
||||
/// function 0 this is `_0`).
|
||||
/// - `$digital_output_function`: the name of the digital function, as an identifier.
|
||||
/// - `$pin_attribute`: `Input` and/or `Output`, marks the possible directions of the GPIO.
|
||||
///
|
||||
/// In this use case, each GPIO's data is individually passed through the macro. This can be used to
|
||||
/// generate code for each GPIO separately, allowing specializing the implementation where needed.
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// for_each_gpio! {
|
||||
/// // Example data: `(0, GPIO0 (_5 => EMAC_TX_CLK) (_1 => CLK_OUT1 _5 => EMAC_TX_CLK) (Input Output))`
|
||||
/// ($n:literal, $gpio:ident ($($digital_input_function:ident => $digital_input_signal:ident)*) ($($digital_output_function:ident => $digital_output_signal:ident)*) ($($pin_attribute:ident)*)) => { /* some code */ };
|
||||
///
|
||||
/// // You can create matchers with data filled in. This example will specifically match GPIO2
|
||||
/// ($n:literal, GPIO2 $input_af:tt $output_af:tt $attributes:tt) => { /* Additional case only for GPIO2 */ };
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// ## Repeated matcher
|
||||
///
|
||||
/// With this option, all GPIO data is passed through the macro all at once. This form can be used
|
||||
/// to, for example, generate struct fields.
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// // Example usage to create a struct containing all GPIOs:
|
||||
/// for_each_gpio! {
|
||||
/// (all $( ($n:literal, $gpio:ident $_af_ins:tt $_af_outs:tt $_attrs:tt) ),*) => {
|
||||
/// struct Gpios {
|
||||
/// $(
|
||||
/// #[doc = concat!(" The ", stringify!($n), "th GPIO pin")]
|
||||
/// pub $gpio: Gpio<$n>,
|
||||
/// )*
|
||||
/// }
|
||||
/// };
|
||||
/// }
|
||||
/// ```
|
||||
/// Example data: `(0, GPIO0 (_5 => EMAC_TX_CLK) (_1 => CLK_OUT1 _5 => EMAC_TX_CLK) (Input Output))`
|
||||
#[macro_export]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
macro_rules! for_each_gpio {
|
||||
($($pattern:tt => $code:tt;)*) => {
|
||||
macro_rules! _for_each_inner { $(($pattern) => $code;)* ($other : tt) => {} }
|
||||
@ -467,7 +523,7 @@ macro_rules! for_each_gpio {
|
||||
/// This macro can be used to generate code for each analog function of each GPIO.
|
||||
///
|
||||
/// For an explanation on the general syntax, as well as usage of individual/repeated
|
||||
/// matchers, refer to [for_each_gpio].
|
||||
/// matchers, refer to [the crate-level documentation][crate#for_each-macros].
|
||||
///
|
||||
/// This macro has two options for its "Individual matcher" case:
|
||||
///
|
||||
@ -476,8 +532,21 @@ macro_rules! for_each_gpio {
|
||||
/// where you need the number(s) of a signal, or the general group to which the signal belongs.
|
||||
/// For example, in case of `ADC2_CH3` the expanded form looks like `(ADC2_CH3, ADCn_CHm, 2, 3)`.
|
||||
///
|
||||
/// The expanded signal are only available when the signal has at least one numbered component.
|
||||
/// Macro fragments:
|
||||
///
|
||||
/// - `$signal`: the name of the signal.
|
||||
/// - `$group`: the name of the signal, with numbers replaced by placeholders. For `ADC2_CH3` this
|
||||
/// is `ADCn_CHm`.
|
||||
/// - `$number`: the numbers extracted from `$signal`.
|
||||
/// - `$gpio`: the name of the GPIO.
|
||||
///
|
||||
/// Example data:
|
||||
/// - `(ADC2_CH5, GPIO12)`
|
||||
/// - `((ADC2_CH5, ADCn_CHm, 2, 5), GPIO12)`
|
||||
///
|
||||
/// The expanded syntax is only available when the signal has at least one numbered component.
|
||||
#[macro_export]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
macro_rules! for_each_analog_function {
|
||||
($($pattern:tt => $code:tt;)*) => {
|
||||
macro_rules! _for_each_inner { $(($pattern) => $code;)* ($other : tt) => {} }
|
||||
@ -549,7 +618,7 @@ macro_rules! for_each_analog_function {
|
||||
/// This macro can be used to generate code for each LP/RTC function of each GPIO.
|
||||
///
|
||||
/// For an explanation on the general syntax, as well as usage of individual/repeated
|
||||
/// matchers, refer to [for_each_gpio].
|
||||
/// matchers, refer to [the crate-level documentation][crate#for_each-macros].
|
||||
///
|
||||
/// This macro has two options for its "Individual matcher" case:
|
||||
///
|
||||
@ -559,8 +628,21 @@ macro_rules! for_each_analog_function {
|
||||
/// For example, in case of `SAR_I2C_SCL_1` the expanded form looks like `(SAR_I2C_SCL_1,
|
||||
/// SAR_I2C_SCL_n, 1)`.
|
||||
///
|
||||
/// The expanded signal are only available when the signal has at least one numbered component.
|
||||
/// Macro fragments:
|
||||
///
|
||||
/// - `$signal`: the name of the signal.
|
||||
/// - `$group`: the name of the signal, with numbers replaced by placeholders. For `ADC2_CH3` this
|
||||
/// is `ADCn_CHm`.
|
||||
/// - `$number`: the numbers extracted from `$signal`.
|
||||
/// - `$gpio`: the name of the GPIO.
|
||||
///
|
||||
/// Example data:
|
||||
/// - `(RTC_GPIO15, GPIO12)`
|
||||
/// - `((RTC_GPIO15, RTC_GPIOn, 15), GPIO12)`
|
||||
///
|
||||
/// The expanded syntax is only available when the signal has at least one numbered component.
|
||||
#[macro_export]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
macro_rules! for_each_lp_function {
|
||||
($($pattern:tt => $code:tt;)*) => {
|
||||
macro_rules! _for_each_inner { $(($pattern) => $code;)* ($other : tt) => {} }
|
||||
@ -612,6 +694,7 @@ macro_rules! for_each_lp_function {
|
||||
};
|
||||
}
|
||||
#[macro_export]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
macro_rules! if_pin_is_type {
|
||||
(GPIO0, Input, $then_tt:tt else $else_tt:tt) => {
|
||||
$then_tt
|
||||
@ -912,6 +995,7 @@ macro_rules! if_pin_is_type {
|
||||
};
|
||||
}
|
||||
#[macro_export]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
#[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) => {
|
||||
@ -1027,6 +1111,7 @@ macro_rules! impl_for_pin_type {
|
||||
};
|
||||
}
|
||||
#[macro_export]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
macro_rules! define_io_mux_signals {
|
||||
() => {
|
||||
#[allow(non_camel_case_types, clippy::upper_case_acronyms)]
|
||||
@ -1436,6 +1521,7 @@ macro_rules! define_io_mux_signals {
|
||||
}
|
||||
#[macro_export]
|
||||
#[expect(clippy::crate_in_macro_def)]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
macro_rules! define_io_mux_reg {
|
||||
() => {
|
||||
pub(crate) fn io_mux_reg(gpio_num: u8) -> &'static crate::pac::io_mux::GPIO0 {
|
||||
|
@ -1,3 +1,6 @@
|
||||
// Do NOT edit this file directly. Make your changes to esp-metadata,
|
||||
// then run `cargo xtask update-metadata`.
|
||||
|
||||
/// The name of the chip as `&str`
|
||||
///
|
||||
/// # Example
|
||||
@ -8,6 +11,7 @@
|
||||
#[doc = concat!("assert_eq!(chip_name, ", chip!(), ")")]
|
||||
/// ```
|
||||
#[macro_export]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
macro_rules! chip {
|
||||
() => {
|
||||
"esp32c2"
|
||||
@ -15,6 +19,7 @@ macro_rules! chip {
|
||||
}
|
||||
/// The properties of this chip and its drivers.
|
||||
#[macro_export]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
macro_rules! property {
|
||||
("chip") => {
|
||||
"esp32c2"
|
||||
@ -145,12 +150,30 @@ macro_rules! property {
|
||||
}
|
||||
/// Macro to get the address range of the given memory region.
|
||||
#[macro_export]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
macro_rules! memory_range {
|
||||
("DRAM") => {
|
||||
1070202880..1070465024
|
||||
};
|
||||
}
|
||||
/// This macro can be used to generate code for each peripheral instance of the I2C master driver.
|
||||
///
|
||||
/// For an explanation on the general syntax, as well as usage of individual/repeated
|
||||
/// matchers, refer to [the crate-level documentation][crate#for_each-macros].
|
||||
///
|
||||
/// This macro has one option for its "Individual matcher" case:
|
||||
///
|
||||
/// Syntax: `($instance:ident, $sys:ident, $scl:ident, $sda:ident)`
|
||||
///
|
||||
/// Macro fragments:
|
||||
///
|
||||
/// - `$instance`: the name of the I2C instance
|
||||
/// - `$sys`: the name of the instance as it is in the `esp_hal::system::Peripheral` enum.
|
||||
/// - `$scl`, `$sda`: peripheral signal names.
|
||||
///
|
||||
/// Example data: `(I2C0, I2cExt0, I2CEXT0_SCL, I2CEXT0_SDA)`
|
||||
#[macro_export]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
macro_rules! for_each_i2c_master {
|
||||
($($pattern:tt => $code:tt;)*) => {
|
||||
macro_rules! _for_each_inner { $(($pattern) => $code;)* ($other : tt) => {} }
|
||||
@ -158,7 +181,24 @@ macro_rules! for_each_i2c_master {
|
||||
_for_each_inner!((all(I2C0, I2cExt0, I2CEXT0_SCL, I2CEXT0_SDA)));
|
||||
};
|
||||
}
|
||||
/// This macro can be used to generate code for each peripheral instance of the UART driver.
|
||||
///
|
||||
/// For an explanation on the general syntax, as well as usage of individual/repeated
|
||||
/// matchers, refer to [the crate-level documentation][crate#for_each-macros].
|
||||
///
|
||||
/// This macro has one option for its "Individual matcher" case:
|
||||
///
|
||||
/// Syntax: `($instance:ident, $sys:ident, $rx:ident, $tx:ident, $cts:ident, $rts:ident)`
|
||||
///
|
||||
/// Macro fragments:
|
||||
///
|
||||
/// - `$instance`: the name of the UART instance
|
||||
/// - `$sys`: the name of the instance as it is in the `esp_hal::system::Peripheral` enum.
|
||||
/// - `$rx`, `$tx`, `$cts`, `$rts`: signal names.
|
||||
///
|
||||
/// Example data: `(UART0, Uart0, U0RXD, U0TXD, U0CTS, U0RTS)`
|
||||
#[macro_export]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
macro_rules! for_each_uart {
|
||||
($($pattern:tt => $code:tt;)*) => {
|
||||
macro_rules! _for_each_inner { $(($pattern) => $code;)* ($other : tt) => {} }
|
||||
@ -168,7 +208,29 @@ macro_rules! for_each_uart {
|
||||
U1RXD, U1TXD, U1CTS, U1RTS)));
|
||||
};
|
||||
}
|
||||
/// This macro can be used to generate code for each peripheral instance of the SPI master driver.
|
||||
///
|
||||
/// For an explanation on the general syntax, as well as usage of individual/repeated
|
||||
/// matchers, refer to [the crate-level documentation][crate#for_each-macros].
|
||||
///
|
||||
/// This macro has one option for its "Individual matcher" case:
|
||||
///
|
||||
/// Syntax: `($instance:ident, $sys:ident, $sclk:ident, [$($cs:ident),*] [$($sio:ident),*
|
||||
/// $($is_qspi:iteral)?])`
|
||||
///
|
||||
/// Macro fragments:
|
||||
///
|
||||
/// - `$instance`: the name of the SPI instance
|
||||
/// - `$sys`: the name of the instance as it is in the `esp_hal::system::Peripheral` enum.
|
||||
/// - `$cs`, `$sio`: chip select and SIO signal names.
|
||||
/// - `$is_qspi`: a `true` literal present if the SPI instance supports QSPI.
|
||||
///
|
||||
/// Example data:
|
||||
/// - `(SPI2, Spi2, FSPICLK [FSPICS0, FSPICS1, FSPICS2, FSPICS3, FSPICS4, FSPICS5] [FSPID, FSPIQ,
|
||||
/// FSPIWP, FSPIHD, FSPIIO4, FSPIIO5, FSPIIO6, FSPIIO7], true)`
|
||||
/// - `(SPI3, Spi3, SPI3_CLK [SPI3_CS0, SPI3_CS1, SPI3_CS2] [SPI3_D, SPI3_Q])`
|
||||
#[macro_export]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
macro_rules! for_each_spi_master {
|
||||
($($pattern:tt => $code:tt;)*) => {
|
||||
macro_rules! _for_each_inner { $(($pattern) => $code;)* ($other : tt) => {} }
|
||||
@ -178,7 +240,24 @@ macro_rules! for_each_spi_master {
|
||||
FSPICS4, FSPICS5] [FSPID, FSPIQ, FSPIWP, FSPIHD], true)));
|
||||
};
|
||||
}
|
||||
/// This macro can be used to generate code for each peripheral instance of the SPI slave driver.
|
||||
///
|
||||
/// For an explanation on the general syntax, as well as usage of individual/repeated
|
||||
/// matchers, refer to [the crate-level documentation][crate#for_each-macros].
|
||||
///
|
||||
/// This macro has one option for its "Individual matcher" case:
|
||||
///
|
||||
/// Syntax: `($instance:ident, $sys:ident, $sclk:ident, $mosi:ident, $miso:ident, $cs:ident)`
|
||||
///
|
||||
/// Macro fragments:
|
||||
///
|
||||
/// - `$instance`: the name of the I2C instance
|
||||
/// - `$sys`: the name of the instance as it is in the `esp_hal::system::Peripheral` enum.
|
||||
/// - `$mosi`, `$miso`, `$cs`: signal names.
|
||||
///
|
||||
/// Example data: `(SPI2, Spi2, FSPICLK, FSPID, FSPIQ, FSPICS0)`
|
||||
#[macro_export]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
macro_rules! for_each_spi_slave {
|
||||
($($pattern:tt => $code:tt;)*) => {
|
||||
macro_rules! _for_each_inner { $(($pattern) => $code;)* ($other : tt) => {} }
|
||||
@ -187,6 +266,7 @@ macro_rules! for_each_spi_slave {
|
||||
};
|
||||
}
|
||||
#[macro_export]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
macro_rules! for_each_peripheral {
|
||||
($($pattern:tt => $code:tt;)*) => {
|
||||
macro_rules! _for_each_inner { $(($pattern) => $code;)* ($other : tt) => {} }
|
||||
@ -264,56 +344,32 @@ macro_rules! for_each_peripheral {
|
||||
(unstable))));
|
||||
};
|
||||
}
|
||||
/// This macro can be used to generate code for each GPIOn instance.
|
||||
/// This macro can be used to generate code for each `GPIOn` instance.
|
||||
///
|
||||
/// The basic syntax of this macro looks like a macro definition with two distinct syntax options:
|
||||
/// For an explanation on the general syntax, as well as usage of individual/repeated
|
||||
/// matchers, refer to [the crate-level documentation][crate#for_each-macros].
|
||||
///
|
||||
/// ```rust, no_run
|
||||
/// for_each_gpio! {
|
||||
/// // Individual matcher, invoked separately for each GPIO
|
||||
/// ( <match arm> ) => { /* some code */ };
|
||||
/// This macro has one option for its "Individual matcher" case:
|
||||
///
|
||||
/// // Repeated matcher, invoked once with all GPIOs
|
||||
/// ( all $( (<individual match syntax>) ),* ) => { /* some code */ };
|
||||
/// }
|
||||
/// ```
|
||||
/// Syntax: `($n:literal, $gpio:ident ($($digital_input_function:ident =>
|
||||
/// $digital_input_signal:ident)*) ($($digital_output_function:ident =>
|
||||
/// $digital_output_signal:ident)*) ($($pin_attribute:ident)*))`
|
||||
///
|
||||
/// You can specify any number of matchers.
|
||||
/// Macro fragments:
|
||||
///
|
||||
/// ## Using the individual matcher
|
||||
/// - `$n`: the number of the GPIO. For `GPIO0`, `$n` is 0.
|
||||
/// - `$gpio`: the name of the GPIO.
|
||||
/// - `$digital_input_function`: the number of the digital function, as an identifier (i.e. for
|
||||
/// function 0 this is `_0`).
|
||||
/// - `$digital_input_function`: the name of the digital function, as an identifier.
|
||||
/// - `$digital_output_function`: the number of the digital function, as an identifier (i.e. for
|
||||
/// function 0 this is `_0`).
|
||||
/// - `$digital_output_function`: the name of the digital function, as an identifier.
|
||||
/// - `$pin_attribute`: `Input` and/or `Output`, marks the possible directions of the GPIO.
|
||||
///
|
||||
/// In this use case, each GPIO's data is individually passed through the macro. This can be used to
|
||||
/// generate code for each GPIO separately, allowing specializing the implementation where needed.
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// for_each_gpio! {
|
||||
/// // Example data: `(0, GPIO0 (_5 => EMAC_TX_CLK) (_1 => CLK_OUT1 _5 => EMAC_TX_CLK) (Input Output))`
|
||||
/// ($n:literal, $gpio:ident ($($digital_input_function:ident => $digital_input_signal:ident)*) ($($digital_output_function:ident => $digital_output_signal:ident)*) ($($pin_attribute:ident)*)) => { /* some code */ };
|
||||
///
|
||||
/// // You can create matchers with data filled in. This example will specifically match GPIO2
|
||||
/// ($n:literal, GPIO2 $input_af:tt $output_af:tt $attributes:tt) => { /* Additional case only for GPIO2 */ };
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// ## Repeated matcher
|
||||
///
|
||||
/// With this option, all GPIO data is passed through the macro all at once. This form can be used
|
||||
/// to, for example, generate struct fields.
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// // Example usage to create a struct containing all GPIOs:
|
||||
/// for_each_gpio! {
|
||||
/// (all $( ($n:literal, $gpio:ident $_af_ins:tt $_af_outs:tt $_attrs:tt) ),*) => {
|
||||
/// struct Gpios {
|
||||
/// $(
|
||||
/// #[doc = concat!(" The ", stringify!($n), "th GPIO pin")]
|
||||
/// pub $gpio: Gpio<$n>,
|
||||
/// )*
|
||||
/// }
|
||||
/// };
|
||||
/// }
|
||||
/// ```
|
||||
/// Example data: `(0, GPIO0 (_5 => EMAC_TX_CLK) (_1 => CLK_OUT1 _5 => EMAC_TX_CLK) (Input Output))`
|
||||
#[macro_export]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
macro_rules! for_each_gpio {
|
||||
($($pattern:tt => $code:tt;)*) => {
|
||||
macro_rules! _for_each_inner { $(($pattern) => $code;)* ($other : tt) => {} }
|
||||
@ -354,7 +410,7 @@ macro_rules! for_each_gpio {
|
||||
/// This macro can be used to generate code for each analog function of each GPIO.
|
||||
///
|
||||
/// For an explanation on the general syntax, as well as usage of individual/repeated
|
||||
/// matchers, refer to [for_each_gpio].
|
||||
/// matchers, refer to [the crate-level documentation][crate#for_each-macros].
|
||||
///
|
||||
/// This macro has two options for its "Individual matcher" case:
|
||||
///
|
||||
@ -363,8 +419,21 @@ macro_rules! for_each_gpio {
|
||||
/// where you need the number(s) of a signal, or the general group to which the signal belongs.
|
||||
/// For example, in case of `ADC2_CH3` the expanded form looks like `(ADC2_CH3, ADCn_CHm, 2, 3)`.
|
||||
///
|
||||
/// The expanded signal are only available when the signal has at least one numbered component.
|
||||
/// Macro fragments:
|
||||
///
|
||||
/// - `$signal`: the name of the signal.
|
||||
/// - `$group`: the name of the signal, with numbers replaced by placeholders. For `ADC2_CH3` this
|
||||
/// is `ADCn_CHm`.
|
||||
/// - `$number`: the numbers extracted from `$signal`.
|
||||
/// - `$gpio`: the name of the GPIO.
|
||||
///
|
||||
/// Example data:
|
||||
/// - `(ADC2_CH5, GPIO12)`
|
||||
/// - `((ADC2_CH5, ADCn_CHm, 2, 5), GPIO12)`
|
||||
///
|
||||
/// The expanded syntax is only available when the signal has at least one numbered component.
|
||||
#[macro_export]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
macro_rules! for_each_analog_function {
|
||||
($($pattern:tt => $code:tt;)*) => {
|
||||
macro_rules! _for_each_inner { $(($pattern) => $code;)* ($other : tt) => {} }
|
||||
@ -384,7 +453,7 @@ macro_rules! for_each_analog_function {
|
||||
/// This macro can be used to generate code for each LP/RTC function of each GPIO.
|
||||
///
|
||||
/// For an explanation on the general syntax, as well as usage of individual/repeated
|
||||
/// matchers, refer to [for_each_gpio].
|
||||
/// matchers, refer to [the crate-level documentation][crate#for_each-macros].
|
||||
///
|
||||
/// This macro has two options for its "Individual matcher" case:
|
||||
///
|
||||
@ -394,8 +463,21 @@ macro_rules! for_each_analog_function {
|
||||
/// For example, in case of `SAR_I2C_SCL_1` the expanded form looks like `(SAR_I2C_SCL_1,
|
||||
/// SAR_I2C_SCL_n, 1)`.
|
||||
///
|
||||
/// The expanded signal are only available when the signal has at least one numbered component.
|
||||
/// Macro fragments:
|
||||
///
|
||||
/// - `$signal`: the name of the signal.
|
||||
/// - `$group`: the name of the signal, with numbers replaced by placeholders. For `ADC2_CH3` this
|
||||
/// is `ADCn_CHm`.
|
||||
/// - `$number`: the numbers extracted from `$signal`.
|
||||
/// - `$gpio`: the name of the GPIO.
|
||||
///
|
||||
/// Example data:
|
||||
/// - `(RTC_GPIO15, GPIO12)`
|
||||
/// - `((RTC_GPIO15, RTC_GPIOn, 15), GPIO12)`
|
||||
///
|
||||
/// The expanded syntax is only available when the signal has at least one numbered component.
|
||||
#[macro_export]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
macro_rules! for_each_lp_function {
|
||||
($($pattern:tt => $code:tt;)*) => {
|
||||
macro_rules! _for_each_inner { $(($pattern) => $code;)* ($other : tt) => {} }
|
||||
@ -415,6 +497,7 @@ macro_rules! for_each_lp_function {
|
||||
};
|
||||
}
|
||||
#[macro_export]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
macro_rules! if_pin_is_type {
|
||||
(GPIO0, Input, $then_tt:tt else $else_tt:tt) => {
|
||||
$then_tt
|
||||
@ -607,6 +690,7 @@ macro_rules! if_pin_is_type {
|
||||
};
|
||||
}
|
||||
#[macro_export]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
#[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) => {
|
||||
@ -680,6 +764,7 @@ macro_rules! impl_for_pin_type {
|
||||
};
|
||||
}
|
||||
#[macro_export]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
macro_rules! define_io_mux_signals {
|
||||
() => {
|
||||
#[allow(non_camel_case_types, clippy::upper_case_acronyms)]
|
||||
@ -797,6 +882,7 @@ macro_rules! define_io_mux_signals {
|
||||
}
|
||||
#[macro_export]
|
||||
#[expect(clippy::crate_in_macro_def)]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
macro_rules! define_io_mux_reg {
|
||||
() => {
|
||||
pub(crate) fn io_mux_reg(gpio_num: u8) -> &'static crate::pac::io_mux::GPIO {
|
||||
|
@ -1,3 +1,6 @@
|
||||
// Do NOT edit this file directly. Make your changes to esp-metadata,
|
||||
// then run `cargo xtask update-metadata`.
|
||||
|
||||
/// The name of the chip as `&str`
|
||||
///
|
||||
/// # Example
|
||||
@ -8,6 +11,7 @@
|
||||
#[doc = concat!("assert_eq!(chip_name, ", chip!(), ")")]
|
||||
/// ```
|
||||
#[macro_export]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
macro_rules! chip {
|
||||
() => {
|
||||
"esp32c3"
|
||||
@ -15,6 +19,7 @@ macro_rules! chip {
|
||||
}
|
||||
/// The properties of this chip and its drivers.
|
||||
#[macro_export]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
macro_rules! property {
|
||||
("chip") => {
|
||||
"esp32c3"
|
||||
@ -157,12 +162,30 @@ macro_rules! property {
|
||||
}
|
||||
/// Macro to get the address range of the given memory region.
|
||||
#[macro_export]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
macro_rules! memory_range {
|
||||
("DRAM") => {
|
||||
1070071808..1070465024
|
||||
};
|
||||
}
|
||||
/// This macro can be used to generate code for each peripheral instance of the I2C master driver.
|
||||
///
|
||||
/// For an explanation on the general syntax, as well as usage of individual/repeated
|
||||
/// matchers, refer to [the crate-level documentation][crate#for_each-macros].
|
||||
///
|
||||
/// This macro has one option for its "Individual matcher" case:
|
||||
///
|
||||
/// Syntax: `($instance:ident, $sys:ident, $scl:ident, $sda:ident)`
|
||||
///
|
||||
/// Macro fragments:
|
||||
///
|
||||
/// - `$instance`: the name of the I2C instance
|
||||
/// - `$sys`: the name of the instance as it is in the `esp_hal::system::Peripheral` enum.
|
||||
/// - `$scl`, `$sda`: peripheral signal names.
|
||||
///
|
||||
/// Example data: `(I2C0, I2cExt0, I2CEXT0_SCL, I2CEXT0_SDA)`
|
||||
#[macro_export]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
macro_rules! for_each_i2c_master {
|
||||
($($pattern:tt => $code:tt;)*) => {
|
||||
macro_rules! _for_each_inner { $(($pattern) => $code;)* ($other : tt) => {} }
|
||||
@ -170,7 +193,24 @@ macro_rules! for_each_i2c_master {
|
||||
_for_each_inner!((all(I2C0, I2cExt0, I2CEXT0_SCL, I2CEXT0_SDA)));
|
||||
};
|
||||
}
|
||||
/// This macro can be used to generate code for each peripheral instance of the UART driver.
|
||||
///
|
||||
/// For an explanation on the general syntax, as well as usage of individual/repeated
|
||||
/// matchers, refer to [the crate-level documentation][crate#for_each-macros].
|
||||
///
|
||||
/// This macro has one option for its "Individual matcher" case:
|
||||
///
|
||||
/// Syntax: `($instance:ident, $sys:ident, $rx:ident, $tx:ident, $cts:ident, $rts:ident)`
|
||||
///
|
||||
/// Macro fragments:
|
||||
///
|
||||
/// - `$instance`: the name of the UART instance
|
||||
/// - `$sys`: the name of the instance as it is in the `esp_hal::system::Peripheral` enum.
|
||||
/// - `$rx`, `$tx`, `$cts`, `$rts`: signal names.
|
||||
///
|
||||
/// Example data: `(UART0, Uart0, U0RXD, U0TXD, U0CTS, U0RTS)`
|
||||
#[macro_export]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
macro_rules! for_each_uart {
|
||||
($($pattern:tt => $code:tt;)*) => {
|
||||
macro_rules! _for_each_inner { $(($pattern) => $code;)* ($other : tt) => {} }
|
||||
@ -180,7 +220,29 @@ macro_rules! for_each_uart {
|
||||
U1RXD, U1TXD, U1CTS, U1RTS)));
|
||||
};
|
||||
}
|
||||
/// This macro can be used to generate code for each peripheral instance of the SPI master driver.
|
||||
///
|
||||
/// For an explanation on the general syntax, as well as usage of individual/repeated
|
||||
/// matchers, refer to [the crate-level documentation][crate#for_each-macros].
|
||||
///
|
||||
/// This macro has one option for its "Individual matcher" case:
|
||||
///
|
||||
/// Syntax: `($instance:ident, $sys:ident, $sclk:ident, [$($cs:ident),*] [$($sio:ident),*
|
||||
/// $($is_qspi:iteral)?])`
|
||||
///
|
||||
/// Macro fragments:
|
||||
///
|
||||
/// - `$instance`: the name of the SPI instance
|
||||
/// - `$sys`: the name of the instance as it is in the `esp_hal::system::Peripheral` enum.
|
||||
/// - `$cs`, `$sio`: chip select and SIO signal names.
|
||||
/// - `$is_qspi`: a `true` literal present if the SPI instance supports QSPI.
|
||||
///
|
||||
/// Example data:
|
||||
/// - `(SPI2, Spi2, FSPICLK [FSPICS0, FSPICS1, FSPICS2, FSPICS3, FSPICS4, FSPICS5] [FSPID, FSPIQ,
|
||||
/// FSPIWP, FSPIHD, FSPIIO4, FSPIIO5, FSPIIO6, FSPIIO7], true)`
|
||||
/// - `(SPI3, Spi3, SPI3_CLK [SPI3_CS0, SPI3_CS1, SPI3_CS2] [SPI3_D, SPI3_Q])`
|
||||
#[macro_export]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
macro_rules! for_each_spi_master {
|
||||
($($pattern:tt => $code:tt;)*) => {
|
||||
macro_rules! _for_each_inner { $(($pattern) => $code;)* ($other : tt) => {} }
|
||||
@ -190,7 +252,24 @@ macro_rules! for_each_spi_master {
|
||||
FSPICS4, FSPICS5] [FSPID, FSPIQ, FSPIWP, FSPIHD], true)));
|
||||
};
|
||||
}
|
||||
/// This macro can be used to generate code for each peripheral instance of the SPI slave driver.
|
||||
///
|
||||
/// For an explanation on the general syntax, as well as usage of individual/repeated
|
||||
/// matchers, refer to [the crate-level documentation][crate#for_each-macros].
|
||||
///
|
||||
/// This macro has one option for its "Individual matcher" case:
|
||||
///
|
||||
/// Syntax: `($instance:ident, $sys:ident, $sclk:ident, $mosi:ident, $miso:ident, $cs:ident)`
|
||||
///
|
||||
/// Macro fragments:
|
||||
///
|
||||
/// - `$instance`: the name of the I2C instance
|
||||
/// - `$sys`: the name of the instance as it is in the `esp_hal::system::Peripheral` enum.
|
||||
/// - `$mosi`, `$miso`, `$cs`: signal names.
|
||||
///
|
||||
/// Example data: `(SPI2, Spi2, FSPICLK, FSPID, FSPIQ, FSPICS0)`
|
||||
#[macro_export]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
macro_rules! for_each_spi_slave {
|
||||
($($pattern:tt => $code:tt;)*) => {
|
||||
macro_rules! _for_each_inner { $(($pattern) => $code;)* ($other : tt) => {} }
|
||||
@ -199,6 +278,7 @@ macro_rules! for_each_spi_slave {
|
||||
};
|
||||
}
|
||||
#[macro_export]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
macro_rules! for_each_peripheral {
|
||||
($($pattern:tt => $code:tt;)*) => {
|
||||
macro_rules! _for_each_inner { $(($pattern) => $code;)* ($other : tt) => {} }
|
||||
@ -289,56 +369,32 @@ macro_rules! for_each_peripheral {
|
||||
(unstable))));
|
||||
};
|
||||
}
|
||||
/// This macro can be used to generate code for each GPIOn instance.
|
||||
/// This macro can be used to generate code for each `GPIOn` instance.
|
||||
///
|
||||
/// The basic syntax of this macro looks like a macro definition with two distinct syntax options:
|
||||
/// For an explanation on the general syntax, as well as usage of individual/repeated
|
||||
/// matchers, refer to [the crate-level documentation][crate#for_each-macros].
|
||||
///
|
||||
/// ```rust, no_run
|
||||
/// for_each_gpio! {
|
||||
/// // Individual matcher, invoked separately for each GPIO
|
||||
/// ( <match arm> ) => { /* some code */ };
|
||||
/// This macro has one option for its "Individual matcher" case:
|
||||
///
|
||||
/// // Repeated matcher, invoked once with all GPIOs
|
||||
/// ( all $( (<individual match syntax>) ),* ) => { /* some code */ };
|
||||
/// }
|
||||
/// ```
|
||||
/// Syntax: `($n:literal, $gpio:ident ($($digital_input_function:ident =>
|
||||
/// $digital_input_signal:ident)*) ($($digital_output_function:ident =>
|
||||
/// $digital_output_signal:ident)*) ($($pin_attribute:ident)*))`
|
||||
///
|
||||
/// You can specify any number of matchers.
|
||||
/// Macro fragments:
|
||||
///
|
||||
/// ## Using the individual matcher
|
||||
/// - `$n`: the number of the GPIO. For `GPIO0`, `$n` is 0.
|
||||
/// - `$gpio`: the name of the GPIO.
|
||||
/// - `$digital_input_function`: the number of the digital function, as an identifier (i.e. for
|
||||
/// function 0 this is `_0`).
|
||||
/// - `$digital_input_function`: the name of the digital function, as an identifier.
|
||||
/// - `$digital_output_function`: the number of the digital function, as an identifier (i.e. for
|
||||
/// function 0 this is `_0`).
|
||||
/// - `$digital_output_function`: the name of the digital function, as an identifier.
|
||||
/// - `$pin_attribute`: `Input` and/or `Output`, marks the possible directions of the GPIO.
|
||||
///
|
||||
/// In this use case, each GPIO's data is individually passed through the macro. This can be used to
|
||||
/// generate code for each GPIO separately, allowing specializing the implementation where needed.
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// for_each_gpio! {
|
||||
/// // Example data: `(0, GPIO0 (_5 => EMAC_TX_CLK) (_1 => CLK_OUT1 _5 => EMAC_TX_CLK) (Input Output))`
|
||||
/// ($n:literal, $gpio:ident ($($digital_input_function:ident => $digital_input_signal:ident)*) ($($digital_output_function:ident => $digital_output_signal:ident)*) ($($pin_attribute:ident)*)) => { /* some code */ };
|
||||
///
|
||||
/// // You can create matchers with data filled in. This example will specifically match GPIO2
|
||||
/// ($n:literal, GPIO2 $input_af:tt $output_af:tt $attributes:tt) => { /* Additional case only for GPIO2 */ };
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// ## Repeated matcher
|
||||
///
|
||||
/// With this option, all GPIO data is passed through the macro all at once. This form can be used
|
||||
/// to, for example, generate struct fields.
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// // Example usage to create a struct containing all GPIOs:
|
||||
/// for_each_gpio! {
|
||||
/// (all $( ($n:literal, $gpio:ident $_af_ins:tt $_af_outs:tt $_attrs:tt) ),*) => {
|
||||
/// struct Gpios {
|
||||
/// $(
|
||||
/// #[doc = concat!(" The ", stringify!($n), "th GPIO pin")]
|
||||
/// pub $gpio: Gpio<$n>,
|
||||
/// )*
|
||||
/// }
|
||||
/// };
|
||||
/// }
|
||||
/// ```
|
||||
/// Example data: `(0, GPIO0 (_5 => EMAC_TX_CLK) (_1 => CLK_OUT1 _5 => EMAC_TX_CLK) (Input Output))`
|
||||
#[macro_export]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
macro_rules! for_each_gpio {
|
||||
($($pattern:tt => $code:tt;)*) => {
|
||||
macro_rules! _for_each_inner { $(($pattern) => $code;)* ($other : tt) => {} }
|
||||
@ -380,7 +436,7 @@ macro_rules! for_each_gpio {
|
||||
/// This macro can be used to generate code for each analog function of each GPIO.
|
||||
///
|
||||
/// For an explanation on the general syntax, as well as usage of individual/repeated
|
||||
/// matchers, refer to [for_each_gpio].
|
||||
/// matchers, refer to [the crate-level documentation][crate#for_each-macros].
|
||||
///
|
||||
/// This macro has two options for its "Individual matcher" case:
|
||||
///
|
||||
@ -389,8 +445,21 @@ macro_rules! for_each_gpio {
|
||||
/// where you need the number(s) of a signal, or the general group to which the signal belongs.
|
||||
/// For example, in case of `ADC2_CH3` the expanded form looks like `(ADC2_CH3, ADCn_CHm, 2, 3)`.
|
||||
///
|
||||
/// The expanded signal are only available when the signal has at least one numbered component.
|
||||
/// Macro fragments:
|
||||
///
|
||||
/// - `$signal`: the name of the signal.
|
||||
/// - `$group`: the name of the signal, with numbers replaced by placeholders. For `ADC2_CH3` this
|
||||
/// is `ADCn_CHm`.
|
||||
/// - `$number`: the numbers extracted from `$signal`.
|
||||
/// - `$gpio`: the name of the GPIO.
|
||||
///
|
||||
/// Example data:
|
||||
/// - `(ADC2_CH5, GPIO12)`
|
||||
/// - `((ADC2_CH5, ADCn_CHm, 2, 5), GPIO12)`
|
||||
///
|
||||
/// The expanded syntax is only available when the signal has at least one numbered component.
|
||||
#[macro_export]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
macro_rules! for_each_analog_function {
|
||||
($($pattern:tt => $code:tt;)*) => {
|
||||
macro_rules! _for_each_inner { $(($pattern) => $code;)* ($other : tt) => {} }
|
||||
@ -413,7 +482,7 @@ macro_rules! for_each_analog_function {
|
||||
/// This macro can be used to generate code for each LP/RTC function of each GPIO.
|
||||
///
|
||||
/// For an explanation on the general syntax, as well as usage of individual/repeated
|
||||
/// matchers, refer to [for_each_gpio].
|
||||
/// matchers, refer to [the crate-level documentation][crate#for_each-macros].
|
||||
///
|
||||
/// This macro has two options for its "Individual matcher" case:
|
||||
///
|
||||
@ -423,8 +492,21 @@ macro_rules! for_each_analog_function {
|
||||
/// For example, in case of `SAR_I2C_SCL_1` the expanded form looks like `(SAR_I2C_SCL_1,
|
||||
/// SAR_I2C_SCL_n, 1)`.
|
||||
///
|
||||
/// The expanded signal are only available when the signal has at least one numbered component.
|
||||
/// Macro fragments:
|
||||
///
|
||||
/// - `$signal`: the name of the signal.
|
||||
/// - `$group`: the name of the signal, with numbers replaced by placeholders. For `ADC2_CH3` this
|
||||
/// is `ADCn_CHm`.
|
||||
/// - `$number`: the numbers extracted from `$signal`.
|
||||
/// - `$gpio`: the name of the GPIO.
|
||||
///
|
||||
/// Example data:
|
||||
/// - `(RTC_GPIO15, GPIO12)`
|
||||
/// - `((RTC_GPIO15, RTC_GPIOn, 15), GPIO12)`
|
||||
///
|
||||
/// The expanded syntax is only available when the signal has at least one numbered component.
|
||||
#[macro_export]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
macro_rules! for_each_lp_function {
|
||||
($($pattern:tt => $code:tt;)*) => {
|
||||
macro_rules! _for_each_inner { $(($pattern) => $code;)* ($other : tt) => {} }
|
||||
@ -444,6 +526,7 @@ macro_rules! for_each_lp_function {
|
||||
};
|
||||
}
|
||||
#[macro_export]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
macro_rules! if_pin_is_type {
|
||||
(GPIO0, Input, $then_tt:tt else $else_tt:tt) => {
|
||||
$then_tt
|
||||
@ -645,6 +728,7 @@ macro_rules! if_pin_is_type {
|
||||
};
|
||||
}
|
||||
#[macro_export]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
#[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) => {
|
||||
@ -721,6 +805,7 @@ macro_rules! impl_for_pin_type {
|
||||
};
|
||||
}
|
||||
#[macro_export]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
macro_rules! define_io_mux_signals {
|
||||
() => {
|
||||
#[allow(non_camel_case_types, clippy::upper_case_acronyms)]
|
||||
@ -864,6 +949,7 @@ macro_rules! define_io_mux_signals {
|
||||
}
|
||||
#[macro_export]
|
||||
#[expect(clippy::crate_in_macro_def)]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
macro_rules! define_io_mux_reg {
|
||||
() => {
|
||||
pub(crate) fn io_mux_reg(gpio_num: u8) -> &'static crate::pac::io_mux::GPIO {
|
||||
|
@ -1,3 +1,6 @@
|
||||
// Do NOT edit this file directly. Make your changes to esp-metadata,
|
||||
// then run `cargo xtask update-metadata`.
|
||||
|
||||
/// The name of the chip as `&str`
|
||||
///
|
||||
/// # Example
|
||||
@ -8,6 +11,7 @@
|
||||
#[doc = concat!("assert_eq!(chip_name, ", chip!(), ")")]
|
||||
/// ```
|
||||
#[macro_export]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
macro_rules! chip {
|
||||
() => {
|
||||
"esp32c6"
|
||||
@ -15,6 +19,7 @@ macro_rules! chip {
|
||||
}
|
||||
/// The properties of this chip and its drivers.
|
||||
#[macro_export]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
macro_rules! property {
|
||||
("chip") => {
|
||||
"esp32c6"
|
||||
@ -157,12 +162,30 @@ macro_rules! property {
|
||||
}
|
||||
/// Macro to get the address range of the given memory region.
|
||||
#[macro_export]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
macro_rules! memory_range {
|
||||
("DRAM") => {
|
||||
1082130432..1082654720
|
||||
};
|
||||
}
|
||||
/// This macro can be used to generate code for each peripheral instance of the I2C master driver.
|
||||
///
|
||||
/// For an explanation on the general syntax, as well as usage of individual/repeated
|
||||
/// matchers, refer to [the crate-level documentation][crate#for_each-macros].
|
||||
///
|
||||
/// This macro has one option for its "Individual matcher" case:
|
||||
///
|
||||
/// Syntax: `($instance:ident, $sys:ident, $scl:ident, $sda:ident)`
|
||||
///
|
||||
/// Macro fragments:
|
||||
///
|
||||
/// - `$instance`: the name of the I2C instance
|
||||
/// - `$sys`: the name of the instance as it is in the `esp_hal::system::Peripheral` enum.
|
||||
/// - `$scl`, `$sda`: peripheral signal names.
|
||||
///
|
||||
/// Example data: `(I2C0, I2cExt0, I2CEXT0_SCL, I2CEXT0_SDA)`
|
||||
#[macro_export]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
macro_rules! for_each_i2c_master {
|
||||
($($pattern:tt => $code:tt;)*) => {
|
||||
macro_rules! _for_each_inner { $(($pattern) => $code;)* ($other : tt) => {} }
|
||||
@ -170,7 +193,24 @@ macro_rules! for_each_i2c_master {
|
||||
_for_each_inner!((all(I2C0, I2cExt0, I2CEXT0_SCL, I2CEXT0_SDA)));
|
||||
};
|
||||
}
|
||||
/// This macro can be used to generate code for each peripheral instance of the UART driver.
|
||||
///
|
||||
/// For an explanation on the general syntax, as well as usage of individual/repeated
|
||||
/// matchers, refer to [the crate-level documentation][crate#for_each-macros].
|
||||
///
|
||||
/// This macro has one option for its "Individual matcher" case:
|
||||
///
|
||||
/// Syntax: `($instance:ident, $sys:ident, $rx:ident, $tx:ident, $cts:ident, $rts:ident)`
|
||||
///
|
||||
/// Macro fragments:
|
||||
///
|
||||
/// - `$instance`: the name of the UART instance
|
||||
/// - `$sys`: the name of the instance as it is in the `esp_hal::system::Peripheral` enum.
|
||||
/// - `$rx`, `$tx`, `$cts`, `$rts`: signal names.
|
||||
///
|
||||
/// Example data: `(UART0, Uart0, U0RXD, U0TXD, U0CTS, U0RTS)`
|
||||
#[macro_export]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
macro_rules! for_each_uart {
|
||||
($($pattern:tt => $code:tt;)*) => {
|
||||
macro_rules! _for_each_inner { $(($pattern) => $code;)* ($other : tt) => {} }
|
||||
@ -180,7 +220,29 @@ macro_rules! for_each_uart {
|
||||
U1RXD, U1TXD, U1CTS, U1RTS)));
|
||||
};
|
||||
}
|
||||
/// This macro can be used to generate code for each peripheral instance of the SPI master driver.
|
||||
///
|
||||
/// For an explanation on the general syntax, as well as usage of individual/repeated
|
||||
/// matchers, refer to [the crate-level documentation][crate#for_each-macros].
|
||||
///
|
||||
/// This macro has one option for its "Individual matcher" case:
|
||||
///
|
||||
/// Syntax: `($instance:ident, $sys:ident, $sclk:ident, [$($cs:ident),*] [$($sio:ident),*
|
||||
/// $($is_qspi:iteral)?])`
|
||||
///
|
||||
/// Macro fragments:
|
||||
///
|
||||
/// - `$instance`: the name of the SPI instance
|
||||
/// - `$sys`: the name of the instance as it is in the `esp_hal::system::Peripheral` enum.
|
||||
/// - `$cs`, `$sio`: chip select and SIO signal names.
|
||||
/// - `$is_qspi`: a `true` literal present if the SPI instance supports QSPI.
|
||||
///
|
||||
/// Example data:
|
||||
/// - `(SPI2, Spi2, FSPICLK [FSPICS0, FSPICS1, FSPICS2, FSPICS3, FSPICS4, FSPICS5] [FSPID, FSPIQ,
|
||||
/// FSPIWP, FSPIHD, FSPIIO4, FSPIIO5, FSPIIO6, FSPIIO7], true)`
|
||||
/// - `(SPI3, Spi3, SPI3_CLK [SPI3_CS0, SPI3_CS1, SPI3_CS2] [SPI3_D, SPI3_Q])`
|
||||
#[macro_export]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
macro_rules! for_each_spi_master {
|
||||
($($pattern:tt => $code:tt;)*) => {
|
||||
macro_rules! _for_each_inner { $(($pattern) => $code;)* ($other : tt) => {} }
|
||||
@ -190,7 +252,24 @@ macro_rules! for_each_spi_master {
|
||||
FSPICS4, FSPICS5] [FSPID, FSPIQ, FSPIWP, FSPIHD], true)));
|
||||
};
|
||||
}
|
||||
/// This macro can be used to generate code for each peripheral instance of the SPI slave driver.
|
||||
///
|
||||
/// For an explanation on the general syntax, as well as usage of individual/repeated
|
||||
/// matchers, refer to [the crate-level documentation][crate#for_each-macros].
|
||||
///
|
||||
/// This macro has one option for its "Individual matcher" case:
|
||||
///
|
||||
/// Syntax: `($instance:ident, $sys:ident, $sclk:ident, $mosi:ident, $miso:ident, $cs:ident)`
|
||||
///
|
||||
/// Macro fragments:
|
||||
///
|
||||
/// - `$instance`: the name of the I2C instance
|
||||
/// - `$sys`: the name of the instance as it is in the `esp_hal::system::Peripheral` enum.
|
||||
/// - `$mosi`, `$miso`, `$cs`: signal names.
|
||||
///
|
||||
/// Example data: `(SPI2, Spi2, FSPICLK, FSPID, FSPIQ, FSPICS0)`
|
||||
#[macro_export]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
macro_rules! for_each_spi_slave {
|
||||
($($pattern:tt => $code:tt;)*) => {
|
||||
macro_rules! _for_each_inner { $(($pattern) => $code;)* ($other : tt) => {} }
|
||||
@ -199,6 +278,7 @@ macro_rules! for_each_spi_slave {
|
||||
};
|
||||
}
|
||||
#[macro_export]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
macro_rules! for_each_peripheral {
|
||||
($($pattern:tt => $code:tt;)*) => {
|
||||
macro_rules! _for_each_inner { $(($pattern) => $code;)* ($other : tt) => {} }
|
||||
@ -344,56 +424,32 @@ macro_rules! for_each_peripheral {
|
||||
(unstable)), (MEM2MEM15 <= virtual() (unstable))));
|
||||
};
|
||||
}
|
||||
/// This macro can be used to generate code for each GPIOn instance.
|
||||
/// This macro can be used to generate code for each `GPIOn` instance.
|
||||
///
|
||||
/// The basic syntax of this macro looks like a macro definition with two distinct syntax options:
|
||||
/// For an explanation on the general syntax, as well as usage of individual/repeated
|
||||
/// matchers, refer to [the crate-level documentation][crate#for_each-macros].
|
||||
///
|
||||
/// ```rust, no_run
|
||||
/// for_each_gpio! {
|
||||
/// // Individual matcher, invoked separately for each GPIO
|
||||
/// ( <match arm> ) => { /* some code */ };
|
||||
/// This macro has one option for its "Individual matcher" case:
|
||||
///
|
||||
/// // Repeated matcher, invoked once with all GPIOs
|
||||
/// ( all $( (<individual match syntax>) ),* ) => { /* some code */ };
|
||||
/// }
|
||||
/// ```
|
||||
/// Syntax: `($n:literal, $gpio:ident ($($digital_input_function:ident =>
|
||||
/// $digital_input_signal:ident)*) ($($digital_output_function:ident =>
|
||||
/// $digital_output_signal:ident)*) ($($pin_attribute:ident)*))`
|
||||
///
|
||||
/// You can specify any number of matchers.
|
||||
/// Macro fragments:
|
||||
///
|
||||
/// ## Using the individual matcher
|
||||
/// - `$n`: the number of the GPIO. For `GPIO0`, `$n` is 0.
|
||||
/// - `$gpio`: the name of the GPIO.
|
||||
/// - `$digital_input_function`: the number of the digital function, as an identifier (i.e. for
|
||||
/// function 0 this is `_0`).
|
||||
/// - `$digital_input_function`: the name of the digital function, as an identifier.
|
||||
/// - `$digital_output_function`: the number of the digital function, as an identifier (i.e. for
|
||||
/// function 0 this is `_0`).
|
||||
/// - `$digital_output_function`: the name of the digital function, as an identifier.
|
||||
/// - `$pin_attribute`: `Input` and/or `Output`, marks the possible directions of the GPIO.
|
||||
///
|
||||
/// In this use case, each GPIO's data is individually passed through the macro. This can be used to
|
||||
/// generate code for each GPIO separately, allowing specializing the implementation where needed.
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// for_each_gpio! {
|
||||
/// // Example data: `(0, GPIO0 (_5 => EMAC_TX_CLK) (_1 => CLK_OUT1 _5 => EMAC_TX_CLK) (Input Output))`
|
||||
/// ($n:literal, $gpio:ident ($($digital_input_function:ident => $digital_input_signal:ident)*) ($($digital_output_function:ident => $digital_output_signal:ident)*) ($($pin_attribute:ident)*)) => { /* some code */ };
|
||||
///
|
||||
/// // You can create matchers with data filled in. This example will specifically match GPIO2
|
||||
/// ($n:literal, GPIO2 $input_af:tt $output_af:tt $attributes:tt) => { /* Additional case only for GPIO2 */ };
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// ## Repeated matcher
|
||||
///
|
||||
/// With this option, all GPIO data is passed through the macro all at once. This form can be used
|
||||
/// to, for example, generate struct fields.
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// // Example usage to create a struct containing all GPIOs:
|
||||
/// for_each_gpio! {
|
||||
/// (all $( ($n:literal, $gpio:ident $_af_ins:tt $_af_outs:tt $_attrs:tt) ),*) => {
|
||||
/// struct Gpios {
|
||||
/// $(
|
||||
/// #[doc = concat!(" The ", stringify!($n), "th GPIO pin")]
|
||||
/// pub $gpio: Gpio<$n>,
|
||||
/// )*
|
||||
/// }
|
||||
/// };
|
||||
/// }
|
||||
/// ```
|
||||
/// Example data: `(0, GPIO0 (_5 => EMAC_TX_CLK) (_1 => CLK_OUT1 _5 => EMAC_TX_CLK) (Input Output))`
|
||||
#[macro_export]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
macro_rules! for_each_gpio {
|
||||
($($pattern:tt => $code:tt;)*) => {
|
||||
macro_rules! _for_each_inner { $(($pattern) => $code;)* ($other : tt) => {} }
|
||||
@ -452,7 +508,7 @@ macro_rules! for_each_gpio {
|
||||
/// This macro can be used to generate code for each analog function of each GPIO.
|
||||
///
|
||||
/// For an explanation on the general syntax, as well as usage of individual/repeated
|
||||
/// matchers, refer to [for_each_gpio].
|
||||
/// matchers, refer to [the crate-level documentation][crate#for_each-macros].
|
||||
///
|
||||
/// This macro has two options for its "Individual matcher" case:
|
||||
///
|
||||
@ -461,8 +517,21 @@ macro_rules! for_each_gpio {
|
||||
/// where you need the number(s) of a signal, or the general group to which the signal belongs.
|
||||
/// For example, in case of `ADC2_CH3` the expanded form looks like `(ADC2_CH3, ADCn_CHm, 2, 3)`.
|
||||
///
|
||||
/// The expanded signal are only available when the signal has at least one numbered component.
|
||||
/// Macro fragments:
|
||||
///
|
||||
/// - `$signal`: the name of the signal.
|
||||
/// - `$group`: the name of the signal, with numbers replaced by placeholders. For `ADC2_CH3` this
|
||||
/// is `ADCn_CHm`.
|
||||
/// - `$number`: the numbers extracted from `$signal`.
|
||||
/// - `$gpio`: the name of the GPIO.
|
||||
///
|
||||
/// Example data:
|
||||
/// - `(ADC2_CH5, GPIO12)`
|
||||
/// - `((ADC2_CH5, ADCn_CHm, 2, 5), GPIO12)`
|
||||
///
|
||||
/// The expanded syntax is only available when the signal has at least one numbered component.
|
||||
#[macro_export]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
macro_rules! for_each_analog_function {
|
||||
($($pattern:tt => $code:tt;)*) => {
|
||||
macro_rules! _for_each_inner { $(($pattern) => $code;)* ($other : tt) => {} }
|
||||
@ -489,7 +558,7 @@ macro_rules! for_each_analog_function {
|
||||
/// This macro can be used to generate code for each LP/RTC function of each GPIO.
|
||||
///
|
||||
/// For an explanation on the general syntax, as well as usage of individual/repeated
|
||||
/// matchers, refer to [for_each_gpio].
|
||||
/// matchers, refer to [the crate-level documentation][crate#for_each-macros].
|
||||
///
|
||||
/// This macro has two options for its "Individual matcher" case:
|
||||
///
|
||||
@ -499,8 +568,21 @@ macro_rules! for_each_analog_function {
|
||||
/// For example, in case of `SAR_I2C_SCL_1` the expanded form looks like `(SAR_I2C_SCL_1,
|
||||
/// SAR_I2C_SCL_n, 1)`.
|
||||
///
|
||||
/// The expanded signal are only available when the signal has at least one numbered component.
|
||||
/// Macro fragments:
|
||||
///
|
||||
/// - `$signal`: the name of the signal.
|
||||
/// - `$group`: the name of the signal, with numbers replaced by placeholders. For `ADC2_CH3` this
|
||||
/// is `ADCn_CHm`.
|
||||
/// - `$number`: the numbers extracted from `$signal`.
|
||||
/// - `$gpio`: the name of the GPIO.
|
||||
///
|
||||
/// Example data:
|
||||
/// - `(RTC_GPIO15, GPIO12)`
|
||||
/// - `((RTC_GPIO15, RTC_GPIOn, 15), GPIO12)`
|
||||
///
|
||||
/// The expanded syntax is only available when the signal has at least one numbered component.
|
||||
#[macro_export]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
macro_rules! for_each_lp_function {
|
||||
($($pattern:tt => $code:tt;)*) => {
|
||||
macro_rules! _for_each_inner { $(($pattern) => $code;)* ($other : tt) => {} }
|
||||
@ -531,6 +613,7 @@ macro_rules! for_each_lp_function {
|
||||
};
|
||||
}
|
||||
#[macro_export]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
macro_rules! if_pin_is_type {
|
||||
(GPIO0, Input, $then_tt:tt else $else_tt:tt) => {
|
||||
$then_tt
|
||||
@ -813,6 +896,7 @@ macro_rules! if_pin_is_type {
|
||||
};
|
||||
}
|
||||
#[macro_export]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
#[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) => {
|
||||
@ -916,6 +1000,7 @@ macro_rules! impl_for_pin_type {
|
||||
};
|
||||
}
|
||||
#[macro_export]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
macro_rules! define_io_mux_signals {
|
||||
() => {
|
||||
#[allow(non_camel_case_types, clippy::upper_case_acronyms)]
|
||||
@ -1156,6 +1241,7 @@ macro_rules! define_io_mux_signals {
|
||||
}
|
||||
#[macro_export]
|
||||
#[expect(clippy::crate_in_macro_def)]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
macro_rules! define_io_mux_reg {
|
||||
() => {
|
||||
pub(crate) fn io_mux_reg(gpio_num: u8) -> &'static crate::pac::io_mux::GPIO {
|
||||
|
@ -1,3 +1,6 @@
|
||||
// Do NOT edit this file directly. Make your changes to esp-metadata,
|
||||
// then run `cargo xtask update-metadata`.
|
||||
|
||||
/// The name of the chip as `&str`
|
||||
///
|
||||
/// # Example
|
||||
@ -8,6 +11,7 @@
|
||||
#[doc = concat!("assert_eq!(chip_name, ", chip!(), ")")]
|
||||
/// ```
|
||||
#[macro_export]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
macro_rules! chip {
|
||||
() => {
|
||||
"esp32h2"
|
||||
@ -15,6 +19,7 @@ macro_rules! chip {
|
||||
}
|
||||
/// The properties of this chip and its drivers.
|
||||
#[macro_export]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
macro_rules! property {
|
||||
("chip") => {
|
||||
"esp32h2"
|
||||
@ -154,12 +159,30 @@ macro_rules! property {
|
||||
}
|
||||
/// Macro to get the address range of the given memory region.
|
||||
#[macro_export]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
macro_rules! memory_range {
|
||||
("DRAM") => {
|
||||
1082130432..1082458112
|
||||
};
|
||||
}
|
||||
/// This macro can be used to generate code for each peripheral instance of the I2C master driver.
|
||||
///
|
||||
/// For an explanation on the general syntax, as well as usage of individual/repeated
|
||||
/// matchers, refer to [the crate-level documentation][crate#for_each-macros].
|
||||
///
|
||||
/// This macro has one option for its "Individual matcher" case:
|
||||
///
|
||||
/// Syntax: `($instance:ident, $sys:ident, $scl:ident, $sda:ident)`
|
||||
///
|
||||
/// Macro fragments:
|
||||
///
|
||||
/// - `$instance`: the name of the I2C instance
|
||||
/// - `$sys`: the name of the instance as it is in the `esp_hal::system::Peripheral` enum.
|
||||
/// - `$scl`, `$sda`: peripheral signal names.
|
||||
///
|
||||
/// Example data: `(I2C0, I2cExt0, I2CEXT0_SCL, I2CEXT0_SDA)`
|
||||
#[macro_export]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
macro_rules! for_each_i2c_master {
|
||||
($($pattern:tt => $code:tt;)*) => {
|
||||
macro_rules! _for_each_inner { $(($pattern) => $code;)* ($other : tt) => {} }
|
||||
@ -169,7 +192,24 @@ macro_rules! for_each_i2c_master {
|
||||
I2CEXT1_SCL, I2CEXT1_SDA)));
|
||||
};
|
||||
}
|
||||
/// This macro can be used to generate code for each peripheral instance of the UART driver.
|
||||
///
|
||||
/// For an explanation on the general syntax, as well as usage of individual/repeated
|
||||
/// matchers, refer to [the crate-level documentation][crate#for_each-macros].
|
||||
///
|
||||
/// This macro has one option for its "Individual matcher" case:
|
||||
///
|
||||
/// Syntax: `($instance:ident, $sys:ident, $rx:ident, $tx:ident, $cts:ident, $rts:ident)`
|
||||
///
|
||||
/// Macro fragments:
|
||||
///
|
||||
/// - `$instance`: the name of the UART instance
|
||||
/// - `$sys`: the name of the instance as it is in the `esp_hal::system::Peripheral` enum.
|
||||
/// - `$rx`, `$tx`, `$cts`, `$rts`: signal names.
|
||||
///
|
||||
/// Example data: `(UART0, Uart0, U0RXD, U0TXD, U0CTS, U0RTS)`
|
||||
#[macro_export]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
macro_rules! for_each_uart {
|
||||
($($pattern:tt => $code:tt;)*) => {
|
||||
macro_rules! _for_each_inner { $(($pattern) => $code;)* ($other : tt) => {} }
|
||||
@ -179,7 +219,29 @@ macro_rules! for_each_uart {
|
||||
U1RXD, U1TXD, U1CTS, U1RTS)));
|
||||
};
|
||||
}
|
||||
/// This macro can be used to generate code for each peripheral instance of the SPI master driver.
|
||||
///
|
||||
/// For an explanation on the general syntax, as well as usage of individual/repeated
|
||||
/// matchers, refer to [the crate-level documentation][crate#for_each-macros].
|
||||
///
|
||||
/// This macro has one option for its "Individual matcher" case:
|
||||
///
|
||||
/// Syntax: `($instance:ident, $sys:ident, $sclk:ident, [$($cs:ident),*] [$($sio:ident),*
|
||||
/// $($is_qspi:iteral)?])`
|
||||
///
|
||||
/// Macro fragments:
|
||||
///
|
||||
/// - `$instance`: the name of the SPI instance
|
||||
/// - `$sys`: the name of the instance as it is in the `esp_hal::system::Peripheral` enum.
|
||||
/// - `$cs`, `$sio`: chip select and SIO signal names.
|
||||
/// - `$is_qspi`: a `true` literal present if the SPI instance supports QSPI.
|
||||
///
|
||||
/// Example data:
|
||||
/// - `(SPI2, Spi2, FSPICLK [FSPICS0, FSPICS1, FSPICS2, FSPICS3, FSPICS4, FSPICS5] [FSPID, FSPIQ,
|
||||
/// FSPIWP, FSPIHD, FSPIIO4, FSPIIO5, FSPIIO6, FSPIIO7], true)`
|
||||
/// - `(SPI3, Spi3, SPI3_CLK [SPI3_CS0, SPI3_CS1, SPI3_CS2] [SPI3_D, SPI3_Q])`
|
||||
#[macro_export]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
macro_rules! for_each_spi_master {
|
||||
($($pattern:tt => $code:tt;)*) => {
|
||||
macro_rules! _for_each_inner { $(($pattern) => $code;)* ($other : tt) => {} }
|
||||
@ -189,7 +251,24 @@ macro_rules! for_each_spi_master {
|
||||
FSPICS4, FSPICS5] [FSPID, FSPIQ, FSPIWP, FSPIHD], true)));
|
||||
};
|
||||
}
|
||||
/// This macro can be used to generate code for each peripheral instance of the SPI slave driver.
|
||||
///
|
||||
/// For an explanation on the general syntax, as well as usage of individual/repeated
|
||||
/// matchers, refer to [the crate-level documentation][crate#for_each-macros].
|
||||
///
|
||||
/// This macro has one option for its "Individual matcher" case:
|
||||
///
|
||||
/// Syntax: `($instance:ident, $sys:ident, $sclk:ident, $mosi:ident, $miso:ident, $cs:ident)`
|
||||
///
|
||||
/// Macro fragments:
|
||||
///
|
||||
/// - `$instance`: the name of the I2C instance
|
||||
/// - `$sys`: the name of the instance as it is in the `esp_hal::system::Peripheral` enum.
|
||||
/// - `$mosi`, `$miso`, `$cs`: signal names.
|
||||
///
|
||||
/// Example data: `(SPI2, Spi2, FSPICLK, FSPID, FSPIQ, FSPICS0)`
|
||||
#[macro_export]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
macro_rules! for_each_spi_slave {
|
||||
($($pattern:tt => $code:tt;)*) => {
|
||||
macro_rules! _for_each_inner { $(($pattern) => $code;)* ($other : tt) => {} }
|
||||
@ -198,6 +277,7 @@ macro_rules! for_each_spi_slave {
|
||||
};
|
||||
}
|
||||
#[macro_export]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
macro_rules! for_each_peripheral {
|
||||
($($pattern:tt => $code:tt;)*) => {
|
||||
macro_rules! _for_each_inner { $(($pattern) => $code;)* ($other : tt) => {} }
|
||||
@ -325,56 +405,32 @@ macro_rules! for_each_peripheral {
|
||||
virtual() (unstable))));
|
||||
};
|
||||
}
|
||||
/// This macro can be used to generate code for each GPIOn instance.
|
||||
/// This macro can be used to generate code for each `GPIOn` instance.
|
||||
///
|
||||
/// The basic syntax of this macro looks like a macro definition with two distinct syntax options:
|
||||
/// For an explanation on the general syntax, as well as usage of individual/repeated
|
||||
/// matchers, refer to [the crate-level documentation][crate#for_each-macros].
|
||||
///
|
||||
/// ```rust, no_run
|
||||
/// for_each_gpio! {
|
||||
/// // Individual matcher, invoked separately for each GPIO
|
||||
/// ( <match arm> ) => { /* some code */ };
|
||||
/// This macro has one option for its "Individual matcher" case:
|
||||
///
|
||||
/// // Repeated matcher, invoked once with all GPIOs
|
||||
/// ( all $( (<individual match syntax>) ),* ) => { /* some code */ };
|
||||
/// }
|
||||
/// ```
|
||||
/// Syntax: `($n:literal, $gpio:ident ($($digital_input_function:ident =>
|
||||
/// $digital_input_signal:ident)*) ($($digital_output_function:ident =>
|
||||
/// $digital_output_signal:ident)*) ($($pin_attribute:ident)*))`
|
||||
///
|
||||
/// You can specify any number of matchers.
|
||||
/// Macro fragments:
|
||||
///
|
||||
/// ## Using the individual matcher
|
||||
/// - `$n`: the number of the GPIO. For `GPIO0`, `$n` is 0.
|
||||
/// - `$gpio`: the name of the GPIO.
|
||||
/// - `$digital_input_function`: the number of the digital function, as an identifier (i.e. for
|
||||
/// function 0 this is `_0`).
|
||||
/// - `$digital_input_function`: the name of the digital function, as an identifier.
|
||||
/// - `$digital_output_function`: the number of the digital function, as an identifier (i.e. for
|
||||
/// function 0 this is `_0`).
|
||||
/// - `$digital_output_function`: the name of the digital function, as an identifier.
|
||||
/// - `$pin_attribute`: `Input` and/or `Output`, marks the possible directions of the GPIO.
|
||||
///
|
||||
/// In this use case, each GPIO's data is individually passed through the macro. This can be used to
|
||||
/// generate code for each GPIO separately, allowing specializing the implementation where needed.
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// for_each_gpio! {
|
||||
/// // Example data: `(0, GPIO0 (_5 => EMAC_TX_CLK) (_1 => CLK_OUT1 _5 => EMAC_TX_CLK) (Input Output))`
|
||||
/// ($n:literal, $gpio:ident ($($digital_input_function:ident => $digital_input_signal:ident)*) ($($digital_output_function:ident => $digital_output_signal:ident)*) ($($pin_attribute:ident)*)) => { /* some code */ };
|
||||
///
|
||||
/// // You can create matchers with data filled in. This example will specifically match GPIO2
|
||||
/// ($n:literal, GPIO2 $input_af:tt $output_af:tt $attributes:tt) => { /* Additional case only for GPIO2 */ };
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// ## Repeated matcher
|
||||
///
|
||||
/// With this option, all GPIO data is passed through the macro all at once. This form can be used
|
||||
/// to, for example, generate struct fields.
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// // Example usage to create a struct containing all GPIOs:
|
||||
/// for_each_gpio! {
|
||||
/// (all $( ($n:literal, $gpio:ident $_af_ins:tt $_af_outs:tt $_attrs:tt) ),*) => {
|
||||
/// struct Gpios {
|
||||
/// $(
|
||||
/// #[doc = concat!(" The ", stringify!($n), "th GPIO pin")]
|
||||
/// pub $gpio: Gpio<$n>,
|
||||
/// )*
|
||||
/// }
|
||||
/// };
|
||||
/// }
|
||||
/// ```
|
||||
/// Example data: `(0, GPIO0 (_5 => EMAC_TX_CLK) (_1 => CLK_OUT1 _5 => EMAC_TX_CLK) (Input Output))`
|
||||
#[macro_export]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
macro_rules! for_each_gpio {
|
||||
($($pattern:tt => $code:tt;)*) => {
|
||||
macro_rules! _for_each_inner { $(($pattern) => $code;)* ($other : tt) => {} }
|
||||
@ -414,7 +470,7 @@ macro_rules! for_each_gpio {
|
||||
/// This macro can be used to generate code for each analog function of each GPIO.
|
||||
///
|
||||
/// For an explanation on the general syntax, as well as usage of individual/repeated
|
||||
/// matchers, refer to [for_each_gpio].
|
||||
/// matchers, refer to [the crate-level documentation][crate#for_each-macros].
|
||||
///
|
||||
/// This macro has two options for its "Individual matcher" case:
|
||||
///
|
||||
@ -423,8 +479,21 @@ macro_rules! for_each_gpio {
|
||||
/// where you need the number(s) of a signal, or the general group to which the signal belongs.
|
||||
/// For example, in case of `ADC2_CH3` the expanded form looks like `(ADC2_CH3, ADCn_CHm, 2, 3)`.
|
||||
///
|
||||
/// The expanded signal are only available when the signal has at least one numbered component.
|
||||
/// Macro fragments:
|
||||
///
|
||||
/// - `$signal`: the name of the signal.
|
||||
/// - `$group`: the name of the signal, with numbers replaced by placeholders. For `ADC2_CH3` this
|
||||
/// is `ADCn_CHm`.
|
||||
/// - `$number`: the numbers extracted from `$signal`.
|
||||
/// - `$gpio`: the name of the GPIO.
|
||||
///
|
||||
/// Example data:
|
||||
/// - `(ADC2_CH5, GPIO12)`
|
||||
/// - `((ADC2_CH5, ADCn_CHm, 2, 5), GPIO12)`
|
||||
///
|
||||
/// The expanded syntax is only available when the signal has at least one numbered component.
|
||||
#[macro_export]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
macro_rules! for_each_analog_function {
|
||||
($($pattern:tt => $code:tt;)*) => {
|
||||
macro_rules! _for_each_inner { $(($pattern) => $code;)* ($other : tt) => {} }
|
||||
@ -450,7 +519,7 @@ macro_rules! for_each_analog_function {
|
||||
/// This macro can be used to generate code for each LP/RTC function of each GPIO.
|
||||
///
|
||||
/// For an explanation on the general syntax, as well as usage of individual/repeated
|
||||
/// matchers, refer to [for_each_gpio].
|
||||
/// matchers, refer to [the crate-level documentation][crate#for_each-macros].
|
||||
///
|
||||
/// This macro has two options for its "Individual matcher" case:
|
||||
///
|
||||
@ -460,8 +529,21 @@ macro_rules! for_each_analog_function {
|
||||
/// For example, in case of `SAR_I2C_SCL_1` the expanded form looks like `(SAR_I2C_SCL_1,
|
||||
/// SAR_I2C_SCL_n, 1)`.
|
||||
///
|
||||
/// The expanded signal are only available when the signal has at least one numbered component.
|
||||
/// Macro fragments:
|
||||
///
|
||||
/// - `$signal`: the name of the signal.
|
||||
/// - `$group`: the name of the signal, with numbers replaced by placeholders. For `ADC2_CH3` this
|
||||
/// is `ADCn_CHm`.
|
||||
/// - `$number`: the numbers extracted from `$signal`.
|
||||
/// - `$gpio`: the name of the GPIO.
|
||||
///
|
||||
/// Example data:
|
||||
/// - `(RTC_GPIO15, GPIO12)`
|
||||
/// - `((RTC_GPIO15, RTC_GPIOn, 15), GPIO12)`
|
||||
///
|
||||
/// The expanded syntax is only available when the signal has at least one numbered component.
|
||||
#[macro_export]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
macro_rules! for_each_lp_function {
|
||||
($($pattern:tt => $code:tt;)*) => {
|
||||
macro_rules! _for_each_inner { $(($pattern) => $code;)* ($other : tt) => {} }
|
||||
@ -469,6 +551,7 @@ macro_rules! for_each_lp_function {
|
||||
};
|
||||
}
|
||||
#[macro_export]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
macro_rules! if_pin_is_type {
|
||||
(GPIO0, Input, $then_tt:tt else $else_tt:tt) => {
|
||||
$then_tt
|
||||
@ -661,6 +744,7 @@ macro_rules! if_pin_is_type {
|
||||
};
|
||||
}
|
||||
#[macro_export]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
#[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) => {
|
||||
@ -734,6 +818,7 @@ macro_rules! impl_for_pin_type {
|
||||
};
|
||||
}
|
||||
#[macro_export]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
macro_rules! define_io_mux_signals {
|
||||
() => {
|
||||
#[allow(non_camel_case_types, clippy::upper_case_acronyms)]
|
||||
@ -927,6 +1012,7 @@ macro_rules! define_io_mux_signals {
|
||||
}
|
||||
#[macro_export]
|
||||
#[expect(clippy::crate_in_macro_def)]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
macro_rules! define_io_mux_reg {
|
||||
() => {
|
||||
pub(crate) fn io_mux_reg(gpio_num: u8) -> &'static crate::pac::io_mux::GPIO {
|
||||
|
@ -1,3 +1,6 @@
|
||||
// Do NOT edit this file directly. Make your changes to esp-metadata,
|
||||
// then run `cargo xtask update-metadata`.
|
||||
|
||||
/// The name of the chip as `&str`
|
||||
///
|
||||
/// # Example
|
||||
@ -8,6 +11,7 @@
|
||||
#[doc = concat!("assert_eq!(chip_name, ", chip!(), ")")]
|
||||
/// ```
|
||||
#[macro_export]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
macro_rules! chip {
|
||||
() => {
|
||||
"esp32s2"
|
||||
@ -15,6 +19,7 @@ macro_rules! chip {
|
||||
}
|
||||
/// The properties of this chip and its drivers.
|
||||
#[macro_export]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
macro_rules! property {
|
||||
("chip") => {
|
||||
"esp32s2"
|
||||
@ -157,12 +162,30 @@ macro_rules! property {
|
||||
}
|
||||
/// Macro to get the address range of the given memory region.
|
||||
#[macro_export]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
macro_rules! memory_range {
|
||||
("DRAM") => {
|
||||
1073414144..1073741824
|
||||
};
|
||||
}
|
||||
/// This macro can be used to generate code for each peripheral instance of the I2C master driver.
|
||||
///
|
||||
/// For an explanation on the general syntax, as well as usage of individual/repeated
|
||||
/// matchers, refer to [the crate-level documentation][crate#for_each-macros].
|
||||
///
|
||||
/// This macro has one option for its "Individual matcher" case:
|
||||
///
|
||||
/// Syntax: `($instance:ident, $sys:ident, $scl:ident, $sda:ident)`
|
||||
///
|
||||
/// Macro fragments:
|
||||
///
|
||||
/// - `$instance`: the name of the I2C instance
|
||||
/// - `$sys`: the name of the instance as it is in the `esp_hal::system::Peripheral` enum.
|
||||
/// - `$scl`, `$sda`: peripheral signal names.
|
||||
///
|
||||
/// Example data: `(I2C0, I2cExt0, I2CEXT0_SCL, I2CEXT0_SDA)`
|
||||
#[macro_export]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
macro_rules! for_each_i2c_master {
|
||||
($($pattern:tt => $code:tt;)*) => {
|
||||
macro_rules! _for_each_inner { $(($pattern) => $code;)* ($other : tt) => {} }
|
||||
@ -172,7 +195,24 @@ macro_rules! for_each_i2c_master {
|
||||
I2CEXT1_SCL, I2CEXT1_SDA)));
|
||||
};
|
||||
}
|
||||
/// This macro can be used to generate code for each peripheral instance of the UART driver.
|
||||
///
|
||||
/// For an explanation on the general syntax, as well as usage of individual/repeated
|
||||
/// matchers, refer to [the crate-level documentation][crate#for_each-macros].
|
||||
///
|
||||
/// This macro has one option for its "Individual matcher" case:
|
||||
///
|
||||
/// Syntax: `($instance:ident, $sys:ident, $rx:ident, $tx:ident, $cts:ident, $rts:ident)`
|
||||
///
|
||||
/// Macro fragments:
|
||||
///
|
||||
/// - `$instance`: the name of the UART instance
|
||||
/// - `$sys`: the name of the instance as it is in the `esp_hal::system::Peripheral` enum.
|
||||
/// - `$rx`, `$tx`, `$cts`, `$rts`: signal names.
|
||||
///
|
||||
/// Example data: `(UART0, Uart0, U0RXD, U0TXD, U0CTS, U0RTS)`
|
||||
#[macro_export]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
macro_rules! for_each_uart {
|
||||
($($pattern:tt => $code:tt;)*) => {
|
||||
macro_rules! _for_each_inner { $(($pattern) => $code;)* ($other : tt) => {} }
|
||||
@ -182,7 +222,29 @@ macro_rules! for_each_uart {
|
||||
U1RXD, U1TXD, U1CTS, U1RTS)));
|
||||
};
|
||||
}
|
||||
/// This macro can be used to generate code for each peripheral instance of the SPI master driver.
|
||||
///
|
||||
/// For an explanation on the general syntax, as well as usage of individual/repeated
|
||||
/// matchers, refer to [the crate-level documentation][crate#for_each-macros].
|
||||
///
|
||||
/// This macro has one option for its "Individual matcher" case:
|
||||
///
|
||||
/// Syntax: `($instance:ident, $sys:ident, $sclk:ident, [$($cs:ident),*] [$($sio:ident),*
|
||||
/// $($is_qspi:iteral)?])`
|
||||
///
|
||||
/// Macro fragments:
|
||||
///
|
||||
/// - `$instance`: the name of the SPI instance
|
||||
/// - `$sys`: the name of the instance as it is in the `esp_hal::system::Peripheral` enum.
|
||||
/// - `$cs`, `$sio`: chip select and SIO signal names.
|
||||
/// - `$is_qspi`: a `true` literal present if the SPI instance supports QSPI.
|
||||
///
|
||||
/// Example data:
|
||||
/// - `(SPI2, Spi2, FSPICLK [FSPICS0, FSPICS1, FSPICS2, FSPICS3, FSPICS4, FSPICS5] [FSPID, FSPIQ,
|
||||
/// FSPIWP, FSPIHD, FSPIIO4, FSPIIO5, FSPIIO6, FSPIIO7], true)`
|
||||
/// - `(SPI3, Spi3, SPI3_CLK [SPI3_CS0, SPI3_CS1, SPI3_CS2] [SPI3_D, SPI3_Q])`
|
||||
#[macro_export]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
macro_rules! for_each_spi_master {
|
||||
($($pattern:tt => $code:tt;)*) => {
|
||||
macro_rules! _for_each_inner { $(($pattern) => $code;)* ($other : tt) => {} }
|
||||
@ -195,7 +257,24 @@ macro_rules! for_each_spi_master {
|
||||
SPI3_CS1, SPI3_CS2] [SPI3_D, SPI3_Q])));
|
||||
};
|
||||
}
|
||||
/// This macro can be used to generate code for each peripheral instance of the SPI slave driver.
|
||||
///
|
||||
/// For an explanation on the general syntax, as well as usage of individual/repeated
|
||||
/// matchers, refer to [the crate-level documentation][crate#for_each-macros].
|
||||
///
|
||||
/// This macro has one option for its "Individual matcher" case:
|
||||
///
|
||||
/// Syntax: `($instance:ident, $sys:ident, $sclk:ident, $mosi:ident, $miso:ident, $cs:ident)`
|
||||
///
|
||||
/// Macro fragments:
|
||||
///
|
||||
/// - `$instance`: the name of the I2C instance
|
||||
/// - `$sys`: the name of the instance as it is in the `esp_hal::system::Peripheral` enum.
|
||||
/// - `$mosi`, `$miso`, `$cs`: signal names.
|
||||
///
|
||||
/// Example data: `(SPI2, Spi2, FSPICLK, FSPID, FSPIQ, FSPICS0)`
|
||||
#[macro_export]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
macro_rules! for_each_spi_slave {
|
||||
($($pattern:tt => $code:tt;)*) => {
|
||||
macro_rules! _for_each_inner { $(($pattern) => $code;)* ($other : tt) => {} }
|
||||
@ -206,6 +285,7 @@ macro_rules! for_each_spi_slave {
|
||||
};
|
||||
}
|
||||
#[macro_export]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
macro_rules! for_each_peripheral {
|
||||
($($pattern:tt => $code:tt;)*) => {
|
||||
macro_rules! _for_each_inner { $(($pattern) => $code;)* ($other : tt) => {} }
|
||||
@ -327,56 +407,32 @@ macro_rules! for_each_peripheral {
|
||||
virtual() (unstable)), (ULP_RISCV_CORE <= virtual() (unstable))));
|
||||
};
|
||||
}
|
||||
/// This macro can be used to generate code for each GPIOn instance.
|
||||
/// This macro can be used to generate code for each `GPIOn` instance.
|
||||
///
|
||||
/// The basic syntax of this macro looks like a macro definition with two distinct syntax options:
|
||||
/// For an explanation on the general syntax, as well as usage of individual/repeated
|
||||
/// matchers, refer to [the crate-level documentation][crate#for_each-macros].
|
||||
///
|
||||
/// ```rust, no_run
|
||||
/// for_each_gpio! {
|
||||
/// // Individual matcher, invoked separately for each GPIO
|
||||
/// ( <match arm> ) => { /* some code */ };
|
||||
/// This macro has one option for its "Individual matcher" case:
|
||||
///
|
||||
/// // Repeated matcher, invoked once with all GPIOs
|
||||
/// ( all $( (<individual match syntax>) ),* ) => { /* some code */ };
|
||||
/// }
|
||||
/// ```
|
||||
/// Syntax: `($n:literal, $gpio:ident ($($digital_input_function:ident =>
|
||||
/// $digital_input_signal:ident)*) ($($digital_output_function:ident =>
|
||||
/// $digital_output_signal:ident)*) ($($pin_attribute:ident)*))`
|
||||
///
|
||||
/// You can specify any number of matchers.
|
||||
/// Macro fragments:
|
||||
///
|
||||
/// ## Using the individual matcher
|
||||
/// - `$n`: the number of the GPIO. For `GPIO0`, `$n` is 0.
|
||||
/// - `$gpio`: the name of the GPIO.
|
||||
/// - `$digital_input_function`: the number of the digital function, as an identifier (i.e. for
|
||||
/// function 0 this is `_0`).
|
||||
/// - `$digital_input_function`: the name of the digital function, as an identifier.
|
||||
/// - `$digital_output_function`: the number of the digital function, as an identifier (i.e. for
|
||||
/// function 0 this is `_0`).
|
||||
/// - `$digital_output_function`: the name of the digital function, as an identifier.
|
||||
/// - `$pin_attribute`: `Input` and/or `Output`, marks the possible directions of the GPIO.
|
||||
///
|
||||
/// In this use case, each GPIO's data is individually passed through the macro. This can be used to
|
||||
/// generate code for each GPIO separately, allowing specializing the implementation where needed.
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// for_each_gpio! {
|
||||
/// // Example data: `(0, GPIO0 (_5 => EMAC_TX_CLK) (_1 => CLK_OUT1 _5 => EMAC_TX_CLK) (Input Output))`
|
||||
/// ($n:literal, $gpio:ident ($($digital_input_function:ident => $digital_input_signal:ident)*) ($($digital_output_function:ident => $digital_output_signal:ident)*) ($($pin_attribute:ident)*)) => { /* some code */ };
|
||||
///
|
||||
/// // You can create matchers with data filled in. This example will specifically match GPIO2
|
||||
/// ($n:literal, GPIO2 $input_af:tt $output_af:tt $attributes:tt) => { /* Additional case only for GPIO2 */ };
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// ## Repeated matcher
|
||||
///
|
||||
/// With this option, all GPIO data is passed through the macro all at once. This form can be used
|
||||
/// to, for example, generate struct fields.
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// // Example usage to create a struct containing all GPIOs:
|
||||
/// for_each_gpio! {
|
||||
/// (all $( ($n:literal, $gpio:ident $_af_ins:tt $_af_outs:tt $_attrs:tt) ),*) => {
|
||||
/// struct Gpios {
|
||||
/// $(
|
||||
/// #[doc = concat!(" The ", stringify!($n), "th GPIO pin")]
|
||||
/// pub $gpio: Gpio<$n>,
|
||||
/// )*
|
||||
/// }
|
||||
/// };
|
||||
/// }
|
||||
/// ```
|
||||
/// Example data: `(0, GPIO0 (_5 => EMAC_TX_CLK) (_1 => CLK_OUT1 _5 => EMAC_TX_CLK) (Input Output))`
|
||||
#[macro_export]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
macro_rules! for_each_gpio {
|
||||
($($pattern:tt => $code:tt;)*) => {
|
||||
macro_rules! _for_each_inner { $(($pattern) => $code;)* ($other : tt) => {} }
|
||||
@ -462,7 +518,7 @@ macro_rules! for_each_gpio {
|
||||
/// This macro can be used to generate code for each analog function of each GPIO.
|
||||
///
|
||||
/// For an explanation on the general syntax, as well as usage of individual/repeated
|
||||
/// matchers, refer to [for_each_gpio].
|
||||
/// matchers, refer to [the crate-level documentation][crate#for_each-macros].
|
||||
///
|
||||
/// This macro has two options for its "Individual matcher" case:
|
||||
///
|
||||
@ -471,8 +527,21 @@ macro_rules! for_each_gpio {
|
||||
/// where you need the number(s) of a signal, or the general group to which the signal belongs.
|
||||
/// For example, in case of `ADC2_CH3` the expanded form looks like `(ADC2_CH3, ADCn_CHm, 2, 3)`.
|
||||
///
|
||||
/// The expanded signal are only available when the signal has at least one numbered component.
|
||||
/// Macro fragments:
|
||||
///
|
||||
/// - `$signal`: the name of the signal.
|
||||
/// - `$group`: the name of the signal, with numbers replaced by placeholders. For `ADC2_CH3` this
|
||||
/// is `ADCn_CHm`.
|
||||
/// - `$number`: the numbers extracted from `$signal`.
|
||||
/// - `$gpio`: the name of the GPIO.
|
||||
///
|
||||
/// Example data:
|
||||
/// - `(ADC2_CH5, GPIO12)`
|
||||
/// - `((ADC2_CH5, ADCn_CHm, 2, 5), GPIO12)`
|
||||
///
|
||||
/// The expanded syntax is only available when the signal has at least one numbered component.
|
||||
#[macro_export]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
macro_rules! for_each_analog_function {
|
||||
($($pattern:tt => $code:tt;)*) => {
|
||||
macro_rules! _for_each_inner { $(($pattern) => $code;)* ($other : tt) => {} }
|
||||
@ -554,7 +623,7 @@ macro_rules! for_each_analog_function {
|
||||
/// This macro can be used to generate code for each LP/RTC function of each GPIO.
|
||||
///
|
||||
/// For an explanation on the general syntax, as well as usage of individual/repeated
|
||||
/// matchers, refer to [for_each_gpio].
|
||||
/// matchers, refer to [the crate-level documentation][crate#for_each-macros].
|
||||
///
|
||||
/// This macro has two options for its "Individual matcher" case:
|
||||
///
|
||||
@ -564,8 +633,21 @@ macro_rules! for_each_analog_function {
|
||||
/// For example, in case of `SAR_I2C_SCL_1` the expanded form looks like `(SAR_I2C_SCL_1,
|
||||
/// SAR_I2C_SCL_n, 1)`.
|
||||
///
|
||||
/// The expanded signal are only available when the signal has at least one numbered component.
|
||||
/// Macro fragments:
|
||||
///
|
||||
/// - `$signal`: the name of the signal.
|
||||
/// - `$group`: the name of the signal, with numbers replaced by placeholders. For `ADC2_CH3` this
|
||||
/// is `ADCn_CHm`.
|
||||
/// - `$number`: the numbers extracted from `$signal`.
|
||||
/// - `$gpio`: the name of the GPIO.
|
||||
///
|
||||
/// Example data:
|
||||
/// - `(RTC_GPIO15, GPIO12)`
|
||||
/// - `((RTC_GPIO15, RTC_GPIOn, 15), GPIO12)`
|
||||
///
|
||||
/// The expanded syntax is only available when the signal has at least one numbered component.
|
||||
#[macro_export]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
macro_rules! for_each_lp_function {
|
||||
($($pattern:tt => $code:tt;)*) => {
|
||||
macro_rules! _for_each_inner { $(($pattern) => $code;)* ($other : tt) => {} }
|
||||
@ -621,6 +703,7 @@ macro_rules! for_each_lp_function {
|
||||
};
|
||||
}
|
||||
#[macro_export]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
macro_rules! if_pin_is_type {
|
||||
(GPIO0, Input, $then_tt:tt else $else_tt:tt) => {
|
||||
$then_tt
|
||||
@ -1011,6 +1094,7 @@ macro_rules! if_pin_is_type {
|
||||
};
|
||||
}
|
||||
#[macro_export]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
#[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) => {
|
||||
@ -1150,6 +1234,7 @@ macro_rules! impl_for_pin_type {
|
||||
};
|
||||
}
|
||||
#[macro_export]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
macro_rules! define_io_mux_signals {
|
||||
() => {
|
||||
#[allow(non_camel_case_types, clippy::upper_case_acronyms)]
|
||||
@ -1367,6 +1452,7 @@ macro_rules! define_io_mux_signals {
|
||||
}
|
||||
#[macro_export]
|
||||
#[expect(clippy::crate_in_macro_def)]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
macro_rules! define_io_mux_reg {
|
||||
() => {
|
||||
pub(crate) fn io_mux_reg(gpio_num: u8) -> &'static crate::pac::io_mux::GPIO {
|
||||
|
@ -1,3 +1,6 @@
|
||||
// Do NOT edit this file directly. Make your changes to esp-metadata,
|
||||
// then run `cargo xtask update-metadata`.
|
||||
|
||||
/// The name of the chip as `&str`
|
||||
///
|
||||
/// # Example
|
||||
@ -8,6 +11,7 @@
|
||||
#[doc = concat!("assert_eq!(chip_name, ", chip!(), ")")]
|
||||
/// ```
|
||||
#[macro_export]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
macro_rules! chip {
|
||||
() => {
|
||||
"esp32s3"
|
||||
@ -15,6 +19,7 @@ macro_rules! chip {
|
||||
}
|
||||
/// The properties of this chip and its drivers.
|
||||
#[macro_export]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
macro_rules! property {
|
||||
("chip") => {
|
||||
"esp32s3"
|
||||
@ -157,12 +162,30 @@ macro_rules! property {
|
||||
}
|
||||
/// Macro to get the address range of the given memory region.
|
||||
#[macro_export]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
macro_rules! memory_range {
|
||||
("DRAM") => {
|
||||
1070104576..1070596096
|
||||
};
|
||||
}
|
||||
/// This macro can be used to generate code for each peripheral instance of the I2C master driver.
|
||||
///
|
||||
/// For an explanation on the general syntax, as well as usage of individual/repeated
|
||||
/// matchers, refer to [the crate-level documentation][crate#for_each-macros].
|
||||
///
|
||||
/// This macro has one option for its "Individual matcher" case:
|
||||
///
|
||||
/// Syntax: `($instance:ident, $sys:ident, $scl:ident, $sda:ident)`
|
||||
///
|
||||
/// Macro fragments:
|
||||
///
|
||||
/// - `$instance`: the name of the I2C instance
|
||||
/// - `$sys`: the name of the instance as it is in the `esp_hal::system::Peripheral` enum.
|
||||
/// - `$scl`, `$sda`: peripheral signal names.
|
||||
///
|
||||
/// Example data: `(I2C0, I2cExt0, I2CEXT0_SCL, I2CEXT0_SDA)`
|
||||
#[macro_export]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
macro_rules! for_each_i2c_master {
|
||||
($($pattern:tt => $code:tt;)*) => {
|
||||
macro_rules! _for_each_inner { $(($pattern) => $code;)* ($other : tt) => {} }
|
||||
@ -172,7 +195,24 @@ macro_rules! for_each_i2c_master {
|
||||
I2CEXT1_SCL, I2CEXT1_SDA)));
|
||||
};
|
||||
}
|
||||
/// This macro can be used to generate code for each peripheral instance of the UART driver.
|
||||
///
|
||||
/// For an explanation on the general syntax, as well as usage of individual/repeated
|
||||
/// matchers, refer to [the crate-level documentation][crate#for_each-macros].
|
||||
///
|
||||
/// This macro has one option for its "Individual matcher" case:
|
||||
///
|
||||
/// Syntax: `($instance:ident, $sys:ident, $rx:ident, $tx:ident, $cts:ident, $rts:ident)`
|
||||
///
|
||||
/// Macro fragments:
|
||||
///
|
||||
/// - `$instance`: the name of the UART instance
|
||||
/// - `$sys`: the name of the instance as it is in the `esp_hal::system::Peripheral` enum.
|
||||
/// - `$rx`, `$tx`, `$cts`, `$rts`: signal names.
|
||||
///
|
||||
/// Example data: `(UART0, Uart0, U0RXD, U0TXD, U0CTS, U0RTS)`
|
||||
#[macro_export]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
macro_rules! for_each_uart {
|
||||
($($pattern:tt => $code:tt;)*) => {
|
||||
macro_rules! _for_each_inner { $(($pattern) => $code;)* ($other : tt) => {} }
|
||||
@ -183,7 +223,29 @@ macro_rules! for_each_uart {
|
||||
U1RXD, U1TXD, U1CTS, U1RTS), (UART2, Uart2, U2RXD, U2TXD, U2CTS, U2RTS)));
|
||||
};
|
||||
}
|
||||
/// This macro can be used to generate code for each peripheral instance of the SPI master driver.
|
||||
///
|
||||
/// For an explanation on the general syntax, as well as usage of individual/repeated
|
||||
/// matchers, refer to [the crate-level documentation][crate#for_each-macros].
|
||||
///
|
||||
/// This macro has one option for its "Individual matcher" case:
|
||||
///
|
||||
/// Syntax: `($instance:ident, $sys:ident, $sclk:ident, [$($cs:ident),*] [$($sio:ident),*
|
||||
/// $($is_qspi:iteral)?])`
|
||||
///
|
||||
/// Macro fragments:
|
||||
///
|
||||
/// - `$instance`: the name of the SPI instance
|
||||
/// - `$sys`: the name of the instance as it is in the `esp_hal::system::Peripheral` enum.
|
||||
/// - `$cs`, `$sio`: chip select and SIO signal names.
|
||||
/// - `$is_qspi`: a `true` literal present if the SPI instance supports QSPI.
|
||||
///
|
||||
/// Example data:
|
||||
/// - `(SPI2, Spi2, FSPICLK [FSPICS0, FSPICS1, FSPICS2, FSPICS3, FSPICS4, FSPICS5] [FSPID, FSPIQ,
|
||||
/// FSPIWP, FSPIHD, FSPIIO4, FSPIIO5, FSPIIO6, FSPIIO7], true)`
|
||||
/// - `(SPI3, Spi3, SPI3_CLK [SPI3_CS0, SPI3_CS1, SPI3_CS2] [SPI3_D, SPI3_Q])`
|
||||
#[macro_export]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
macro_rules! for_each_spi_master {
|
||||
($($pattern:tt => $code:tt;)*) => {
|
||||
macro_rules! _for_each_inner { $(($pattern) => $code;)* ($other : tt) => {} }
|
||||
@ -197,7 +259,24 @@ macro_rules! for_each_spi_master {
|
||||
true)));
|
||||
};
|
||||
}
|
||||
/// This macro can be used to generate code for each peripheral instance of the SPI slave driver.
|
||||
///
|
||||
/// For an explanation on the general syntax, as well as usage of individual/repeated
|
||||
/// matchers, refer to [the crate-level documentation][crate#for_each-macros].
|
||||
///
|
||||
/// This macro has one option for its "Individual matcher" case:
|
||||
///
|
||||
/// Syntax: `($instance:ident, $sys:ident, $sclk:ident, $mosi:ident, $miso:ident, $cs:ident)`
|
||||
///
|
||||
/// Macro fragments:
|
||||
///
|
||||
/// - `$instance`: the name of the I2C instance
|
||||
/// - `$sys`: the name of the instance as it is in the `esp_hal::system::Peripheral` enum.
|
||||
/// - `$mosi`, `$miso`, `$cs`: signal names.
|
||||
///
|
||||
/// Example data: `(SPI2, Spi2, FSPICLK, FSPID, FSPIQ, FSPICS0)`
|
||||
#[macro_export]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
macro_rules! for_each_spi_slave {
|
||||
($($pattern:tt => $code:tt;)*) => {
|
||||
macro_rules! _for_each_inner { $(($pattern) => $code;)* ($other : tt) => {} }
|
||||
@ -208,6 +287,7 @@ macro_rules! for_each_spi_slave {
|
||||
};
|
||||
}
|
||||
#[macro_export]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
macro_rules! for_each_peripheral {
|
||||
($($pattern:tt => $code:tt;)*) => {
|
||||
macro_rules! _for_each_inner { $(($pattern) => $code;)* ($other : tt) => {} }
|
||||
@ -345,56 +425,32 @@ macro_rules! for_each_peripheral {
|
||||
virtual() (unstable))));
|
||||
};
|
||||
}
|
||||
/// This macro can be used to generate code for each GPIOn instance.
|
||||
/// This macro can be used to generate code for each `GPIOn` instance.
|
||||
///
|
||||
/// The basic syntax of this macro looks like a macro definition with two distinct syntax options:
|
||||
/// For an explanation on the general syntax, as well as usage of individual/repeated
|
||||
/// matchers, refer to [the crate-level documentation][crate#for_each-macros].
|
||||
///
|
||||
/// ```rust, no_run
|
||||
/// for_each_gpio! {
|
||||
/// // Individual matcher, invoked separately for each GPIO
|
||||
/// ( <match arm> ) => { /* some code */ };
|
||||
/// This macro has one option for its "Individual matcher" case:
|
||||
///
|
||||
/// // Repeated matcher, invoked once with all GPIOs
|
||||
/// ( all $( (<individual match syntax>) ),* ) => { /* some code */ };
|
||||
/// }
|
||||
/// ```
|
||||
/// Syntax: `($n:literal, $gpio:ident ($($digital_input_function:ident =>
|
||||
/// $digital_input_signal:ident)*) ($($digital_output_function:ident =>
|
||||
/// $digital_output_signal:ident)*) ($($pin_attribute:ident)*))`
|
||||
///
|
||||
/// You can specify any number of matchers.
|
||||
/// Macro fragments:
|
||||
///
|
||||
/// ## Using the individual matcher
|
||||
/// - `$n`: the number of the GPIO. For `GPIO0`, `$n` is 0.
|
||||
/// - `$gpio`: the name of the GPIO.
|
||||
/// - `$digital_input_function`: the number of the digital function, as an identifier (i.e. for
|
||||
/// function 0 this is `_0`).
|
||||
/// - `$digital_input_function`: the name of the digital function, as an identifier.
|
||||
/// - `$digital_output_function`: the number of the digital function, as an identifier (i.e. for
|
||||
/// function 0 this is `_0`).
|
||||
/// - `$digital_output_function`: the name of the digital function, as an identifier.
|
||||
/// - `$pin_attribute`: `Input` and/or `Output`, marks the possible directions of the GPIO.
|
||||
///
|
||||
/// In this use case, each GPIO's data is individually passed through the macro. This can be used to
|
||||
/// generate code for each GPIO separately, allowing specializing the implementation where needed.
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// for_each_gpio! {
|
||||
/// // Example data: `(0, GPIO0 (_5 => EMAC_TX_CLK) (_1 => CLK_OUT1 _5 => EMAC_TX_CLK) (Input Output))`
|
||||
/// ($n:literal, $gpio:ident ($($digital_input_function:ident => $digital_input_signal:ident)*) ($($digital_output_function:ident => $digital_output_signal:ident)*) ($($pin_attribute:ident)*)) => { /* some code */ };
|
||||
///
|
||||
/// // You can create matchers with data filled in. This example will specifically match GPIO2
|
||||
/// ($n:literal, GPIO2 $input_af:tt $output_af:tt $attributes:tt) => { /* Additional case only for GPIO2 */ };
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// ## Repeated matcher
|
||||
///
|
||||
/// With this option, all GPIO data is passed through the macro all at once. This form can be used
|
||||
/// to, for example, generate struct fields.
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// // Example usage to create a struct containing all GPIOs:
|
||||
/// for_each_gpio! {
|
||||
/// (all $( ($n:literal, $gpio:ident $_af_ins:tt $_af_outs:tt $_attrs:tt) ),*) => {
|
||||
/// struct Gpios {
|
||||
/// $(
|
||||
/// #[doc = concat!(" The ", stringify!($n), "th GPIO pin")]
|
||||
/// pub $gpio: Gpio<$n>,
|
||||
/// )*
|
||||
/// }
|
||||
/// };
|
||||
/// }
|
||||
/// ```
|
||||
/// Example data: `(0, GPIO0 (_5 => EMAC_TX_CLK) (_1 => CLK_OUT1 _5 => EMAC_TX_CLK) (Input Output))`
|
||||
#[macro_export]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
macro_rules! for_each_gpio {
|
||||
($($pattern:tt => $code:tt;)*) => {
|
||||
macro_rules! _for_each_inner { $(($pattern) => $code;)* ($other : tt) => {} }
|
||||
@ -486,7 +542,7 @@ macro_rules! for_each_gpio {
|
||||
/// This macro can be used to generate code for each analog function of each GPIO.
|
||||
///
|
||||
/// For an explanation on the general syntax, as well as usage of individual/repeated
|
||||
/// matchers, refer to [for_each_gpio].
|
||||
/// matchers, refer to [the crate-level documentation][crate#for_each-macros].
|
||||
///
|
||||
/// This macro has two options for its "Individual matcher" case:
|
||||
///
|
||||
@ -495,8 +551,21 @@ macro_rules! for_each_gpio {
|
||||
/// where you need the number(s) of a signal, or the general group to which the signal belongs.
|
||||
/// For example, in case of `ADC2_CH3` the expanded form looks like `(ADC2_CH3, ADCn_CHm, 2, 3)`.
|
||||
///
|
||||
/// The expanded signal are only available when the signal has at least one numbered component.
|
||||
/// Macro fragments:
|
||||
///
|
||||
/// - `$signal`: the name of the signal.
|
||||
/// - `$group`: the name of the signal, with numbers replaced by placeholders. For `ADC2_CH3` this
|
||||
/// is `ADCn_CHm`.
|
||||
/// - `$number`: the numbers extracted from `$signal`.
|
||||
/// - `$gpio`: the name of the GPIO.
|
||||
///
|
||||
/// Example data:
|
||||
/// - `(ADC2_CH5, GPIO12)`
|
||||
/// - `((ADC2_CH5, ADCn_CHm, 2, 5), GPIO12)`
|
||||
///
|
||||
/// The expanded syntax is only available when the signal has at least one numbered component.
|
||||
#[macro_export]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
macro_rules! for_each_analog_function {
|
||||
($($pattern:tt => $code:tt;)*) => {
|
||||
macro_rules! _for_each_inner { $(($pattern) => $code;)* ($other : tt) => {} }
|
||||
@ -575,7 +644,7 @@ macro_rules! for_each_analog_function {
|
||||
/// This macro can be used to generate code for each LP/RTC function of each GPIO.
|
||||
///
|
||||
/// For an explanation on the general syntax, as well as usage of individual/repeated
|
||||
/// matchers, refer to [for_each_gpio].
|
||||
/// matchers, refer to [the crate-level documentation][crate#for_each-macros].
|
||||
///
|
||||
/// This macro has two options for its "Individual matcher" case:
|
||||
///
|
||||
@ -585,8 +654,21 @@ macro_rules! for_each_analog_function {
|
||||
/// For example, in case of `SAR_I2C_SCL_1` the expanded form looks like `(SAR_I2C_SCL_1,
|
||||
/// SAR_I2C_SCL_n, 1)`.
|
||||
///
|
||||
/// The expanded signal are only available when the signal has at least one numbered component.
|
||||
/// Macro fragments:
|
||||
///
|
||||
/// - `$signal`: the name of the signal.
|
||||
/// - `$group`: the name of the signal, with numbers replaced by placeholders. For `ADC2_CH3` this
|
||||
/// is `ADCn_CHm`.
|
||||
/// - `$number`: the numbers extracted from `$signal`.
|
||||
/// - `$gpio`: the name of the GPIO.
|
||||
///
|
||||
/// Example data:
|
||||
/// - `(RTC_GPIO15, GPIO12)`
|
||||
/// - `((RTC_GPIO15, RTC_GPIOn, 15), GPIO12)`
|
||||
///
|
||||
/// The expanded syntax is only available when the signal has at least one numbered component.
|
||||
#[macro_export]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
macro_rules! for_each_lp_function {
|
||||
($($pattern:tt => $code:tt;)*) => {
|
||||
macro_rules! _for_each_inner { $(($pattern) => $code;)* ($other : tt) => {} }
|
||||
@ -653,6 +735,7 @@ macro_rules! for_each_lp_function {
|
||||
};
|
||||
}
|
||||
#[macro_export]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
macro_rules! if_pin_is_type {
|
||||
(GPIO0, Input, $then_tt:tt else $else_tt:tt) => {
|
||||
$then_tt
|
||||
@ -1061,6 +1144,7 @@ macro_rules! if_pin_is_type {
|
||||
};
|
||||
}
|
||||
#[macro_export]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
#[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) => {
|
||||
@ -1206,6 +1290,7 @@ macro_rules! impl_for_pin_type {
|
||||
};
|
||||
}
|
||||
#[macro_export]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
macro_rules! define_io_mux_signals {
|
||||
() => {
|
||||
#[allow(non_camel_case_types, clippy::upper_case_acronyms)]
|
||||
@ -1582,6 +1667,7 @@ macro_rules! define_io_mux_signals {
|
||||
}
|
||||
#[macro_export]
|
||||
#[expect(clippy::crate_in_macro_def)]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
macro_rules! define_io_mux_reg {
|
||||
() => {
|
||||
pub(crate) fn io_mux_reg(gpio_num: u8) -> &'static crate::pac::io_mux::GPIO {
|
||||
|
@ -1,3 +1,100 @@
|
||||
// Do NOT edit this file directly. Make your changes to esp-metadata,
|
||||
// then run `cargo xtask update-metadata`.
|
||||
|
||||
//! # (Generated) metadata for Espressif MCUs.
|
||||
//!
|
||||
//! This crate provides properties that are specific to various Espressif microcontrollers,
|
||||
//! and provides macros to work with peripherals, pins, and various other parts of the chips.
|
||||
//!
|
||||
//! This crate can be used both in firmware, as well as in build scripts, but the usage is
|
||||
//! different.
|
||||
//!
|
||||
//! ## Usage in build scripts
|
||||
//!
|
||||
//! To use the `Chip` enum, add the crate to your `Cargo.toml` build
|
||||
//! dependencies, with the `build-script` feature:
|
||||
//!
|
||||
//! ```toml
|
||||
//! [build-dependencies]
|
||||
//! esp-metadata-generated = { version = "...", features = ["build-script"] }
|
||||
//! ```
|
||||
//!
|
||||
//! ## Usage in firmware
|
||||
//!
|
||||
//! To use the various macros, add the crate to your `Cargo.toml` dependencies.
|
||||
//! A device-specific feature needs to be enabled in order to use the crate, usually
|
||||
//! picked by the user:
|
||||
//!
|
||||
//! ```toml
|
||||
//! [dependencies]
|
||||
//! esp-metadata-generated = { version = "..." }
|
||||
//! # ...
|
||||
//!
|
||||
//! [features]
|
||||
//! esp32 = ["esp-metadata-generated/esp32"]
|
||||
//! esp32c2 = ["esp-metadata-generated/esp32c2"]
|
||||
//! # ...
|
||||
//! ```
|
||||
//!
|
||||
//! ## `for_each` macros
|
||||
//!
|
||||
//! The basic syntax of this macro looks like a macro definition with two distinct syntax options:
|
||||
//!
|
||||
//! ```rust, no_run
|
||||
//! for_each_peripherals! {
|
||||
//! // Individual matcher, invoked separately for each peripheral instance
|
||||
//! ( <individual match syntax> ) => { /* some code */ };
|
||||
//!
|
||||
//! // Repeated matcher, invoked once with all peripheral instances
|
||||
//! ( all $( (<individual match syntax>) ),* ) => { /* some code */ };
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
//! You can specify any number of matchers in the same invocation.
|
||||
//!
|
||||
//! ### Using the individual matcher
|
||||
//!
|
||||
//! In this use case, each item's data is individually passed through the macro. This can be used to
|
||||
//! generate code for each item separately, allowing specializing the implementation where needed.
|
||||
//!
|
||||
//! ```rust,no_run
|
||||
//! for_each_gpio! {
|
||||
//! // Example data: `(0, GPIO0 (_5 => EMAC_TX_CLK) (_1 => CLK_OUT1 _5 => EMAC_TX_CLK) (Input Output))`
|
||||
//! ($n:literal, $gpio:ident ($($digital_input_function:ident => $digital_input_signal:ident)*) ($($digital_output_function:ident => $digital_output_signal:ident)*) ($($pin_attribute:ident)*)) => { /* some code */ };
|
||||
//!
|
||||
//! // You can create matchers with data filled in. This example will specifically match GPIO2
|
||||
//! ($n:literal, GPIO2 $input_af:tt $output_af:tt $attributes:tt) => { /* Additional case only for GPIO2 */ };
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
//! Different macros can have multiple different syntax options for their individual matchers,
|
||||
//! usually to provide more detailed information, while preserving simpler syntax for more basic use
|
||||
//! cases. Consult each macro's documentation for available options.
|
||||
//!
|
||||
//! ### Repeated matcher
|
||||
//!
|
||||
//! With this option, all data is passed through the macro all at once. This form can be used to,
|
||||
//! for example, generate struct fields. If the macro has multiple individual matcher options,
|
||||
//! the repeated matcher will contain each item's data multiple times, once for each available
|
||||
//! syntax option. Currently, using the repeated matcher is not recommended for these macros.
|
||||
//!
|
||||
//! > This issue will be likely resolved by naming the different syntax options, and providing
|
||||
//! > different match arms for each in place of `all`.
|
||||
//!
|
||||
//! ```rust,no_run
|
||||
//! // Example usage to create a struct containing all GPIOs:
|
||||
//! for_each_gpio! {
|
||||
//! (all $( ($n:literal, $gpio:ident $_af_ins:tt $_af_outs:tt $_attrs:tt) ),*) => {
|
||||
//! struct Gpios {
|
||||
//! $(
|
||||
//! #[doc = concat!(" The ", stringify!($n), "th GPIO pin")]
|
||||
//! pub $gpio: Gpio<$n>,
|
||||
//! )*
|
||||
//! }
|
||||
//! };
|
||||
//! }
|
||||
//! ```
|
||||
#![cfg_attr(docsrs, feature(doc_cfg))]
|
||||
#![cfg_attr(not(feature = "build-script"), no_std)]
|
||||
#[cfg(all(not(feature = "build-script"), feature = "esp32"))]
|
||||
include!("_generated_esp32.rs");
|
||||
@ -13,5 +110,5 @@ include!("_generated_esp32h2.rs");
|
||||
include!("_generated_esp32s2.rs");
|
||||
#[cfg(all(not(feature = "build-script"), feature = "esp32s3"))]
|
||||
include!("_generated_esp32s3.rs");
|
||||
#[cfg(feature = "build-script")]
|
||||
#[cfg(any(feature = "build-script", docsrs))]
|
||||
include!("_build_script_utils.rs");
|
||||
|
@ -8,6 +8,8 @@
|
||||
|
||||
Metadata for Espressif devices, intended for use in [build scripts].
|
||||
|
||||
Firmware crates are meant to depend on `esp-metadata-generated`, not on this crate directly. To update `esp-metadata-generated`, make your changes in `esp-metadata`, then run `cargo xtask update-metadata`.
|
||||
|
||||
[build scripts]: https://doc.rust-lang.org/cargo/reference/build-scripts.html
|
||||
|
||||
## [Documentation](https://docs.espressif.com/projects/rust/esp-metadata/latest/)
|
||||
|
@ -425,6 +425,7 @@ pub(crate) fn generate_gpios(gpio: &super::GpioProperties) -> TokenStream {
|
||||
|
||||
quote! {
|
||||
#[macro_export]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
macro_rules! if_pin_is_type {
|
||||
#(#branches)*
|
||||
}
|
||||
@ -453,6 +454,7 @@ pub(crate) fn generate_gpios(gpio: &super::GpioProperties) -> TokenStream {
|
||||
|
||||
quote! {
|
||||
#[macro_export]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
#[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) => {
|
||||
@ -487,87 +489,81 @@ pub(crate) fn generate_gpios(gpio: &super::GpioProperties) -> TokenStream {
|
||||
let output_signals = render_signals("OutputSignal", &gpio.pins_and_signals.output_signals);
|
||||
|
||||
quote! {
|
||||
/// This macro can be used to generate code for each GPIOn instance.
|
||||
/// This macro can be used to generate code for each `GPIOn` instance.
|
||||
///
|
||||
/// The basic syntax of this macro looks like a macro definition with two distinct syntax options:
|
||||
/// For an explanation on the general syntax, as well as usage of individual/repeated
|
||||
/// matchers, refer to [the crate-level documentation][crate#for_each-macros].
|
||||
///
|
||||
/// ```rust, no_run
|
||||
/// for_each_gpio! {
|
||||
/// // Individual matcher, invoked separately for each GPIO
|
||||
/// ( <match arm> ) => { /* some code */ };
|
||||
/// This macro has one option for its "Individual matcher" case:
|
||||
///
|
||||
/// // Repeated matcher, invoked once with all GPIOs
|
||||
/// ( all $( (<individual match syntax>) ),* ) => { /* some code */ };
|
||||
/// }
|
||||
/// ```
|
||||
/// Syntax: `($n:literal, $gpio:ident ($($digital_input_function:ident => $digital_input_signal:ident)*) ($($digital_output_function:ident => $digital_output_signal:ident)*) ($($pin_attribute:ident)*))`
|
||||
///
|
||||
/// You can specify any number of matchers.
|
||||
/// Macro fragments:
|
||||
///
|
||||
/// ## Using the individual matcher
|
||||
/// - `$n`: the number of the GPIO. For `GPIO0`, `$n` is 0.
|
||||
/// - `$gpio`: the name of the GPIO.
|
||||
/// - `$digital_input_function`: the number of the digital function, as an identifier (i.e. for function 0 this is `_0`).
|
||||
/// - `$digital_input_function`: the name of the digital function, as an identifier.
|
||||
/// - `$digital_output_function`: the number of the digital function, as an identifier (i.e. for function 0 this is `_0`).
|
||||
/// - `$digital_output_function`: the name of the digital function, as an identifier.
|
||||
/// - `$pin_attribute`: `Input` and/or `Output`, marks the possible directions of the GPIO.
|
||||
///
|
||||
/// In this use case, each GPIO's data is individually passed through the macro. This can be used to
|
||||
/// generate code for each GPIO separately, allowing specializing the implementation where needed.
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// for_each_gpio! {
|
||||
/// // Example data: `(0, GPIO0 (_5 => EMAC_TX_CLK) (_1 => CLK_OUT1 _5 => EMAC_TX_CLK) (Input Output))`
|
||||
/// ($n:literal, $gpio:ident ($($digital_input_function:ident => $digital_input_signal:ident)*) ($($digital_output_function:ident => $digital_output_signal:ident)*) ($($pin_attribute:ident)*)) => { /* some code */ };
|
||||
///
|
||||
/// // You can create matchers with data filled in. This example will specifically match GPIO2
|
||||
/// ($n:literal, GPIO2 $input_af:tt $output_af:tt $attributes:tt) => { /* Additional case only for GPIO2 */ };
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// ## Repeated matcher
|
||||
///
|
||||
/// With this option, all GPIO data is passed through the macro all at once. This form can be used to,
|
||||
/// for example, generate struct fields.
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// // Example usage to create a struct containing all GPIOs:
|
||||
/// for_each_gpio! {
|
||||
/// (all $( ($n:literal, $gpio:ident $_af_ins:tt $_af_outs:tt $_attrs:tt) ),*) => {
|
||||
/// struct Gpios {
|
||||
/// $(
|
||||
/// #[doc = concat!(" The ", stringify!($n), "th GPIO pin")]
|
||||
/// pub $gpio: Gpio<$n>,
|
||||
/// )*
|
||||
/// }
|
||||
/// };
|
||||
/// }
|
||||
/// ```
|
||||
/// Example data: `(0, GPIO0 (_5 => EMAC_TX_CLK) (_1 => CLK_OUT1 _5 => EMAC_TX_CLK) (Input Output))`
|
||||
#for_each_gpio
|
||||
|
||||
/// This macro can be used to generate code for each analog function of each GPIO.
|
||||
///
|
||||
/// For an explanation on the general syntax, as well as usage of individual/repeated
|
||||
/// matchers, refer to [for_each_gpio].
|
||||
/// matchers, refer to [the crate-level documentation][crate#for_each-macros].
|
||||
///
|
||||
/// This macro has two options for its "Individual matcher" case:
|
||||
///
|
||||
/// - `($signal:ident, $gpio:ident)` - simple case where you only need identifiers
|
||||
/// - `(($signal:ident, $group:ident $(, $number:literal)+), $gpio:ident)` - expanded signal case, where you need the number(s) of a signal, or the general group to which the signal belongs. For example, in case of `ADC2_CH3` the expanded form looks like `(ADC2_CH3, ADCn_CHm, 2, 3)`.
|
||||
///
|
||||
/// The expanded signal are only available when the signal has at least one numbered component.
|
||||
/// Macro fragments:
|
||||
///
|
||||
/// - `$signal`: the name of the signal.
|
||||
/// - `$group`: the name of the signal, with numbers replaced by placeholders. For `ADC2_CH3` this is `ADCn_CHm`.
|
||||
/// - `$number`: the numbers extracted from `$signal`.
|
||||
/// - `$gpio`: the name of the GPIO.
|
||||
///
|
||||
/// Example data:
|
||||
/// - `(ADC2_CH5, GPIO12)`
|
||||
/// - `((ADC2_CH5, ADCn_CHm, 2, 5), GPIO12)`
|
||||
///
|
||||
/// The expanded syntax is only available when the signal has at least one numbered component.
|
||||
#for_each_analog
|
||||
|
||||
/// This macro can be used to generate code for each LP/RTC function of each GPIO.
|
||||
///
|
||||
/// For an explanation on the general syntax, as well as usage of individual/repeated
|
||||
/// matchers, refer to [for_each_gpio].
|
||||
/// matchers, refer to [the crate-level documentation][crate#for_each-macros].
|
||||
///
|
||||
/// This macro has two options for its "Individual matcher" case:
|
||||
///
|
||||
/// - `($signal:ident, $gpio:ident)` - simple case where you only need identifiers
|
||||
/// - `(($signal:ident, $group:ident $(, $number:literal)+), $gpio:ident)` - expanded signal case, where you need the number(s) of a signal, or the general group to which the signal belongs. For example, in case of `SAR_I2C_SCL_1` the expanded form looks like `(SAR_I2C_SCL_1, SAR_I2C_SCL_n, 1)`.
|
||||
///
|
||||
/// The expanded signal are only available when the signal has at least one numbered component.
|
||||
/// Macro fragments:
|
||||
///
|
||||
/// - `$signal`: the name of the signal.
|
||||
/// - `$group`: the name of the signal, with numbers replaced by placeholders. For `ADC2_CH3` this is `ADCn_CHm`.
|
||||
/// - `$number`: the numbers extracted from `$signal`.
|
||||
/// - `$gpio`: the name of the GPIO.
|
||||
///
|
||||
/// Example data:
|
||||
/// - `(RTC_GPIO15, GPIO12)`
|
||||
/// - `((RTC_GPIO15, RTC_GPIOn, 15), GPIO12)`
|
||||
///
|
||||
/// The expanded syntax is only available when the signal has at least one numbered component.
|
||||
#for_each_lp
|
||||
|
||||
#if_pin_is_type
|
||||
#impl_for_pin_type
|
||||
|
||||
#[macro_export]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
macro_rules! define_io_mux_signals {
|
||||
() => {
|
||||
#input_signals
|
||||
@ -577,6 +573,7 @@ pub(crate) fn generate_gpios(gpio: &super::GpioProperties) -> TokenStream {
|
||||
|
||||
#[macro_export]
|
||||
#[expect(clippy::crate_in_macro_def)]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
macro_rules! define_io_mux_reg {
|
||||
() => {
|
||||
#io_mux_accessor
|
||||
|
@ -1,5 +1,5 @@
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::format_ident;
|
||||
use quote::{format_ident, quote};
|
||||
|
||||
use crate::{cfg::I2cMasterProperties, generate_for_each_macro};
|
||||
|
||||
@ -34,11 +34,31 @@ pub(crate) fn generate_i2c_master_peripherals(i2c: &I2cMasterProperties) -> Toke
|
||||
|
||||
// The order and meaning of these tokens must match their use in the
|
||||
// `for_each_i2c_master!` call.
|
||||
quote::quote! {
|
||||
quote! {
|
||||
#instance, #sys, #scl, #sda
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
generate_for_each_macro("i2c_master", &i2c_master_instance_cfgs)
|
||||
let for_each = generate_for_each_macro("i2c_master", &i2c_master_instance_cfgs);
|
||||
|
||||
quote! {
|
||||
/// This macro can be used to generate code for each peripheral instance of the I2C master driver.
|
||||
///
|
||||
/// For an explanation on the general syntax, as well as usage of individual/repeated
|
||||
/// matchers, refer to [the crate-level documentation][crate#for_each-macros].
|
||||
///
|
||||
/// This macro has one option for its "Individual matcher" case:
|
||||
///
|
||||
/// Syntax: `($instance:ident, $sys:ident, $scl:ident, $sda:ident)`
|
||||
///
|
||||
/// Macro fragments:
|
||||
///
|
||||
/// - `$instance`: the name of the I2C instance
|
||||
/// - `$sys`: the name of the instance as it is in the `esp_hal::system::Peripheral` enum.
|
||||
/// - `$scl`, `$sda`: peripheral signal names.
|
||||
///
|
||||
/// Example data: `(I2C0, I2cExt0, I2CEXT0_SCL, I2CEXT0_SDA)`
|
||||
#for_each
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::format_ident;
|
||||
use quote::{format_ident, quote};
|
||||
|
||||
use crate::{cfg::SpiMasterProperties, generate_for_each_macro};
|
||||
|
||||
@ -32,18 +32,40 @@ pub(crate) fn generate_spi_master_peripherals(spi_slave: &SpiMasterProperties) -
|
||||
let sio = instance_config.sio.iter().map(|cs| format_ident!("{cs}"));
|
||||
|
||||
let is_qspi = if instance_config.sio.len() > 2 {
|
||||
quote::quote! { , true }
|
||||
quote! { , true }
|
||||
} else {
|
||||
quote::quote! {}
|
||||
quote! {}
|
||||
};
|
||||
|
||||
// The order and meaning of these tokens must match their use in the
|
||||
// `for_each_i2c_master!` call.
|
||||
quote::quote! {
|
||||
quote! {
|
||||
#instance, #sys, #sclk [#(#cs),*] [#(#sio),*] #is_qspi
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
generate_for_each_macro("spi_master", &instance_cfgs)
|
||||
let for_each = generate_for_each_macro("spi_master", &instance_cfgs);
|
||||
quote! {
|
||||
/// This macro can be used to generate code for each peripheral instance of the SPI master driver.
|
||||
///
|
||||
/// For an explanation on the general syntax, as well as usage of individual/repeated
|
||||
/// matchers, refer to [the crate-level documentation][crate#for_each-macros].
|
||||
///
|
||||
/// This macro has one option for its "Individual matcher" case:
|
||||
///
|
||||
/// Syntax: `($instance:ident, $sys:ident, $sclk:ident, [$($cs:ident),*] [$($sio:ident),* $($is_qspi:iteral)?])`
|
||||
///
|
||||
/// Macro fragments:
|
||||
///
|
||||
/// - `$instance`: the name of the SPI instance
|
||||
/// - `$sys`: the name of the instance as it is in the `esp_hal::system::Peripheral` enum.
|
||||
/// - `$cs`, `$sio`: chip select and SIO signal names.
|
||||
/// - `$is_qspi`: a `true` literal present if the SPI instance supports QSPI.
|
||||
///
|
||||
/// Example data:
|
||||
/// - `(SPI2, Spi2, FSPICLK [FSPICS0, FSPICS1, FSPICS2, FSPICS3, FSPICS4, FSPICS5] [FSPID, FSPIQ, FSPIWP, FSPIHD, FSPIIO4, FSPIIO5, FSPIIO6, FSPIIO7], true)`
|
||||
/// - `(SPI3, Spi3, SPI3_CLK [SPI3_CS0, SPI3_CS1, SPI3_CS2] [SPI3_D, SPI3_Q])`
|
||||
#for_each
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::format_ident;
|
||||
use quote::{format_ident, quote};
|
||||
|
||||
use crate::{cfg::SpiSlaveProperties, generate_for_each_macro};
|
||||
|
||||
@ -35,11 +35,30 @@ pub(crate) fn generate_spi_slave_peripherals(spi_slave: &SpiSlaveProperties) ->
|
||||
|
||||
// The order and meaning of these tokens must match their use in the
|
||||
// `for_each_i2c_master!` call.
|
||||
quote::quote! {
|
||||
quote! {
|
||||
#instance, #sys, #sclk, #mosi, #miso, #cs
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
generate_for_each_macro("spi_slave", &instance_cfgs)
|
||||
let for_each = generate_for_each_macro("spi_slave", &instance_cfgs);
|
||||
quote! {
|
||||
/// This macro can be used to generate code for each peripheral instance of the SPI slave driver.
|
||||
///
|
||||
/// For an explanation on the general syntax, as well as usage of individual/repeated
|
||||
/// matchers, refer to [the crate-level documentation][crate#for_each-macros].
|
||||
///
|
||||
/// This macro has one option for its "Individual matcher" case:
|
||||
///
|
||||
/// Syntax: `($instance:ident, $sys:ident, $sclk:ident, $mosi:ident, $miso:ident, $cs:ident)`
|
||||
///
|
||||
/// Macro fragments:
|
||||
///
|
||||
/// - `$instance`: the name of the I2C instance
|
||||
/// - `$sys`: the name of the instance as it is in the `esp_hal::system::Peripheral` enum.
|
||||
/// - `$mosi`, `$miso`, `$cs`: signal names.
|
||||
///
|
||||
/// Example data: `(SPI2, Spi2, FSPICLK, FSPID, FSPIQ, FSPICS0)`
|
||||
#for_each
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::format_ident;
|
||||
use quote::{format_ident, quote};
|
||||
|
||||
use crate::{cfg::UartProperties, generate_for_each_macro};
|
||||
|
||||
@ -42,11 +42,30 @@ pub(crate) fn generate_uart_peripherals(uart: &UartProperties) -> TokenStream {
|
||||
|
||||
// The order and meaning of these tokens must match their use in the
|
||||
// `for_each_uart!` call.
|
||||
quote::quote! {
|
||||
quote! {
|
||||
#instance, #sys, #rx, #tx, #cts, #rts
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
generate_for_each_macro("uart", &uart_instance_cfgs)
|
||||
let for_each = generate_for_each_macro("uart", &uart_instance_cfgs);
|
||||
quote! {
|
||||
/// This macro can be used to generate code for each peripheral instance of the UART driver.
|
||||
///
|
||||
/// For an explanation on the general syntax, as well as usage of individual/repeated
|
||||
/// matchers, refer to [the crate-level documentation][crate#for_each-macros].
|
||||
///
|
||||
/// This macro has one option for its "Individual matcher" case:
|
||||
///
|
||||
/// Syntax: `($instance:ident, $sys:ident, $rx:ident, $tx:ident, $cts:ident, $rts:ident)`
|
||||
///
|
||||
/// Macro fragments:
|
||||
///
|
||||
/// - `$instance`: the name of the UART instance
|
||||
/// - `$sys`: the name of the instance as it is in the `esp_hal::system::Peripheral` enum.
|
||||
/// - `$rx`, `$tx`, `$cts`, `$rts`: signal names.
|
||||
///
|
||||
/// Example data: `(UART0, Uart0, U0RXD, U0TXD, U0CTS, U0RTS)`
|
||||
#for_each
|
||||
}
|
||||
}
|
||||
|
@ -444,6 +444,7 @@ impl Config {
|
||||
#[doc = concat!("assert_eq!(chip_name, ", chip!(), ")")]
|
||||
/// ```
|
||||
#[macro_export]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
macro_rules! chip {
|
||||
() => { #chip_name };
|
||||
}
|
||||
@ -476,6 +477,7 @@ impl Config {
|
||||
tokens.extend(quote! {
|
||||
/// The properties of this chip and its drivers.
|
||||
#[macro_export]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
macro_rules! property {
|
||||
("chip") => { #chip_name };
|
||||
("arch") => { #arch };
|
||||
@ -501,6 +503,7 @@ impl Config {
|
||||
tokens.extend(quote! {
|
||||
/// Macro to get the address range of the given memory region.
|
||||
#[macro_export]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
macro_rules! memory_range {
|
||||
#(#region_branches)*
|
||||
}
|
||||
@ -636,6 +639,7 @@ fn generate_for_each_macro(name: &str, branches: &[TokenStream]) -> TokenStream
|
||||
// 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]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))]
|
||||
macro_rules! #macro_name {
|
||||
(
|
||||
$($pattern:tt => $code:tt;)*
|
||||
@ -707,7 +711,14 @@ pub fn generate_build_script_utils() -> TokenStream {
|
||||
);
|
||||
|
||||
quote! {
|
||||
// make it possible to build documentation without `std`.
|
||||
#[cfg(docsrs)]
|
||||
macro_rules! println {
|
||||
($($any:tt)*) => {};
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "build-script")))]
|
||||
pub enum Chip {
|
||||
#(#chip),*
|
||||
}
|
||||
@ -724,7 +735,10 @@ pub fn generate_build_script_utils() -> TokenStream {
|
||||
}
|
||||
|
||||
impl Chip {
|
||||
pub fn from_cargo_feature() -> Result<Self, Box<dyn std::error::Error>> {
|
||||
/// Tries to extract the active chip from the active cargo features.
|
||||
///
|
||||
/// Exactly one device feature must be enabled for this function to succeed.
|
||||
pub fn from_cargo_feature() -> Result<Self, &'static str> {
|
||||
let all_chips = [
|
||||
#(( #feature_env, Self::#chip )),*
|
||||
];
|
||||
@ -733,7 +747,7 @@ pub fn generate_build_script_utils() -> TokenStream {
|
||||
for (env, c) in all_chips {
|
||||
if std::env::var(env).is_ok() {
|
||||
if chip.is_some() {
|
||||
return Err(#bail_message.into());
|
||||
return Err(#bail_message);
|
||||
}
|
||||
chip = Some(c);
|
||||
}
|
||||
@ -741,50 +755,83 @@ pub fn generate_build_script_utils() -> TokenStream {
|
||||
|
||||
match chip {
|
||||
Some(chip) => Ok(chip),
|
||||
None => Err(#bail_message.into())
|
||||
None => Err(#bail_message)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns whether the current chip uses the Tensilica Xtensa ISA.
|
||||
pub fn is_xtensa(self) -> bool {
|
||||
self.config().architecture == "xtensa"
|
||||
}
|
||||
|
||||
/// The target triple of the current chip.
|
||||
pub fn target(self) -> &'static str {
|
||||
self.config().target
|
||||
}
|
||||
|
||||
/// The simple name of the current chip.
|
||||
///
|
||||
/// ## Example
|
||||
///
|
||||
/// ```rust
|
||||
/// assert_eq!(Chip::Esp32s3.name(), "esp32s3");
|
||||
/// ```
|
||||
pub fn name(self) -> &'static str {
|
||||
match self {
|
||||
#( Self::#chip => #name ),*
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns whether the chip configuration contains the given symbol.
|
||||
///
|
||||
/// This function is a short-hand for `self.all_symbols().contains(&symbol)`.
|
||||
///
|
||||
/// ## Example
|
||||
///
|
||||
/// ```rust
|
||||
/// assert!(Chip::Esp32s3.contains("soc_has_pcnt"));
|
||||
/// ```
|
||||
pub fn contains(self, symbol: &str) -> bool {
|
||||
self.config().contains(symbol)
|
||||
self.all_symbols().contains(&symbol)
|
||||
}
|
||||
|
||||
/// Calling this function will define all cfg symbols for the firmware crate to use.
|
||||
pub fn define_cfgs(self) {
|
||||
self.config().define_cfgs()
|
||||
}
|
||||
|
||||
/// Returns all symbols as a big slice.
|
||||
///
|
||||
/// ## Example
|
||||
///
|
||||
/// ```rust
|
||||
/// assert!(Chip::Esp32s3.all_symbols().contains("soc_has_pcnt"));
|
||||
/// ```
|
||||
pub fn all_symbols(&self) -> &'static [&'static str] {
|
||||
self.config().symbols
|
||||
}
|
||||
|
||||
/// Returns an iterator over all chips.
|
||||
///
|
||||
/// ## Example
|
||||
///
|
||||
/// ```rust
|
||||
/// assert!(Chip::iter().any(|c| c == Chip::Esp32));
|
||||
/// ```
|
||||
pub fn iter() -> impl Iterator<Item = Chip> {
|
||||
[
|
||||
#( Self::#chip ),*
|
||||
].into_iter()
|
||||
}
|
||||
|
||||
pub fn config(self) -> Config {
|
||||
fn config(self) -> Config {
|
||||
match self {
|
||||
#(Self::#chip => #config),*
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Config {
|
||||
struct Config {
|
||||
architecture: &'static str,
|
||||
target: &'static str,
|
||||
symbols: &'static [&'static str],
|
||||
@ -792,10 +839,6 @@ pub fn generate_build_script_utils() -> TokenStream {
|
||||
}
|
||||
|
||||
impl Config {
|
||||
fn contains(&self, symbol: &str) -> bool {
|
||||
self.symbols.contains(&symbol)
|
||||
}
|
||||
|
||||
fn define_cfgs(&self) {
|
||||
#(println!(#check_cfgs);)*
|
||||
|
||||
@ -818,11 +861,104 @@ pub fn generate_lib_rs() -> TokenStream {
|
||||
});
|
||||
|
||||
quote! {
|
||||
//! # (Generated) metadata for Espressif MCUs.
|
||||
//!
|
||||
//! This crate provides properties that are specific to various Espressif microcontrollers,
|
||||
//! and provides macros to work with peripherals, pins, and various other parts of the chips.
|
||||
//!
|
||||
//! This crate can be used both in firmware, as well as in build scripts, but the usage is different.
|
||||
//!
|
||||
//! ## Usage in build scripts
|
||||
//!
|
||||
//! To use the `Chip` enum, add the crate to your `Cargo.toml` build
|
||||
//! dependencies, with the `build-script` feature:
|
||||
//!
|
||||
//! ```toml
|
||||
//! [build-dependencies]
|
||||
//! esp-metadata-generated = { version = "...", features = ["build-script"] }
|
||||
//! ```
|
||||
//!
|
||||
//! ## Usage in firmware
|
||||
//!
|
||||
//! To use the various macros, add the crate to your `Cargo.toml` dependencies.
|
||||
//! A device-specific feature needs to be enabled in order to use the crate, usually
|
||||
//! picked by the user:
|
||||
//!
|
||||
//! ```toml
|
||||
//! [dependencies]
|
||||
//! esp-metadata-generated = { version = "..." }
|
||||
//! # ...
|
||||
//!
|
||||
//! [features]
|
||||
//! esp32 = ["esp-metadata-generated/esp32"]
|
||||
//! esp32c2 = ["esp-metadata-generated/esp32c2"]
|
||||
//! # ...
|
||||
//! ```
|
||||
//!
|
||||
//! ## `for_each` macros
|
||||
//!
|
||||
//! The basic syntax of this macro looks like a macro definition with two distinct syntax options:
|
||||
//!
|
||||
//! ```rust, no_run
|
||||
//! for_each_peripherals! {
|
||||
//! // Individual matcher, invoked separately for each peripheral instance
|
||||
//! ( <individual match syntax> ) => { /* some code */ };
|
||||
//!
|
||||
//! // Repeated matcher, invoked once with all peripheral instances
|
||||
//! ( all $( (<individual match syntax>) ),* ) => { /* some code */ };
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
//! You can specify any number of matchers in the same invocation.
|
||||
//!
|
||||
//! ### Using the individual matcher
|
||||
//!
|
||||
//! In this use case, each item's data is individually passed through the macro. This can be used to
|
||||
//! generate code for each item separately, allowing specializing the implementation where needed.
|
||||
//!
|
||||
//! ```rust,no_run
|
||||
//! for_each_gpio! {
|
||||
//! // Example data: `(0, GPIO0 (_5 => EMAC_TX_CLK) (_1 => CLK_OUT1 _5 => EMAC_TX_CLK) (Input Output))`
|
||||
//! ($n:literal, $gpio:ident ($($digital_input_function:ident => $digital_input_signal:ident)*) ($($digital_output_function:ident => $digital_output_signal:ident)*) ($($pin_attribute:ident)*)) => { /* some code */ };
|
||||
//!
|
||||
//! // You can create matchers with data filled in. This example will specifically match GPIO2
|
||||
//! ($n:literal, GPIO2 $input_af:tt $output_af:tt $attributes:tt) => { /* Additional case only for GPIO2 */ };
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
//! Different macros can have multiple different syntax options for their individual matchers, usually
|
||||
//! to provide more detailed information, while preserving simpler syntax for more basic use cases.
|
||||
//! Consult each macro's documentation for available options.
|
||||
//!
|
||||
//! ### Repeated matcher
|
||||
//!
|
||||
//! With this option, all data is passed through the macro all at once. This form can be used to,
|
||||
//! for example, generate struct fields. If the macro has multiple individual matcher options,
|
||||
//! the repeated matcher will contain each item's data multiple times, once for each available
|
||||
//! syntax option. Currently, using the repeated matcher is not recommended for these macros.
|
||||
//!
|
||||
//! > This issue will be likely resolved by naming the different syntax options, and providing
|
||||
//! > different match arms for each in place of `all`.
|
||||
//!
|
||||
//! ```rust,no_run
|
||||
//! // Example usage to create a struct containing all GPIOs:
|
||||
//! for_each_gpio! {
|
||||
//! (all $( ($n:literal, $gpio:ident $_af_ins:tt $_af_outs:tt $_attrs:tt) ),*) => {
|
||||
//! struct Gpios {
|
||||
//! $(
|
||||
//! #[doc = concat!(" The ", stringify!($n), "th GPIO pin")]
|
||||
//! pub $gpio: Gpio<$n>,
|
||||
//! )*
|
||||
//! }
|
||||
//! };
|
||||
//! }
|
||||
//! ```
|
||||
#![cfg_attr(docsrs, feature(doc_cfg))]
|
||||
#![cfg_attr(not(feature = "build-script"), no_std)]
|
||||
|
||||
#(#chips)*
|
||||
|
||||
#[cfg(feature = "build-script")]
|
||||
#[cfg(any(feature = "build-script", docsrs))]
|
||||
include!( "_build_script_utils.rs");
|
||||
}
|
||||
}
|
||||
|
@ -564,7 +564,10 @@ 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);
|
||||
let mut source = String::from(
|
||||
"// Do NOT edit this file directly. Make your changes to esp-metadata,\n// then run `cargo xtask update-metadata`.\n\n",
|
||||
);
|
||||
source.push_str(&prettyplease::unparse(&syntax_tree));
|
||||
|
||||
std::fs::write(out_path, source)?;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user