mirror of
https://github.com/esp-rs/esp-hal.git
synced 2025-10-02 14:44:42 +00:00
Generate i2c instances from metadata (#3678)
This commit is contained in:
parent
c71cbcd2c3
commit
c72889a73d
@ -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) => {
|
($inst:ident, $peri:ident, $scl:ident, $sda:ident, $interrupt:ident) => {
|
||||||
impl Instance for crate::peripherals::$inst<'_> {
|
impl Instance for crate::peripherals::$inst<'_> {
|
||||||
fn parts(&self) -> (&Info, &State) {
|
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! {
|
crate::any_peripheral! {
|
||||||
/// Any I2C peripheral.
|
/// Any I2C peripheral.
|
||||||
|
@ -122,4 +122,5 @@ crate::peripherals! {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
include!(concat!(env!("OUT_DIR"), "/_generated_peris.rs"));
|
||||||
include!(concat!(env!("OUT_DIR"), "/_generated_gpio.rs"));
|
include!(concat!(env!("OUT_DIR"), "/_generated_gpio.rs"));
|
||||||
|
@ -82,4 +82,5 @@ crate::peripherals! {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
include!(concat!(env!("OUT_DIR"), "/_generated_peris.rs"));
|
||||||
include!(concat!(env!("OUT_DIR"), "/_generated_gpio.rs"));
|
include!(concat!(env!("OUT_DIR"), "/_generated_gpio.rs"));
|
||||||
|
@ -100,4 +100,5 @@ crate::peripherals! {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
include!(concat!(env!("OUT_DIR"), "/_generated_peris.rs"));
|
||||||
include!(concat!(env!("OUT_DIR"), "/_generated_gpio.rs"));
|
include!(concat!(env!("OUT_DIR"), "/_generated_gpio.rs"));
|
||||||
|
@ -145,4 +145,5 @@ crate::peripherals! {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
include!(concat!(env!("OUT_DIR"), "/_generated_peris.rs"));
|
||||||
include!(concat!(env!("OUT_DIR"), "/_generated_gpio.rs"));
|
include!(concat!(env!("OUT_DIR"), "/_generated_gpio.rs"));
|
||||||
|
@ -130,4 +130,5 @@ crate::peripherals! {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
include!(concat!(env!("OUT_DIR"), "/_generated_peris.rs"));
|
||||||
include!(concat!(env!("OUT_DIR"), "/_generated_gpio.rs"));
|
include!(concat!(env!("OUT_DIR"), "/_generated_gpio.rs"));
|
||||||
|
@ -129,4 +129,5 @@ crate::peripherals! {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
include!(concat!(env!("OUT_DIR"), "/_generated_peris.rs"));
|
||||||
include!(concat!(env!("OUT_DIR"), "/_generated_gpio.rs"));
|
include!(concat!(env!("OUT_DIR"), "/_generated_gpio.rs"));
|
||||||
|
@ -138,4 +138,5 @@ crate::peripherals! {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
include!(concat!(env!("OUT_DIR"), "/_generated_peris.rs"));
|
||||||
include!(concat!(env!("OUT_DIR"), "/_generated_gpio.rs"));
|
include!(concat!(env!("OUT_DIR"), "/_generated_gpio.rs"));
|
||||||
|
@ -551,7 +551,10 @@ output_signals = [
|
|||||||
|
|
||||||
[device.i2c_master]
|
[device.i2c_master]
|
||||||
support_status = "supported"
|
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
|
ll_intr_mask = 0x3ffff
|
||||||
fifo_size = 32
|
fifo_size = 32
|
||||||
max_bus_timeout = 0xFFFFF
|
max_bus_timeout = 0xFFFFF
|
||||||
|
@ -195,7 +195,9 @@ output_signals = [
|
|||||||
|
|
||||||
[device.i2c_master]
|
[device.i2c_master]
|
||||||
support_status = "supported"
|
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_fsm_timeouts = true
|
||||||
has_hw_bus_clear = true
|
has_hw_bus_clear = true
|
||||||
ll_intr_mask = 0x3ffff
|
ll_intr_mask = 0x3ffff
|
||||||
|
@ -244,7 +244,9 @@ output_signals = [
|
|||||||
|
|
||||||
[device.i2c_master]
|
[device.i2c_master]
|
||||||
support_status = "supported"
|
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_fsm_timeouts = true
|
||||||
has_hw_bus_clear = true
|
has_hw_bus_clear = true
|
||||||
ll_intr_mask = 0x3ffff
|
ll_intr_mask = 0x3ffff
|
||||||
|
@ -367,7 +367,9 @@ output_signals = [
|
|||||||
|
|
||||||
[device.i2c_master]
|
[device.i2c_master]
|
||||||
support_status = "supported"
|
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_fsm_timeouts = true
|
||||||
has_hw_bus_clear = true
|
has_hw_bus_clear = true
|
||||||
ll_intr_mask = 0x3ffff
|
ll_intr_mask = 0x3ffff
|
||||||
|
@ -311,7 +311,10 @@ output_signals = [
|
|||||||
|
|
||||||
[device.i2c_master]
|
[device.i2c_master]
|
||||||
support_status = "supported"
|
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_fsm_timeouts = true
|
||||||
has_hw_bus_clear = true
|
has_hw_bus_clear = true
|
||||||
ll_intr_mask = 0x3ffff
|
ll_intr_mask = 0x3ffff
|
||||||
|
@ -337,7 +337,10 @@ output_signals = [
|
|||||||
]
|
]
|
||||||
[device.i2c_master]
|
[device.i2c_master]
|
||||||
support_status = "supported"
|
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
|
ll_intr_mask = 0x1ffff
|
||||||
fifo_size = 32
|
fifo_size = 32
|
||||||
has_bus_timeout_enable = true
|
has_bus_timeout_enable = true
|
||||||
|
@ -485,7 +485,10 @@ output_signals = [
|
|||||||
|
|
||||||
[device.i2c_master]
|
[device.i2c_master]
|
||||||
support_status = "supported"
|
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_fsm_timeouts = true
|
||||||
has_hw_bus_clear = true
|
has_hw_bus_clear = true
|
||||||
ll_intr_mask = 0x3ffff
|
ll_intr_mask = 0x3ffff
|
||||||
|
@ -49,6 +49,14 @@ impl SupportStatus {
|
|||||||
#[derive(Debug, Default, Clone, serde::Deserialize, serde::Serialize)]
|
#[derive(Debug, Default, Clone, serde::Deserialize, serde::Serialize)]
|
||||||
pub(crate) struct EmptyInstanceConfig {}
|
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)]
|
#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
|
||||||
#[serde(rename_all = "snake_case")]
|
#[serde(rename_all = "snake_case")]
|
||||||
pub(crate) enum PinCapability {
|
pub(crate) enum PinCapability {
|
||||||
@ -349,7 +357,7 @@ driver_configs![
|
|||||||
peripherals: &["hmac"],
|
peripherals: &["hmac"],
|
||||||
properties: {}
|
properties: {}
|
||||||
},
|
},
|
||||||
I2cMasterProperties {
|
I2cMasterProperties<I2cMasterInstanceConfig> {
|
||||||
driver: i2c_master,
|
driver: i2c_master,
|
||||||
name: "I2C master",
|
name: "I2C master",
|
||||||
peripherals: &["i2c0", "i2c1"],
|
peripherals: &["i2c0", "i2c1"],
|
||||||
|
@ -375,6 +375,7 @@ impl Config {
|
|||||||
self.generate_properties(out_dir, "_generated.rs");
|
self.generate_properties(out_dir, "_generated.rs");
|
||||||
self.generate_gpios(out_dir, "_generated_gpio.rs");
|
self.generate_gpios(out_dir, "_generated_gpio.rs");
|
||||||
self.generate_gpio_extras(out_dir, "_generated_gpio_extras.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) {
|
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 io_mux_accessor = if gpio.remap_iomux_pin_registers {
|
||||||
let iomux_pin_regs = gpio.pins_and_signals.pins.iter().map(|pin| {
|
let iomux_pin_regs = gpio.pins_and_signals.pins.iter().map(|pin| {
|
||||||
let pin = number(pin.pin);
|
let pin = number(pin.pin);
|
||||||
let reg = quote::format_ident!("GPIO{pin}");
|
let reg = format_ident!("GPIO{pin}");
|
||||||
let accessor = quote::format_ident!("gpio{pin}");
|
let accessor = format_ident!("gpio{pin}");
|
||||||
|
|
||||||
quote::quote! { #pin => transmute::<&'static io_mux::#reg, &'static io_mux::GPIO0>(iomux.#accessor()), }
|
quote::quote! { #pin => transmute::<&'static io_mux::#reg, &'static io_mux::GPIO0>(iomux.#accessor()), }
|
||||||
});
|
});
|
||||||
@ -728,6 +729,43 @@ impl Config {
|
|||||||
|
|
||||||
save(&out_file, g);
|
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::<Vec<_>>();
|
||||||
|
|
||||||
|
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 {
|
fn render_signals(enum_name: &str, signals: &[IoMuxSignal]) -> TokenStream {
|
||||||
@ -743,7 +781,7 @@ fn render_signals(enum_name: &str, signals: &[IoMuxSignal]) -> TokenStream {
|
|||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
|
||||||
let name = quote::format_ident!("{}", signal.name);
|
let name = format_ident!("{}", signal.name);
|
||||||
let value = number(id);
|
let value = number(id);
|
||||||
variants.push(quote::quote! {
|
variants.push(quote::quote! {
|
||||||
#name = #value,
|
#name = #value,
|
||||||
@ -756,13 +794,13 @@ fn render_signals(enum_name: &str, signals: &[IoMuxSignal]) -> TokenStream {
|
|||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
|
||||||
let name = quote::format_ident!("{}", signal.name);
|
let name = format_ident!("{}", signal.name);
|
||||||
variants.push(quote::quote! {
|
variants.push(quote::quote! {
|
||||||
#name,
|
#name,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
let enum_name = quote::format_ident!("{enum_name}");
|
let enum_name = format_ident!("{enum_name}");
|
||||||
|
|
||||||
quote::quote! {
|
quote::quote! {
|
||||||
#[allow(non_camel_case_types, clippy::upper_case_acronyms)]
|
#[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<Path>, tokens: TokenStream) {
|
fn save(path: impl AsRef<Path>, tokens: TokenStream) {
|
||||||
let source = tokens.to_string();
|
let source = tokens.to_string();
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user