diff --git a/esp-hal/src/i2c/master/mod.rs b/esp-hal/src/i2c/master/mod.rs index ebd5bf501..f4797c336 100644 --- a/esp-hal/src/i2c/master/mod.rs +++ b/esp-hal/src/i2c/master/mod.rs @@ -3114,7 +3114,7 @@ fn estimate_ack_failed_reason(_register_block: &RegisterBlock) -> AcknowledgeChe } } -macro_rules! instance { +crate::peripherals::for_each_i2c_master!( ($inst:ident, $peri:ident, $scl:ident, $sda:ident, $interrupt:ident) => { impl Instance for crate::peripherals::$inst<'_> { fn parts(&self) -> (&Info, &State) { @@ -3141,12 +3141,7 @@ macro_rules! instance { } } }; -} - -#[cfg(i2c_master_i2c0)] -instance!(I2C0, I2cExt0, I2CEXT0_SCL, I2CEXT0_SDA, I2C_EXT0); -#[cfg(i2c_master_i2c1)] -instance!(I2C1, I2cExt1, I2CEXT1_SCL, I2CEXT1_SDA, I2C_EXT1); +); crate::any_peripheral! { /// Any I2C peripheral. diff --git a/esp-hal/src/soc/esp32/peripherals.rs b/esp-hal/src/soc/esp32/peripherals.rs index 5ac75142d..854cc4dd7 100644 --- a/esp-hal/src/soc/esp32/peripherals.rs +++ b/esp-hal/src/soc/esp32/peripherals.rs @@ -122,4 +122,5 @@ crate::peripherals! { ] } +include!(concat!(env!("OUT_DIR"), "/_generated_peris.rs")); include!(concat!(env!("OUT_DIR"), "/_generated_gpio.rs")); diff --git a/esp-hal/src/soc/esp32c2/peripherals.rs b/esp-hal/src/soc/esp32c2/peripherals.rs index 3297c0266..8509a13eb 100644 --- a/esp-hal/src/soc/esp32c2/peripherals.rs +++ b/esp-hal/src/soc/esp32c2/peripherals.rs @@ -82,4 +82,5 @@ crate::peripherals! { ] } +include!(concat!(env!("OUT_DIR"), "/_generated_peris.rs")); include!(concat!(env!("OUT_DIR"), "/_generated_gpio.rs")); diff --git a/esp-hal/src/soc/esp32c3/peripherals.rs b/esp-hal/src/soc/esp32c3/peripherals.rs index 0646ff2d5..261a8afe5 100644 --- a/esp-hal/src/soc/esp32c3/peripherals.rs +++ b/esp-hal/src/soc/esp32c3/peripherals.rs @@ -100,4 +100,5 @@ crate::peripherals! { ] } +include!(concat!(env!("OUT_DIR"), "/_generated_peris.rs")); include!(concat!(env!("OUT_DIR"), "/_generated_gpio.rs")); diff --git a/esp-hal/src/soc/esp32c6/peripherals.rs b/esp-hal/src/soc/esp32c6/peripherals.rs index f3ceaa8f9..3aae03cc5 100644 --- a/esp-hal/src/soc/esp32c6/peripherals.rs +++ b/esp-hal/src/soc/esp32c6/peripherals.rs @@ -145,4 +145,5 @@ crate::peripherals! { ] } +include!(concat!(env!("OUT_DIR"), "/_generated_peris.rs")); include!(concat!(env!("OUT_DIR"), "/_generated_gpio.rs")); diff --git a/esp-hal/src/soc/esp32h2/peripherals.rs b/esp-hal/src/soc/esp32h2/peripherals.rs index ba285e48f..c9aa606b3 100644 --- a/esp-hal/src/soc/esp32h2/peripherals.rs +++ b/esp-hal/src/soc/esp32h2/peripherals.rs @@ -130,4 +130,5 @@ crate::peripherals! { ] } +include!(concat!(env!("OUT_DIR"), "/_generated_peris.rs")); include!(concat!(env!("OUT_DIR"), "/_generated_gpio.rs")); diff --git a/esp-hal/src/soc/esp32s2/peripherals.rs b/esp-hal/src/soc/esp32s2/peripherals.rs index 4fece2434..e2ed42fe4 100644 --- a/esp-hal/src/soc/esp32s2/peripherals.rs +++ b/esp-hal/src/soc/esp32s2/peripherals.rs @@ -129,4 +129,5 @@ crate::peripherals! { ] } +include!(concat!(env!("OUT_DIR"), "/_generated_peris.rs")); include!(concat!(env!("OUT_DIR"), "/_generated_gpio.rs")); diff --git a/esp-hal/src/soc/esp32s3/peripherals.rs b/esp-hal/src/soc/esp32s3/peripherals.rs index cf7a94bd2..0ef7a08cd 100644 --- a/esp-hal/src/soc/esp32s3/peripherals.rs +++ b/esp-hal/src/soc/esp32s3/peripherals.rs @@ -138,4 +138,5 @@ crate::peripherals! { ] } +include!(concat!(env!("OUT_DIR"), "/_generated_peris.rs")); include!(concat!(env!("OUT_DIR"), "/_generated_gpio.rs")); diff --git a/esp-metadata/devices/esp32.toml b/esp-metadata/devices/esp32.toml index 7164c0900..45aa5aae9 100644 --- a/esp-metadata/devices/esp32.toml +++ b/esp-metadata/devices/esp32.toml @@ -551,7 +551,10 @@ output_signals = [ [device.i2c_master] support_status = "supported" -instances = [{ name = "i2c0" }, { name = "i2c1" }] +instances = [ + { name = "i2c0", sys_instance = "I2cExt0", scl = "I2CEXT0_SCL", sda = "I2CEXT0_SDA", interrupt = "I2C_EXT0" }, + { name = "i2c1", sys_instance = "I2cExt1", scl = "I2CEXT1_SCL", sda = "I2CEXT1_SDA", interrupt = "I2C_EXT1" }, +] ll_intr_mask = 0x3ffff fifo_size = 32 max_bus_timeout = 0xFFFFF diff --git a/esp-metadata/devices/esp32c2.toml b/esp-metadata/devices/esp32c2.toml index b1504eb47..d18ff7a83 100644 --- a/esp-metadata/devices/esp32c2.toml +++ b/esp-metadata/devices/esp32c2.toml @@ -195,7 +195,9 @@ output_signals = [ [device.i2c_master] support_status = "supported" -instances = [{ name = "i2c0" }] +instances = [ + { name = "i2c0", sys_instance = "I2cExt0", scl = "I2CEXT0_SCL", sda = "I2CEXT0_SDA", interrupt = "I2C_EXT0" }, +] has_fsm_timeouts = true has_hw_bus_clear = true ll_intr_mask = 0x3ffff diff --git a/esp-metadata/devices/esp32c3.toml b/esp-metadata/devices/esp32c3.toml index f587e4a49..1a47c90aa 100644 --- a/esp-metadata/devices/esp32c3.toml +++ b/esp-metadata/devices/esp32c3.toml @@ -244,7 +244,9 @@ output_signals = [ [device.i2c_master] support_status = "supported" -instances = [{ name = "i2c0" }] +instances = [ + { name = "i2c0", sys_instance = "I2cExt0", scl = "I2CEXT0_SCL", sda = "I2CEXT0_SDA", interrupt = "I2C_EXT0" }, +] has_fsm_timeouts = true has_hw_bus_clear = true ll_intr_mask = 0x3ffff diff --git a/esp-metadata/devices/esp32c6.toml b/esp-metadata/devices/esp32c6.toml index c22e4ad13..f20a73b99 100644 --- a/esp-metadata/devices/esp32c6.toml +++ b/esp-metadata/devices/esp32c6.toml @@ -367,7 +367,9 @@ output_signals = [ [device.i2c_master] support_status = "supported" -instances = [{ name = "i2c0" }] +instances = [ + { name = "i2c0", sys_instance = "I2cExt0", scl = "I2CEXT0_SCL", sda = "I2CEXT0_SDA", interrupt = "I2C_EXT0" }, +] has_fsm_timeouts = true has_hw_bus_clear = true ll_intr_mask = 0x3ffff diff --git a/esp-metadata/devices/esp32h2.toml b/esp-metadata/devices/esp32h2.toml index b7211cd57..98d93af1d 100644 --- a/esp-metadata/devices/esp32h2.toml +++ b/esp-metadata/devices/esp32h2.toml @@ -311,7 +311,10 @@ output_signals = [ [device.i2c_master] support_status = "supported" -instances = [{ name = "i2c0" }, { name = "i2c1" }] +instances = [ + { name = "i2c0", sys_instance = "I2cExt0", scl = "I2CEXT0_SCL", sda = "I2CEXT0_SDA", interrupt = "I2C_EXT0" }, + { name = "i2c1", sys_instance = "I2cExt1", scl = "I2CEXT1_SCL", sda = "I2CEXT1_SDA", interrupt = "I2C_EXT1" }, +] has_fsm_timeouts = true has_hw_bus_clear = true ll_intr_mask = 0x3ffff diff --git a/esp-metadata/devices/esp32s2.toml b/esp-metadata/devices/esp32s2.toml index 0bb5eea06..64b100d9b 100644 --- a/esp-metadata/devices/esp32s2.toml +++ b/esp-metadata/devices/esp32s2.toml @@ -337,7 +337,10 @@ output_signals = [ ] [device.i2c_master] support_status = "supported" -instances = [{ name = "i2c0" }, { name = "i2c1" }] +instances = [ + { name = "i2c0", sys_instance = "I2cExt0", scl = "I2CEXT0_SCL", sda = "I2CEXT0_SDA", interrupt = "I2C_EXT0" }, + { name = "i2c1", sys_instance = "I2cExt1", scl = "I2CEXT1_SCL", sda = "I2CEXT1_SDA", interrupt = "I2C_EXT1" }, +] ll_intr_mask = 0x1ffff fifo_size = 32 has_bus_timeout_enable = true diff --git a/esp-metadata/devices/esp32s3.toml b/esp-metadata/devices/esp32s3.toml index b81824c3c..4fdc8b008 100644 --- a/esp-metadata/devices/esp32s3.toml +++ b/esp-metadata/devices/esp32s3.toml @@ -485,7 +485,10 @@ output_signals = [ [device.i2c_master] support_status = "supported" -instances = [{ name = "i2c0" }, { name = "i2c1" }] +instances = [ + { name = "i2c0", sys_instance = "I2cExt0", scl = "I2CEXT0_SCL", sda = "I2CEXT0_SDA", interrupt = "I2C_EXT0" }, + { name = "i2c1", sys_instance = "I2cExt1", scl = "I2CEXT1_SCL", sda = "I2CEXT1_SDA", interrupt = "I2C_EXT1" }, +] has_fsm_timeouts = true has_hw_bus_clear = true ll_intr_mask = 0x3ffff diff --git a/esp-metadata/src/cfg.rs b/esp-metadata/src/cfg.rs index 59559f059..b712847c1 100644 --- a/esp-metadata/src/cfg.rs +++ b/esp-metadata/src/cfg.rs @@ -49,6 +49,14 @@ impl SupportStatus { #[derive(Debug, Default, Clone, serde::Deserialize, serde::Serialize)] pub(crate) struct EmptyInstanceConfig {} +#[derive(Debug, Default, Clone, serde::Deserialize, serde::Serialize)] +pub(crate) struct I2cMasterInstanceConfig { + pub sys_instance: String, + pub scl: String, + pub sda: String, + pub interrupt: String, +} + #[derive(Debug, Clone, serde::Deserialize, serde::Serialize)] #[serde(rename_all = "snake_case")] pub(crate) enum PinCapability { @@ -349,7 +357,7 @@ driver_configs![ peripherals: &["hmac"], properties: {} }, - I2cMasterProperties { + I2cMasterProperties { driver: i2c_master, name: "I2C master", peripherals: &["i2c0", "i2c1"], diff --git a/esp-metadata/src/lib.rs b/esp-metadata/src/lib.rs index 88c3d40da..3b4aea0a5 100644 --- a/esp-metadata/src/lib.rs +++ b/esp-metadata/src/lib.rs @@ -375,6 +375,7 @@ impl Config { self.generate_properties(out_dir, "_generated.rs"); self.generate_gpios(out_dir, "_generated_gpio.rs"); self.generate_gpio_extras(out_dir, "_generated_gpio_extras.rs"); + self.generate_peripherals(out_dir, "_generated_peris.rs"); } fn generate_properties(&self, out_dir: &Path, file_name: &str) { @@ -597,8 +598,8 @@ impl Config { let io_mux_accessor = if gpio.remap_iomux_pin_registers { let iomux_pin_regs = gpio.pins_and_signals.pins.iter().map(|pin| { let pin = number(pin.pin); - let reg = quote::format_ident!("GPIO{pin}"); - let accessor = quote::format_ident!("gpio{pin}"); + let reg = format_ident!("GPIO{pin}"); + let accessor = format_ident!("gpio{pin}"); quote::quote! { #pin => transmute::<&'static io_mux::#reg, &'static io_mux::GPIO0>(iomux.#accessor()), } }); @@ -728,6 +729,43 @@ impl Config { save(&out_file, g); } + + fn generate_peripherals(&self, out_dir: &Path, file_name: &str) { + let out_file = out_dir.join(file_name).to_string_lossy().to_string(); + + let i2c_master_instance_cfgs = self + .device + .peri_config + .i2c_master + .iter() + .flat_map(|peri| { + peri.instances.iter().map(|instance| { + let instance_config = &instance.instance_config; + + let instance = format_ident!("{}", instance.name.to_uppercase()); + + let sys = format_ident!("{}", instance_config.sys_instance); + let sda = format_ident!("{}", instance_config.sda); + let scl = format_ident!("{}", instance_config.scl); + let int = format_ident!("{}", instance_config.interrupt); + + // The order and meaning of these tokens must match their use in the + // `for_each_i2c_master!` call. + quote::quote! { + #instance, #sys, #scl, #sda, #int + } + }) + }) + .collect::>(); + + let for_each_i2c_master = generate_for_each_macro("i2c_master", &i2c_master_instance_cfgs); + + let g = quote::quote! { + #for_each_i2c_master + }; + + save(&out_file, g); + } } fn render_signals(enum_name: &str, signals: &[IoMuxSignal]) -> TokenStream { @@ -743,7 +781,7 @@ fn render_signals(enum_name: &str, signals: &[IoMuxSignal]) -> TokenStream { continue; }; - let name = quote::format_ident!("{}", signal.name); + let name = format_ident!("{}", signal.name); let value = number(id); variants.push(quote::quote! { #name = #value, @@ -756,13 +794,13 @@ fn render_signals(enum_name: &str, signals: &[IoMuxSignal]) -> TokenStream { continue; }; - let name = quote::format_ident!("{}", signal.name); + let name = format_ident!("{}", signal.name); variants.push(quote::quote! { #name, }); } - let enum_name = quote::format_ident!("{enum_name}"); + let enum_name = format_ident!("{enum_name}"); quote::quote! { #[allow(non_camel_case_types, clippy::upper_case_acronyms)] @@ -775,6 +813,28 @@ fn render_signals(enum_name: &str, signals: &[IoMuxSignal]) -> TokenStream { } } +fn generate_for_each_macro(name: &str, branches: &[TokenStream]) -> TokenStream { + let macro_name = format_ident!("for_each_{name}"); + quote::quote! { + // This macro is called in esp-hal to implement a driver's + // Instance trait for available peripherals. It works by defining, then calling an inner + // macro that substitutes the properties into the template provided by the call in esp-hal. + macro_rules! #macro_name { + ( + $pattern:tt => $code:tt; + ) => { + macro_rules! _for_each_inner { + ($pattern) => $code; + } + + #(_for_each_inner!(( #branches ));)* + }; + } + + pub(crate) use #macro_name; + } +} + fn save(path: impl AsRef, tokens: TokenStream) { let source = tokens.to_string();