From 21dd55b69ed2418f62a86185b52d6c7df9d6292b Mon Sep 17 00:00:00 2001 From: i509VCB Date: Sat, 25 Oct 2025 13:14:06 -0500 Subject: nxp: generate all chip peripherals and impls from metadata --- embassy-nxp/CHANGELOG.md | 1 + embassy-nxp/Cargo.toml | 4 +- embassy-nxp/build.rs | 353 ++++++++++++++++++++++++++++--- embassy-nxp/src/chips/lpc55.rs | 127 +---------- embassy-nxp/src/chips/mimxrt1011.rs | 104 +-------- embassy-nxp/src/chips/mimxrt1062.rs | 273 +----------------------- embassy-nxp/src/dma.rs | 1 + embassy-nxp/src/dma/lpc55.rs | 47 ++-- embassy-nxp/src/gpio/lpc55.rs | 93 ++------ embassy-nxp/src/gpio/rt1xxx.rs | 50 ++--- embassy-nxp/src/iomuxc.rs | 29 +++ embassy-nxp/src/lib.rs | 16 +- embassy-nxp/src/pwm.rs | 2 + embassy-nxp/src/pwm/lpc55.rs | 113 ++-------- embassy-nxp/src/sct.rs | 56 +++++ embassy-nxp/src/usart.rs | 2 + embassy-nxp/src/usart/lpc55.rs | 115 ++++------ examples/lpc55s69/src/bin/pwm.rs | 2 +- examples/lpc55s69/src/bin/usart_async.rs | 4 +- 19 files changed, 549 insertions(+), 843 deletions(-) create mode 100644 embassy-nxp/src/iomuxc.rs create mode 100644 embassy-nxp/src/sct.rs diff --git a/embassy-nxp/CHANGELOG.md b/embassy-nxp/CHANGELOG.md index 39f5c75bd..e6f117da4 100644 --- a/embassy-nxp/CHANGELOG.md +++ b/embassy-nxp/CHANGELOG.md @@ -7,6 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased - ReleaseDate +- Codegen using `nxp-pac` metadata - LPC55: PWM simple - LPC55: Move ALT definitions for USART to TX/RX pin impls. - LPC55: Remove internal match_iocon macro diff --git a/embassy-nxp/Cargo.toml b/embassy-nxp/Cargo.toml index f8c63ba29..b78c26c77 100644 --- a/embassy-nxp/Cargo.toml +++ b/embassy-nxp/Cargo.toml @@ -38,13 +38,13 @@ embassy-time-queue-utils = { version = "0.3.0", path = "../embassy-time-queue-ut embedded-io = "0.6.1" embedded-hal-02 = { package = "embedded-hal", version = "0.2.6", features = ["unproven"] } ## Chip dependencies -nxp-pac = { version = "0.1.0", optional = true, git = "https://github.com/i509VCB/nxp-pac", rev = "477dfdbfd5e6c75c0730c56494b601c1b2257263"} +nxp-pac = { version = "0.1.0", optional = true, git = "https://github.com/i509VCB/nxp-pac", rev = "af5122e1cbe1483833c5d2e5af96b26a34ed5d62"} imxrt-rt = { version = "0.1.7", optional = true, features = ["device"] } [build-dependencies] cfg_aliases = "0.2.1" -nxp-pac = { version = "0.1.0", git = "https://github.com/i509VCB/nxp-pac", rev = "477dfdbfd5e6c75c0730c56494b601c1b2257263", features = ["metadata"], optional = true } +nxp-pac = { version = "0.1.0", git = "https://github.com/i509VCB/nxp-pac", rev = "af5122e1cbe1483833c5d2e5af96b26a34ed5d62", features = ["metadata"], optional = true } proc-macro2 = "1.0.95" quote = "1.0.15" diff --git a/embassy-nxp/build.rs b/embassy-nxp/build.rs index f3c062c87..f53c29161 100644 --- a/embassy-nxp/build.rs +++ b/embassy-nxp/build.rs @@ -4,10 +4,12 @@ use std::process::Command; use std::{env, fs}; use cfg_aliases::cfg_aliases; -#[cfg(feature = "_rt1xxx")] use nxp_pac::metadata; +use nxp_pac::metadata::{METADATA, Peripheral}; #[allow(unused)] use proc_macro2::TokenStream; +use proc_macro2::{Ident, Literal, Span}; +use quote::format_ident; #[allow(unused)] use quote::quote; @@ -31,56 +33,188 @@ fn main() { .unwrap() .to_ascii_lowercase(); + let singletons = singletons(&mut cfgs); + cfg_aliases! { rt1xxx: { any(feature = "mimxrt1011", feature = "mimxrt1062") }, - gpio1: { any(feature = "mimxrt1011", feature = "mimxrt1062") }, - gpio2: { any(feature = "mimxrt1011", feature = "mimxrt1062") }, - gpio3: { feature = "mimxrt1062" }, - gpio4: { feature = "mimxrt1062" }, - gpio5: { any(feature = "mimxrt1011", feature = "mimxrt1062") }, } eprintln!("chip: {chip_name}"); - generate_code(); + generate_code(&mut cfgs, &singletons); } -#[cfg(feature = "_rt1xxx")] -fn generate_iomuxc() -> TokenStream { - use proc_macro2::{Ident, Span}; +/// A peripheral singleton returned by `embassy_nxp::init`. +struct Singleton { + name: String, - let pads = metadata::iomuxc::IOMUXC_REGISTERS.iter().map(|registers| { - let name = Ident::new(®isters.name, Span::call_site()); - let address = registers.pad_ctl; + /// A cfg guard which indicates whether the `Peripherals` struct will give the user this singleton. + cfg: Option, +} - quote! { - pub const #name: u32 = #address; +fn singletons(cfgs: &mut common::CfgSet) -> Vec { + let mut singletons = Vec::new(); + + for peripheral in METADATA.peripherals { + // GPIO and DMA are generated in a 2nd pass. + let skip_singleton = if peripheral.name.starts_with("GPIO") || peripheral.name.starts_with("DMA") { + true + } else { + false + }; + + if !skip_singleton { + singletons.push(Singleton { + name: peripheral.name.into(), + cfg: None, + }); } - }); + } - let muxes = metadata::iomuxc::IOMUXC_REGISTERS.iter().map(|registers| { - let name = Ident::new(®isters.name, Span::call_site()); - let address = registers.mux_ctl; + cfgs.declare_all(&[ + "gpio1", + "gpio1_hi", + "gpio2", + "gpio2_hi", + "gpio3", + "gpio3_hi", + "gpio4", + "gpio4_hi", + "gpio5", + "gpio5_hi", + "gpio10", + "gpio10_hi", + ]); - quote! { - pub const #name: u32 = #address; + for peripheral in METADATA.peripherals.iter().filter(|p| p.name.starts_with("GPIO")) { + let number = peripheral.name.strip_prefix("GPIO").unwrap(); + assert!(number.parse::().is_ok()); + cfgs.enable(format!("gpio{}", number)); + + for signal in peripheral.signals.iter() { + let pin_number = signal.name.parse::().unwrap(); + + if pin_number > 15 { + cfgs.enable(format!("gpio{}_hi", number)); + } + + // GPIO signals only defined a single signal, on a single pin. + assert_eq!(signal.pins.len(), 1); + + singletons.push(Singleton { + name: signal.pins[0].pin.into(), + cfg: None, + }); + } + } + + for peripheral in METADATA.peripherals.iter().filter(|p| p.name.starts_with("DMA")) { + let instance = peripheral.name.strip_prefix("DMA").unwrap(); + assert!(instance.parse::().is_ok()); + + for signal in peripheral.signals.iter() { + let channel_number = signal.name.parse::().unwrap(); + let name = format!("DMA{instance}_CH{channel_number}"); + + // DMA has no pins. + assert!(signal.pins.is_empty()); + + singletons.push(Singleton { name, cfg: None }); + } + } + + for peripheral in METADATA.peripherals.iter().filter(|p| p.name.starts_with("SCT")) { + let instance = peripheral.name.strip_prefix("SCT").unwrap(); + assert!(instance.parse::().is_ok()); + + for signal in peripheral.signals.iter() { + if !signal.name.starts_with("OUT") { + continue; + } + + let channel_number = signal.name.strip_prefix("OUT").unwrap().parse::().unwrap(); + let name = format!("SCT{instance}_OUT{channel_number}"); + + singletons.push(Singleton { name, cfg: None }); } + } + + singletons +} + +#[cfg(feature = "_rt1xxx")] +fn generate_iomuxc() -> TokenStream { + let iomuxc_pad_impls = metadata::METADATA + .pins + .iter() + .filter(|p| p.iomuxc.as_ref().filter(|i| i.mux.is_some()).is_some()) + .map(|pin| { + let Some(ref iomuxc) = pin.iomuxc else { + panic!("Pin {} has no IOMUXC definitions", pin.name); + }; + + let name = Ident::new(pin.name, Span::call_site()); + let mux = iomuxc.mux.unwrap(); + let pad = iomuxc.pad; + + quote! { + impl_iomuxc_pad!(#name, #pad, #mux); + } + }); + + let base_match_arms = metadata::METADATA + .peripherals + .iter() + .filter(|p| p.name.starts_with("GPIO")) + .map(|peripheral| { + peripheral.signals.iter().map(|signal| { + // All GPIO signals have a single pin. + let pin = &signal.pins[0]; + let instance = peripheral.name.strip_prefix("GPIO").unwrap(); + let bank_match = format_ident!("Gpio{}", instance); + let pin_number = signal.name.parse::().unwrap(); + let pin_ident = Ident::new(pin.pin, Span::call_site()); + + quote! { + (Bank::#bank_match, #pin_number) => + } + }) + }) + .flatten() + .collect::>(); + + let pad_match_arms = base_match_arms.iter().map(|arm| { + quote! { #arm::PAD } + }); + + let mux_match_arms = base_match_arms.iter().map(|arm| { + quote! { #arm::MUX } }); quote! { - pub mod iomuxc { - pub mod pads { - #(#pads)* + #(#iomuxc_pad_impls)* + + pub(crate) fn iomuxc_pad(bank: crate::gpio::Bank, pin: u8) -> *mut () { + use crate::gpio::Bank; + + match (bank, pin) { + #(#pad_match_arms),*, + _ => unreachable!() } + } + + pub(crate) fn iomuxc_mux(bank: crate::gpio::Bank, pin: u8) -> Option<*mut ()> { + use crate::gpio::Bank; - pub mod muxes { - #(#muxes)* + match (bank, pin) { + #(#mux_match_arms),*, + _ => unreachable!() } } } } -fn generate_code() { +fn generate_code(cfgs: &mut common::CfgSet, singletons: &[Singleton]) { #[allow(unused)] use std::fmt::Write; @@ -88,14 +222,179 @@ fn generate_code() { #[allow(unused_mut)] let mut output = String::new(); + writeln!(&mut output, "{}", peripherals(singletons)).unwrap(); + #[cfg(feature = "_rt1xxx")] writeln!(&mut output, "{}", generate_iomuxc()).unwrap(); + writeln!(&mut output, "{}", interrupts()).unwrap(); + writeln!(&mut output, "{}", impl_peripherals(cfgs, singletons)).unwrap(); + let out_file = out_dir.join("_generated.rs").to_string_lossy().to_string(); fs::write(&out_file, output).unwrap(); rustfmt(&out_file); } +fn interrupts() -> TokenStream { + let interrupts = METADATA.interrupts.iter().map(|interrupt| format_ident!("{interrupt}")); + + quote! { + embassy_hal_internal::interrupt_mod!(#(#interrupts),*); + } +} + +fn peripherals(singletons: &[Singleton]) -> TokenStream { + let defs = singletons.iter().map(|s| { + let ident = Ident::new(&s.name, Span::call_site()); + quote! { #ident } + }); + + let peripherals = singletons.iter().map(|s| { + let ident = Ident::new(&s.name, Span::call_site()); + let cfg = s.cfg.clone().unwrap_or_else(|| quote! {}); + quote! { + #cfg + #ident + } + }); + + quote! { + embassy_hal_internal::peripherals_definition!(#(#defs),*); + embassy_hal_internal::peripherals_struct!(#(#peripherals),*); + } +} + +fn impl_gpio_pin(impls: &mut Vec, peripheral: &Peripheral) { + let instance = peripheral.name.strip_prefix("GPIO").unwrap(); + let bank = format_ident!("Gpio{}", instance); + // let pin = + + for signal in peripheral.signals.iter() { + let pin_number = signal.name.parse::().unwrap(); + let pin = Ident::new(signal.pins[0].pin, Span::call_site()); + + impls.push(quote! { + impl_pin!(#pin, #bank, #pin_number); + }); + } +} + +fn impl_dma_channel(impls: &mut Vec, peripheral: &Peripheral) { + let instance = Ident::new(peripheral.name, Span::call_site()); + + for signal in peripheral.signals.iter() { + let channel_number = signal.name.parse::().unwrap(); + let channel_name = format_ident!("{instance}_CH{channel_number}"); + + impls.push(quote! { + impl_dma_channel!(#instance, #channel_name, #channel_number); + }); + } +} + +fn impl_usart(impls: &mut Vec, peripheral: &Peripheral) { + let instance = Ident::new(peripheral.name, Span::call_site()); + let flexcomm = Ident::new( + peripheral.flexcomm.expect("LPC55 must specify FLEXCOMM instance"), + Span::call_site(), + ); + let number = Literal::u8_unsuffixed(peripheral.name.strip_prefix("USART").unwrap().parse::().unwrap()); + + impls.push(quote! { + impl_usart_instance!(#instance, #flexcomm, #number); + }); + + for signal in peripheral.signals { + let r#macro = match signal.name { + "TXD" => format_ident!("impl_usart_txd_pin"), + "RXD" => format_ident!("impl_usart_rxd_pin"), + _ => unreachable!(), + }; + + for pin in signal.pins { + let alt = format_ident!("ALT{}", pin.alt); + let pin = format_ident!("{}", pin.pin); + + impls.push(quote! { + #r#macro!(#pin, #instance, #alt); + }); + } + } + + for dma_mux in peripheral.dma_muxing { + assert_eq!(dma_mux.mux, "DMA0", "TODO: USART for more than LPC55"); + + let r#macro = match dma_mux.signal { + "TX" => format_ident!("impl_usart_tx_channel"), + "RX" => format_ident!("impl_usart_rx_channel"), + _ => unreachable!(), + }; + + let channel = format_ident!("DMA0_CH{}", dma_mux.request); + + impls.push(quote! { + #r#macro!(#instance, #channel); + }); + } +} + +fn impl_sct(impls: &mut Vec, peripheral: &Peripheral) { + let instance = Ident::new(peripheral.name, Span::call_site()); + + impls.push(quote! { + impl_sct_instance!(#instance); + }); + + for signal in peripheral.signals.iter() { + if signal.name.starts_with("OUT") { + let channel_number = signal.name.strip_prefix("OUT").unwrap().parse::().unwrap(); + + let channel_name = format_ident!("{instance}_OUT{channel_number}"); + + impls.push(quote! { + impl_sct_output_instance!(#instance, #channel_name, #channel_number); + }); + + if signal.name.starts_with("OUT") { + for pin in signal.pins { + let pin_name = format_ident!("{}", pin.pin); + let alt = format_ident!("ALT{}", pin.alt); + + impls.push(quote! { + impl_sct_output_pin!(#instance, #channel_name, #pin_name, #alt); + }); + } + } + } + } +} + +fn impl_peripherals(_cfgs: &mut common::CfgSet, _singletons: &[Singleton]) -> TokenStream { + let mut impls = Vec::new(); + + for peripheral in metadata::METADATA.peripherals.iter() { + if peripheral.name.starts_with("GPIO") { + impl_gpio_pin(&mut impls, peripheral); + } + + if peripheral.name.starts_with("DMA") { + impl_dma_channel(&mut impls, peripheral); + } + + if peripheral.name.starts_with("USART") { + impl_usart(&mut impls, peripheral); + } + + if peripheral.name.starts_with("SCT") { + impl_sct(&mut impls, peripheral); + } + } + + quote! { + #(#impls)* + } +} + /// rustfmt a given path. /// Failures are logged to stderr and ignored. fn rustfmt(path: impl AsRef) { diff --git a/embassy-nxp/src/chips/lpc55.rs b/embassy-nxp/src/chips/lpc55.rs index e9addddb6..7967e07d1 100644 --- a/embassy-nxp/src/chips/lpc55.rs +++ b/embassy-nxp/src/chips/lpc55.rs @@ -1,121 +1,10 @@ -pub use nxp_pac as pac; +pub(crate) mod _generated { + #![allow(dead_code)] + #![allow(unused_imports)] + #![allow(non_snake_case)] + #![allow(missing_docs)] -embassy_hal_internal::interrupt_mod!( - FLEXCOMM0, FLEXCOMM1, FLEXCOMM2, FLEXCOMM3, FLEXCOMM4, FLEXCOMM5, FLEXCOMM6, FLEXCOMM7 -); - -embassy_hal_internal::peripherals! { - // External pins. These are not only GPIOs, they are multi-purpose pins and can be used by other - // peripheral types (e.g. I2C). - PIO0_0, - PIO0_1, - PIO0_2, - PIO0_3, - PIO0_4, - PIO0_5, - PIO0_6, - PIO0_7, - PIO0_8, - PIO0_9, - PIO0_10, - PIO0_11, - PIO0_12, - PIO0_13, - PIO0_14, - PIO0_15, - PIO0_16, - PIO0_17, - PIO0_18, - PIO0_19, - PIO0_20, - PIO0_21, - PIO0_22, - PIO0_23, - PIO0_24, - PIO0_25, - PIO0_26, - PIO0_27, - PIO0_28, - PIO0_29, - PIO0_30, - PIO0_31, - PIO1_0, - PIO1_1, - PIO1_2, - PIO1_3, - PIO1_4, - PIO1_5, - PIO1_6, - PIO1_7, - PIO1_8, - PIO1_9, - PIO1_10, - PIO1_11, - PIO1_12, - PIO1_13, - PIO1_14, - PIO1_15, - PIO1_16, - PIO1_17, - PIO1_18, - PIO1_19, - PIO1_20, - PIO1_21, - PIO1_22, - PIO1_23, - PIO1_24, - PIO1_25, - PIO1_26, - PIO1_27, - PIO1_28, - PIO1_29, - PIO1_30, - PIO1_31, - - // Direct Memory Access (DMA) channels. They are used for asynchronous modes of peripherals. - DMA_CH0, - DMA_CH1, - DMA_CH2, - DMA_CH3, - DMA_CH4, - DMA_CH5, - DMA_CH6, - DMA_CH7, - DMA_CH8, - DMA_CH9, - DMA_CH10, - DMA_CH11, - DMA_CH12, - DMA_CH13, - DMA_CH14, - DMA_CH15, - DMA_CH16, - DMA_CH17, - DMA_CH18, - DMA_CH19, - DMA_CH20, - DMA_CH21, - DMA_CH22, - - // Pulse-Width Modulation Outputs. - PWM_OUTPUT0, - PWM_OUTPUT1, - PWM_OUTPUT2, - PWM_OUTPUT3, - PWM_OUTPUT4, - PWM_OUTPUT5, - PWM_OUTPUT6, - PWM_OUTPUT7, - PWM_OUTPUT8, - PWM_OUTPUT9, - - // Universal Synchronous/Asynchronous Receiver/Transmitter (USART) instances. - USART0, - USART1, - USART2, - USART3, - USART4, - USART5, - USART6, - USART7 + include!(concat!(env!("OUT_DIR"), "/_generated.rs")); } + +pub use _generated::*; diff --git a/embassy-nxp/src/chips/mimxrt1011.rs b/embassy-nxp/src/chips/mimxrt1011.rs index a74d953fc..d5969a24b 100644 --- a/embassy-nxp/src/chips/mimxrt1011.rs +++ b/embassy-nxp/src/chips/mimxrt1011.rs @@ -1,107 +1,5 @@ // This must be imported so that __preinit is defined. use imxrt_rt as _; -pub use nxp_pac as pac; - -embassy_hal_internal::peripherals! { - // External pins. These are not only GPIOs, they are multi-purpose pins and can be used by other - // peripheral types (e.g. I2C). - GPIO_00, - GPIO_01, - GPIO_02, - GPIO_03, - GPIO_04, - GPIO_05, - GPIO_06, - GPIO_07, - GPIO_08, - GPIO_09, - GPIO_10, - GPIO_11, - GPIO_12, - GPIO_13, - GPIO_AD_00, - GPIO_AD_01, - GPIO_AD_02, - GPIO_AD_03, - GPIO_AD_04, - GPIO_AD_05, - GPIO_AD_06, - GPIO_AD_07, - GPIO_AD_08, - GPIO_AD_09, - GPIO_AD_10, - GPIO_AD_11, - GPIO_AD_12, - GPIO_AD_13, - GPIO_AD_14, - GPIO_SD_00, - GPIO_SD_01, - GPIO_SD_02, - GPIO_SD_03, - GPIO_SD_04, - GPIO_SD_05, - GPIO_SD_06, - GPIO_SD_07, - GPIO_SD_08, - GPIO_SD_09, - GPIO_SD_10, - GPIO_SD_11, - GPIO_SD_12, - GPIO_SD_13, - PMIC_ON_REQ, -} - -impl_gpio! { - // GPIO Bank 1 - GPIO_00(Gpio1, 0); - GPIO_01(Gpio1, 1); - GPIO_02(Gpio1, 2); - GPIO_03(Gpio1, 3); - GPIO_04(Gpio1, 4); - GPIO_05(Gpio1, 5); - GPIO_06(Gpio1, 6); - GPIO_07(Gpio1, 7); - GPIO_08(Gpio1, 8); - GPIO_09(Gpio1, 9); - GPIO_10(Gpio1, 10); - GPIO_11(Gpio1, 11); - GPIO_12(Gpio1, 12); - GPIO_13(Gpio1, 13); - GPIO_AD_00(Gpio1, 14); - GPIO_AD_01(Gpio1, 15); - GPIO_AD_02(Gpio1, 16); - GPIO_AD_03(Gpio1, 17); - GPIO_AD_04(Gpio1, 18); - GPIO_AD_05(Gpio1, 19); - GPIO_AD_06(Gpio1, 20); - GPIO_AD_07(Gpio1, 21); - GPIO_AD_08(Gpio1, 22); - GPIO_AD_09(Gpio1, 23); - GPIO_AD_10(Gpio1, 24); - GPIO_AD_11(Gpio1, 25); - GPIO_AD_12(Gpio1, 26); - GPIO_AD_13(Gpio1, 27); - GPIO_AD_14(Gpio1, 28); - - // GPIO Bank 2 - GPIO_SD_00(Gpio2, 0); - GPIO_SD_01(Gpio2, 1); - GPIO_SD_02(Gpio2, 2); - GPIO_SD_03(Gpio2, 3); - GPIO_SD_04(Gpio2, 4); - GPIO_SD_05(Gpio2, 5); - GPIO_SD_06(Gpio2, 6); - GPIO_SD_07(Gpio2, 7); - GPIO_SD_08(Gpio2, 8); - GPIO_SD_09(Gpio2, 9); - GPIO_SD_10(Gpio2, 10); - GPIO_SD_11(Gpio2, 11); - GPIO_SD_12(Gpio2, 12); - GPIO_SD_13(Gpio2, 13); - - // GPIO Bank 5 - PMIC_ON_REQ(Gpio5, 0); -} pub(crate) mod _generated { #![allow(dead_code)] @@ -111,3 +9,5 @@ pub(crate) mod _generated { include!(concat!(env!("OUT_DIR"), "/_generated.rs")); } + +pub use _generated::*; diff --git a/embassy-nxp/src/chips/mimxrt1062.rs b/embassy-nxp/src/chips/mimxrt1062.rs index ef153bd66..d5969a24b 100644 --- a/embassy-nxp/src/chips/mimxrt1062.rs +++ b/embassy-nxp/src/chips/mimxrt1062.rs @@ -1,276 +1,5 @@ // This must be imported so that __preinit is defined. use imxrt_rt as _; -pub use nxp_pac as pac; - -embassy_hal_internal::peripherals! { - // External pins. These are not only GPIOs, they are multi-purpose pins and can be used by other - // peripheral types (e.g. I2C). - GPIO_AD_B0_00, - GPIO_AD_B0_01, - GPIO_AD_B0_02, - GPIO_AD_B0_03, - GPIO_AD_B0_04, - GPIO_AD_B0_05, - GPIO_AD_B0_06, - GPIO_AD_B0_07, - GPIO_AD_B0_08, - GPIO_AD_B0_09, - GPIO_AD_B0_10, - GPIO_AD_B0_11, - GPIO_AD_B0_12, - GPIO_AD_B0_13, - GPIO_AD_B0_14, - GPIO_AD_B0_15, - GPIO_AD_B1_00, - GPIO_AD_B1_01, - GPIO_AD_B1_02, - GPIO_AD_B1_03, - GPIO_AD_B1_04, - GPIO_AD_B1_05, - GPIO_AD_B1_06, - GPIO_AD_B1_07, - GPIO_AD_B1_08, - GPIO_AD_B1_09, - GPIO_AD_B1_10, - GPIO_AD_B1_11, - GPIO_AD_B1_12, - GPIO_AD_B1_13, - GPIO_AD_B1_14, - GPIO_AD_B1_15, - GPIO_B0_00, - GPIO_B0_01, - GPIO_B0_02, - GPIO_B0_03, - GPIO_B0_04, - GPIO_B0_05, - GPIO_B0_06, - GPIO_B0_07, - GPIO_B0_08, - GPIO_B0_09, - GPIO_B0_10, - GPIO_B0_11, - GPIO_B0_12, - GPIO_B0_13, - GPIO_B0_14, - GPIO_B0_15, - GPIO_B1_00, - GPIO_B1_01, - GPIO_B1_02, - GPIO_B1_03, - GPIO_B1_04, - GPIO_B1_05, - GPIO_B1_06, - GPIO_B1_07, - GPIO_B1_08, - GPIO_B1_09, - GPIO_B1_10, - GPIO_B1_11, - GPIO_B1_12, - GPIO_B1_13, - GPIO_B1_14, - GPIO_B1_15, - GPIO_EMC_00, - GPIO_EMC_01, - GPIO_EMC_02, - GPIO_EMC_03, - GPIO_EMC_04, - GPIO_EMC_05, - GPIO_EMC_06, - GPIO_EMC_07, - GPIO_EMC_08, - GPIO_EMC_09, - GPIO_EMC_10, - GPIO_EMC_11, - GPIO_EMC_12, - GPIO_EMC_13, - GPIO_EMC_14, - GPIO_EMC_15, - GPIO_EMC_16, - GPIO_EMC_17, - GPIO_EMC_18, - GPIO_EMC_19, - GPIO_EMC_20, - GPIO_EMC_21, - GPIO_EMC_22, - GPIO_EMC_23, - GPIO_EMC_24, - GPIO_EMC_25, - GPIO_EMC_26, - GPIO_EMC_27, - GPIO_EMC_28, - GPIO_EMC_29, - GPIO_EMC_30, - GPIO_EMC_31, - GPIO_EMC_32, - GPIO_EMC_33, - GPIO_EMC_34, - GPIO_EMC_35, - GPIO_EMC_36, - GPIO_EMC_37, - GPIO_EMC_38, - GPIO_EMC_39, - GPIO_EMC_40, - GPIO_EMC_41, - GPIO_SD_B0_00, - GPIO_SD_B0_01, - GPIO_SD_B0_02, - GPIO_SD_B0_03, - GPIO_SD_B0_04, - GPIO_SD_B0_05, - GPIO_SD_B1_00, - GPIO_SD_B1_01, - GPIO_SD_B1_02, - GPIO_SD_B1_03, - GPIO_SD_B1_04, - GPIO_SD_B1_05, - GPIO_SD_B1_06, - GPIO_SD_B1_07, - GPIO_SD_B1_08, - GPIO_SD_B1_09, - GPIO_SD_B1_10, - GPIO_SD_B1_11, - WAKEUP, - PMIC_ON_REQ, - PMIC_STBY_REQ, -} - -impl_gpio! { - // GPIO Bank 1 - GPIO_AD_B0_00(Gpio1, 0); - GPIO_AD_B0_01(Gpio1, 1); - GPIO_AD_B0_02(Gpio1, 2); - GPIO_AD_B0_03(Gpio1, 3); - GPIO_AD_B0_04(Gpio1, 4); - GPIO_AD_B0_05(Gpio1, 5); - GPIO_AD_B0_06(Gpio1, 6); - GPIO_AD_B0_07(Gpio1, 7); - GPIO_AD_B0_08(Gpio1, 8); - GPIO_AD_B0_09(Gpio1, 9); - GPIO_AD_B0_10(Gpio1, 10); - GPIO_AD_B0_11(Gpio1, 11); - GPIO_AD_B0_12(Gpio1, 12); - GPIO_AD_B0_13(Gpio1, 13); - GPIO_AD_B0_14(Gpio1, 14); - GPIO_AD_B0_15(Gpio1, 15); - GPIO_AD_B1_00(Gpio1, 16); - GPIO_AD_B1_01(Gpio1, 17); - GPIO_AD_B1_02(Gpio1, 18); - GPIO_AD_B1_03(Gpio1, 19); - GPIO_AD_B1_04(Gpio1, 20); - GPIO_AD_B1_05(Gpio1, 21); - GPIO_AD_B1_06(Gpio1, 22); - GPIO_AD_B1_07(Gpio1, 23); - GPIO_AD_B1_08(Gpio1, 24); - GPIO_AD_B1_09(Gpio1, 25); - GPIO_AD_B1_10(Gpio1, 26); - GPIO_AD_B1_11(Gpio1, 27); - GPIO_AD_B1_12(Gpio1, 28); - GPIO_AD_B1_13(Gpio1, 29); - GPIO_AD_B1_14(Gpio1, 30); - GPIO_AD_B1_15(Gpio1, 31); - - // GPIO Bank 2 - GPIO_B0_00(Gpio2, 0); - GPIO_B0_01(Gpio2, 1); - GPIO_B0_02(Gpio2, 2); - GPIO_B0_03(Gpio2, 3); - GPIO_B0_04(Gpio2, 4); - GPIO_B0_05(Gpio2, 5); - GPIO_B0_06(Gpio2, 6); - GPIO_B0_07(Gpio2, 7); - GPIO_B0_08(Gpio2, 8); - GPIO_B0_09(Gpio2, 9); - GPIO_B0_10(Gpio2, 10); - GPIO_B0_11(Gpio2, 11); - GPIO_B0_12(Gpio2, 12); - GPIO_B0_13(Gpio2, 13); - GPIO_B0_14(Gpio2, 14); - GPIO_B0_15(Gpio2, 15); - GPIO_B1_00(Gpio2, 16); - GPIO_B1_01(Gpio2, 17); - GPIO_B1_02(Gpio2, 18); - GPIO_B1_03(Gpio2, 19); - GPIO_B1_04(Gpio2, 20); - GPIO_B1_05(Gpio2, 21); - GPIO_B1_06(Gpio2, 22); - GPIO_B1_07(Gpio2, 23); - GPIO_B1_08(Gpio2, 24); - GPIO_B1_09(Gpio2, 25); - GPIO_B1_10(Gpio2, 26); - GPIO_B1_11(Gpio2, 27); - GPIO_B1_12(Gpio2, 28); - GPIO_B1_13(Gpio2, 29); - GPIO_B1_14(Gpio2, 30); - GPIO_B1_15(Gpio2, 31); - - // GPIO Bank 4 (EMC is 4, then 3) - GPIO_EMC_00(Gpio4, 0); - GPIO_EMC_01(Gpio4, 1); - GPIO_EMC_02(Gpio4, 2); - GPIO_EMC_03(Gpio4, 3); - GPIO_EMC_04(Gpio4, 4); - GPIO_EMC_05(Gpio4, 5); - GPIO_EMC_06(Gpio4, 6); - GPIO_EMC_07(Gpio4, 7); - GPIO_EMC_08(Gpio4, 8); - GPIO_EMC_09(Gpio4, 9); - GPIO_EMC_10(Gpio4, 10); - GPIO_EMC_11(Gpio4, 11); - GPIO_EMC_12(Gpio4, 12); - GPIO_EMC_13(Gpio4, 13); - GPIO_EMC_14(Gpio4, 14); - GPIO_EMC_15(Gpio4, 15); - GPIO_EMC_16(Gpio4, 16); - GPIO_EMC_17(Gpio4, 17); - GPIO_EMC_18(Gpio4, 18); - GPIO_EMC_19(Gpio4, 19); - GPIO_EMC_20(Gpio4, 20); - GPIO_EMC_21(Gpio4, 21); - GPIO_EMC_22(Gpio4, 22); - GPIO_EMC_23(Gpio4, 23); - GPIO_EMC_24(Gpio4, 24); - GPIO_EMC_25(Gpio4, 25); - GPIO_EMC_26(Gpio4, 26); - GPIO_EMC_27(Gpio4, 27); - GPIO_EMC_28(Gpio4, 28); - GPIO_EMC_29(Gpio4, 29); - GPIO_EMC_30(Gpio4, 30); - GPIO_EMC_31(Gpio4, 31); - - // GPIO Bank 3 - GPIO_EMC_32(Gpio3, 18); - GPIO_EMC_33(Gpio3, 19); - GPIO_EMC_34(Gpio3, 20); - GPIO_EMC_35(Gpio3, 21); - GPIO_EMC_36(Gpio3, 22); - GPIO_EMC_37(Gpio3, 23); - GPIO_EMC_38(Gpio3, 24); - GPIO_EMC_39(Gpio3, 25); - GPIO_EMC_40(Gpio3, 26); - GPIO_EMC_41(Gpio3, 27); - GPIO_SD_B0_00(Gpio3, 12); - GPIO_SD_B0_01(Gpio3, 13); - GPIO_SD_B0_02(Gpio3, 14); - GPIO_SD_B0_03(Gpio3, 15); - GPIO_SD_B0_04(Gpio3, 16); - GPIO_SD_B0_05(Gpio3, 17); - GPIO_SD_B1_00(Gpio3, 0); - GPIO_SD_B1_01(Gpio3, 1); - GPIO_SD_B1_02(Gpio3, 2); - GPIO_SD_B1_03(Gpio3, 3); - GPIO_SD_B1_04(Gpio3, 4); - GPIO_SD_B1_05(Gpio3, 5); - GPIO_SD_B1_06(Gpio3, 6); - GPIO_SD_B1_07(Gpio3, 7); - GPIO_SD_B1_08(Gpio3, 8); - GPIO_SD_B1_09(Gpio3, 9); - GPIO_SD_B1_10(Gpio3, 10); - GPIO_SD_B1_11(Gpio3, 11); - - WAKEUP(Gpio5, 0); - PMIC_ON_REQ(Gpio5, 1); - PMIC_STBY_REQ(Gpio5, 2); -} pub(crate) mod _generated { #![allow(dead_code)] @@ -280,3 +9,5 @@ pub(crate) mod _generated { include!(concat!(env!("OUT_DIR"), "/_generated.rs")); } + +pub use _generated::*; diff --git a/embassy-nxp/src/dma.rs b/embassy-nxp/src/dma.rs index e2df65fc9..1f479122d 100644 --- a/embassy-nxp/src/dma.rs +++ b/embassy-nxp/src/dma.rs @@ -1,3 +1,4 @@ +#![macro_use] //! Direct Memory Access (DMA) driver. #[cfg_attr(feature = "lpc55-core0", path = "./dma/lpc55.rs")] diff --git a/embassy-nxp/src/dma/lpc55.rs b/embassy-nxp/src/dma/lpc55.rs index 5bd763f03..623644bf1 100644 --- a/embassy-nxp/src/dma/lpc55.rs +++ b/embassy-nxp/src/dma/lpc55.rs @@ -1,3 +1,5 @@ +#![macro_use] + use core::cell::RefCell; use core::future::Future; use core::pin::Pin; @@ -9,9 +11,12 @@ use embassy_hal_internal::interrupt::InterruptExt; use embassy_hal_internal::{PeripheralType, impl_peripheral}; use embassy_sync::waitqueue::AtomicWaker; -use crate::pac::{DMA0, SYSCON, *}; -use crate::{Peri, peripherals}; +use crate::Peri; +#[cfg(feature = "rt")] +use crate::pac::interrupt; +use crate::pac::{SYSCON, *}; +#[cfg(feature = "rt")] #[interrupt] fn DMA0() { let inta = DMA0.inta0().read().ia(); @@ -278,7 +283,7 @@ static DMA_DESCRIPTORS: Mutex> = Mutex::new(RefCell: }; CHANNEL_COUNT], })); -trait SealedChannel {} +pub(crate) trait SealedChannel {} trait SealedWord {} /// DMA channel interface. @@ -323,7 +328,7 @@ impl Word for u32 { /// Type erased DMA channel. pub struct AnyChannel { - number: u8, + pub(crate) number: u8, } impl_peripheral!(AnyChannel); @@ -335,10 +340,10 @@ impl Channel for AnyChannel { } } -macro_rules! channel { - ($name:ident, $num:expr) => { - impl SealedChannel for peripherals::$name {} - impl Channel for peripherals::$name { +macro_rules! impl_dma_channel { + ($instance:ident, $name:ident, $num:expr) => { + impl crate::dma::SealedChannel for crate::peripherals::$name {} + impl crate::dma::Channel for crate::peripherals::$name { fn number(&self) -> u8 { $num } @@ -346,32 +351,10 @@ macro_rules! channel { impl From for crate::dma::AnyChannel { fn from(val: peripherals::$name) -> Self { + use crate::dma::Channel; + Self { number: val.number() } } } }; } - -channel!(DMA_CH0, 0); -channel!(DMA_CH1, 1); -channel!(DMA_CH2, 2); -channel!(DMA_CH3, 3); -channel!(DMA_CH4, 4); -channel!(DMA_CH5, 5); -channel!(DMA_CH6, 6); -channel!(DMA_CH7, 7); -channel!(DMA_CH8, 8); -channel!(DMA_CH9, 9); -channel!(DMA_CH10, 10); -channel!(DMA_CH11, 11); -channel!(DMA_CH12, 12); -channel!(DMA_CH13, 13); -channel!(DMA_CH14, 14); -channel!(DMA_CH15, 15); -channel!(DMA_CH16, 16); -channel!(DMA_CH17, 17); -channel!(DMA_CH18, 18); -channel!(DMA_CH19, 19); -channel!(DMA_CH20, 20); -channel!(DMA_CH21, 21); -channel!(DMA_CH22, 22); diff --git a/embassy-nxp/src/gpio/lpc55.rs b/embassy-nxp/src/gpio/lpc55.rs index 6039d8ca8..6be405463 100644 --- a/embassy-nxp/src/gpio/lpc55.rs +++ b/embassy-nxp/src/gpio/lpc55.rs @@ -1,9 +1,11 @@ +#![macro_use] + use embassy_hal_internal::{PeripheralType, impl_peripheral}; +use crate::Peri; use crate::pac::common::{RW, Reg}; use crate::pac::iocon::vals::{PioDigimode, PioMode}; use crate::pac::{GPIO, IOCON, SYSCON, iocon}; -use crate::{Peri, peripherals}; pub(crate) fn init() { // Enable clocks for GPIO, PINT, and IOCON @@ -39,8 +41,8 @@ pub enum Pull { /// The LPC55 boards have two GPIO banks, each with 32 pins. This enum represents the two banks. #[derive(Debug, Eq, PartialEq, Clone, Copy)] pub enum Bank { - Bank0 = 0, - Bank1 = 1, + Gpio0 = 0, + Gpio1 = 1, } /// GPIO output driver. Internally, this is a specialized [Flex] pin. @@ -228,8 +230,8 @@ pub(crate) trait SealedPin: Sized { #[inline] fn pio(&self) -> Reg { match self.pin_bank() { - Bank::Bank0 => IOCON.pio0(self.pin_number() as usize), - Bank::Bank1 => IOCON.pio1(self.pin_number() as usize), + Bank::Gpio0 => IOCON.pio0(self.pin_number() as usize), + Bank::Gpio1 => IOCON.pio1(self.pin_number() as usize), } } } @@ -254,8 +256,8 @@ pub trait Pin: PeripheralType + Into + SealedPin + Sized + 'static { /// Type-erased GPIO pin. pub struct AnyPin { - pin_bank: Bank, - pin_number: u8, + pub(crate) pin_bank: Bank, + pub(crate) pin_number: u8, } impl AnyPin { @@ -285,12 +287,12 @@ impl SealedPin for AnyPin { } macro_rules! impl_pin { - ($name:ident, $bank:expr, $pin_num:expr) => { - impl Pin for peripherals::$name {} - impl SealedPin for peripherals::$name { + ($name:ident, $bank:ident, $pin_num:expr) => { + impl crate::gpio::Pin for peripherals::$name {} + impl crate::gpio::SealedPin for peripherals::$name { #[inline] - fn pin_bank(&self) -> Bank { - $bank + fn pin_bank(&self) -> crate::gpio::Bank { + crate::gpio::Bank::$bank } #[inline] @@ -301,6 +303,8 @@ macro_rules! impl_pin { impl From for crate::gpio::AnyPin { fn from(val: peripherals::$name) -> Self { + use crate::gpio::SealedPin; + Self { pin_bank: val.pin_bank(), pin_number: val.pin_number(), @@ -309,68 +313,3 @@ macro_rules! impl_pin { } }; } - -impl_pin!(PIO0_0, Bank::Bank0, 0); -impl_pin!(PIO0_1, Bank::Bank0, 1); -impl_pin!(PIO0_2, Bank::Bank0, 2); -impl_pin!(PIO0_3, Bank::Bank0, 3); -impl_pin!(PIO0_4, Bank::Bank0, 4); -impl_pin!(PIO0_5, Bank::Bank0, 5); -impl_pin!(PIO0_6, Bank::Bank0, 6); -impl_pin!(PIO0_7, Bank::Bank0, 7); -impl_pin!(PIO0_8, Bank::Bank0, 8); -impl_pin!(PIO0_9, Bank::Bank0, 9); -impl_pin!(PIO0_10, Bank::Bank0, 10); -impl_pin!(PIO0_11, Bank::Bank0, 11); -impl_pin!(PIO0_12, Bank::Bank0, 12); -impl_pin!(PIO0_13, Bank::Bank0, 13); -impl_pin!(PIO0_14, Bank::Bank0, 14); -impl_pin!(PIO0_15, Bank::Bank0, 15); -impl_pin!(PIO0_16, Bank::Bank0, 16); -impl_pin!(PIO0_17, Bank::Bank0, 17); -impl_pin!(PIO0_18, Bank::Bank0, 18); -impl_pin!(PIO0_19, Bank::Bank0, 19); -impl_pin!(PIO0_20, Bank::Bank0, 20); -impl_pin!(PIO0_21, Bank::Bank0, 21); -impl_pin!(PIO0_22, Bank::Bank0, 22); -impl_pin!(PIO0_23, Bank::Bank0, 23); -impl_pin!(PIO0_24, Bank::Bank0, 24); -impl_pin!(PIO0_25, Bank::Bank0, 25); -impl_pin!(PIO0_26, Bank::Bank0, 26); -impl_pin!(PIO0_27, Bank::Bank0, 27); -impl_pin!(PIO0_28, Bank::Bank0, 28); -impl_pin!(PIO0_29, Bank::Bank0, 29); -impl_pin!(PIO0_30, Bank::Bank0, 30); -impl_pin!(PIO0_31, Bank::Bank0, 31); -impl_pin!(PIO1_0, Bank::Bank1, 0); -impl_pin!(PIO1_1, Bank::Bank1, 1); -impl_pin!(PIO1_2, Bank::Bank1, 2); -impl_pin!(PIO1_3, Bank::Bank1, 3); -impl_pin!(PIO1_4, Bank::Bank1, 4); -impl_pin!(PIO1_5, Bank::Bank1, 5); -impl_pin!(PIO1_6, Bank::Bank1, 6); -impl_pin!(PIO1_7, Bank::Bank1, 7); -impl_pin!(PIO1_8, Bank::Bank1, 8); -impl_pin!(PIO1_9, Bank::Bank1, 9); -impl_pin!(PIO1_10, Bank::Bank1, 10); -impl_pin!(PIO1_11, Bank::Bank1, 11); -impl_pin!(PIO1_12, Bank::Bank1, 12); -impl_pin!(PIO1_13, Bank::Bank1, 13); -impl_pin!(PIO1_14, Bank::Bank1, 14); -impl_pin!(PIO1_15, Bank::Bank1, 15); -impl_pin!(PIO1_16, Bank::Bank1, 16); -impl_pin!(PIO1_17, Bank::Bank1, 17); -impl_pin!(PIO1_18, Bank::Bank1, 18); -impl_pin!(PIO1_19, Bank::Bank1, 19); -impl_pin!(PIO1_20, Bank::Bank1, 20); -impl_pin!(PIO1_21, Bank::Bank1, 21); -impl_pin!(PIO1_22, Bank::Bank1, 22); -impl_pin!(PIO1_23, Bank::Bank1, 23); -impl_pin!(PIO1_24, Bank::Bank1, 24); -impl_pin!(PIO1_25, Bank::Bank1, 25); -impl_pin!(PIO1_26, Bank::Bank1, 26); -impl_pin!(PIO1_27, Bank::Bank1, 27); -impl_pin!(PIO1_28, Bank::Bank1, 28); -impl_pin!(PIO1_29, Bank::Bank1, 29); -impl_pin!(PIO1_30, Bank::Bank1, 30); -impl_pin!(PIO1_31, Bank::Bank1, 31); diff --git a/embassy-nxp/src/gpio/rt1xxx.rs b/embassy-nxp/src/gpio/rt1xxx.rs index c4dc110ff..8a560310c 100644 --- a/embassy-nxp/src/gpio/rt1xxx.rs +++ b/embassy-nxp/src/gpio/rt1xxx.rs @@ -10,7 +10,7 @@ use embassy_sync::waitqueue::AtomicWaker; use nxp_pac::gpio::vals::Icr; use nxp_pac::iomuxc::vals::Pus; -use crate::chip::{mux_address, pad_address}; +use crate::chip::{iomuxc_mux, iomuxc_pad}; use crate::pac::common::{RW, Reg}; use crate::pac::gpio::Gpio; #[cfg(feature = "rt")] @@ -121,6 +121,10 @@ pub enum Bank { /// Bank 5 #[cfg(gpio5)] Gpio5, + + #[cfg(gpio10)] + /// Bank 10 + Gpio10, } /// GPIO flexible pin. @@ -656,6 +660,8 @@ static GPIO3_WAKERS: [AtomicWaker; 32] = [const { AtomicWaker::new() }; 32]; static GPIO4_WAKERS: [AtomicWaker; 32] = [const { AtomicWaker::new() }; 32]; #[cfg(gpio5)] static GPIO5_WAKERS: [AtomicWaker; 32] = [const { AtomicWaker::new() }; 32]; +#[cfg(gpio10)] +static GPIO10_WAKERS: [AtomicWaker; 32] = [const { AtomicWaker::new() }; 32]; /// Sealed trait for pins. This trait is sealed and cannot be implemented outside of this crate. pub(crate) trait SealedPin: Sized { @@ -676,13 +682,15 @@ pub(crate) trait SealedPin: Sized { Bank::Gpio4 => pac::GPIO4, #[cfg(gpio5)] Bank::Gpio5 => pac::GPIO5, + #[cfg(gpio10)] + Bank::Gpio10 => pac::GPIO10, } } #[inline] fn mux(&self) -> Reg { // SAFETY: The generated mux address table is valid since it is generated from the SVD files. - let address = unsafe { mux_address(self._bank(), self.pin_number()).unwrap_unchecked() }; + let address = unsafe { iomuxc_mux(self._bank(), self.pin_number()).unwrap_unchecked() }; // SAFETY: The register at the address is an instance of MuxCtl. unsafe { Reg::from_ptr(address as *mut _) } @@ -690,8 +698,7 @@ pub(crate) trait SealedPin: Sized { #[inline] fn pad(&self) -> Reg { - // SAFETY: The generated pad address table is valid since it is generated from the SVD files. - let address = unsafe { pad_address(self._bank(), self.pin_number()).unwrap_unchecked() }; + let address = iomuxc_pad(self._bank(), self.pin_number()); // SAFETY: The register at the address is an instance of Ctl. unsafe { Reg::from_ptr(address as *mut _) } @@ -709,6 +716,8 @@ pub(crate) trait SealedPin: Sized { Bank::Gpio4 => &GPIO4_WAKERS[self.pin_number() as usize], #[cfg(gpio5)] Bank::Gpio5 => &GPIO5_WAKERS[self.pin_number() as usize], + #[cfg(gpio10)] + Bank::Gpio10 => &GPIO10_WAKERS[self.pin_number() as usize], } } } @@ -793,39 +802,6 @@ impl<'d> Future for InputFuture<'d> { } } -/// A macro to generate all GPIO pins. -/// -/// This generates a lookup table for IOMUX register addresses. -macro_rules! impl_gpio { - ( - $($name: ident($bank: ident, $pin_number: expr);)* - ) => { - #[inline] - pub(crate) const fn pad_address(bank: crate::gpio::Bank, pin: u8) -> Option { - match (bank, pin) { - $( - (crate::gpio::Bank::$bank, $pin_number) => Some(crate::chip::_generated::iomuxc::pads::$name), - )* - _ => None - } - } - - #[inline] - pub(crate) const fn mux_address(bank: crate::gpio::Bank, pin: u8) -> Option { - match (bank, pin) { - $( - (crate::gpio::Bank::$bank, $pin_number) => Some(crate::chip::_generated::iomuxc::muxes::$name), - )* - _ => None - } - } - - $( - impl_pin!($name, $bank, $pin_number); - )* - }; -} - macro_rules! impl_pin { ($name: ident, $bank: ident, $pin_num: expr) => { impl crate::gpio::Pin for crate::peripherals::$name {} diff --git a/embassy-nxp/src/iomuxc.rs b/embassy-nxp/src/iomuxc.rs new file mode 100644 index 000000000..c015ecbc2 --- /dev/null +++ b/embassy-nxp/src/iomuxc.rs @@ -0,0 +1,29 @@ +#![macro_use] + +/// An IOMUXC pad. +/// +/// This trait does not imply that GPIO can be used with this pad. [`Pin`](crate::gpio::Pin) must +/// also be implemented for GPIO. +#[allow(private_bounds)] +pub trait Pad: SealedPad {} + +pub(crate) trait SealedPad { + /// Address of the pad register for this pad. + const PAD: *mut (); + + /// Address of the mux register for this pad. + /// + /// Some pads do not allow muxing (e.g. ONOFF). + const MUX: Option<*mut ()>; +} + +macro_rules! impl_iomuxc_pad { + ($name: ident, $pad: expr, $mux: expr) => { + impl crate::iomuxc::SealedPad for crate::peripherals::$name { + const PAD: *mut () = $pad as *mut (); + const MUX: Option<*mut ()> = Some($mux as *mut ()); + } + + impl crate::iomuxc::Pad for crate::peripherals::$name {} + }; +} diff --git a/embassy-nxp/src/lib.rs b/embassy-nxp/src/lib.rs index 4058881a5..4c3dbebb9 100644 --- a/embassy-nxp/src/lib.rs +++ b/embassy-nxp/src/lib.rs @@ -12,8 +12,13 @@ pub mod pint; #[cfg(feature = "lpc55-core0")] pub mod pwm; #[cfg(feature = "lpc55-core0")] +pub mod sct; +#[cfg(feature = "lpc55-core0")] pub mod usart; +#[cfg(rt1xxx)] +mod iomuxc; + #[cfg(feature = "_time_driver")] #[cfg_attr(feature = "time-driver-pit", path = "time_driver/pit.rs")] #[cfg_attr(feature = "time-driver-rtc", path = "time_driver/rtc.rs")] @@ -25,15 +30,12 @@ mod time_driver; #[cfg_attr(feature = "mimxrt1062", path = "chips/mimxrt1062.rs")] mod chip; -// TODO: Remove when this module is implemented for other chips -#[cfg(feature = "lpc55-core0")] -pub use chip::interrupt; +pub use chip::{Peripherals, interrupt, peripherals}; +pub use embassy_hal_internal::{Peri, PeripheralType}; #[cfg(feature = "unstable-pac")] -pub use chip::pac; +pub use nxp_pac as pac; #[cfg(not(feature = "unstable-pac"))] -pub(crate) use chip::pac; -pub use chip::{Peripherals, peripherals}; -pub use embassy_hal_internal::{Peri, PeripheralType}; +pub(crate) use nxp_pac as pac; /// Macro to bind interrupts to handlers. /// (Copied from `embassy-rp`) diff --git a/embassy-nxp/src/pwm.rs b/embassy-nxp/src/pwm.rs index 68980924a..c87a39c34 100644 --- a/embassy-nxp/src/pwm.rs +++ b/embassy-nxp/src/pwm.rs @@ -1,3 +1,5 @@ +#![macro_use] + //! Pulse-Width Modulation (PWM) driver. #[cfg_attr(feature = "lpc55-core0", path = "./pwm/lpc55.rs")] diff --git a/embassy-nxp/src/pwm/lpc55.rs b/embassy-nxp/src/pwm/lpc55.rs index 197184ad6..4cdbd8526 100644 --- a/embassy-nxp/src/pwm/lpc55.rs +++ b/embassy-nxp/src/pwm/lpc55.rs @@ -1,12 +1,15 @@ +#![macro_use] + use core::sync::atomic::{AtomicU8, AtomicU32, Ordering}; -use embassy_hal_internal::{Peri, PeripheralType}; +use embassy_hal_internal::Peri; use crate::gpio::AnyPin; -use crate::pac::iocon::vals::{PioDigimode, PioFunc, PioMode, PioOd, PioSlew}; +use crate::pac::iocon::vals::{PioDigimode, PioMode, PioOd, PioSlew}; use crate::pac::sct0::vals; use crate::pac::syscon::vals::{SctRst, SctclkselSel}; use crate::pac::{SCT0, SYSCON}; +use crate::sct; // Since for now the counter is shared, the TOP value has to be kept. static TOP_VALUE: AtomicU32 = AtomicU32::new(0); @@ -75,7 +78,11 @@ impl<'d> Pwm<'d> { SYSCON.presetctrl1().modify(|w| w.set_sct_rst(SctRst::ASSERTED)); SYSCON.presetctrl1().modify(|w| w.set_sct_rst(SctRst::RELEASED)); } - fn new_inner(output: usize, channel: Peri<'d, impl OutputChannelPin>, config: Config) -> Self { + fn new_inner>( + output: usize, + channel: Peri<'d, impl sct::OutputPin>, + config: Config, + ) -> Self { // Enable clocks (Syscon is enabled by default) critical_section::with(|_cs| { if !SYSCON.ahbclkctrl0().read().iocon() { @@ -109,12 +116,12 @@ impl<'d> Pwm<'d> { /// Create PWM driver with a single 'a' pin as output. #[inline] - pub fn new_output( - output: Peri<'d, T>, - channel: Peri<'d, impl OutputChannelPin>, + pub fn new_output>( + output: Peri<'d, O>, + channel: Peri<'d, impl sct::OutputPin>, config: Config, ) -> Self { - Self::new_inner(output.number(), channel, config) + Self::new_inner::(output.number(), channel, config) } /// Set the PWM config. @@ -196,18 +203,18 @@ impl<'d> Pwm<'d> { // TODO(frihetselsker): optimize nxp-pac so that `set_clr` and `set_set` are turned into a bit array. if config.invert { // Low when event 0 is active - SCT0.out(output_number).out_clr().modify(|w| w.set_clr(1 << 0)); + SCT0.out(output_number).out_clr().modify(|w| w.set_clr(0, true)); // High when event `output_number + 1` is active SCT0.out(output_number) .out_set() - .modify(|w| w.set_set(1 << (output_number + 1))); + .modify(|w| w.set_set(output_number, true)); } else { // High when event 0 is active - SCT0.out(output_number).out_set().modify(|w| w.set_set(1 << 0)); + SCT0.out(output_number).out_set().modify(|w| w.set_set(0, true)); // Low when event `output_number + 1` is active SCT0.out(output_number) .out_clr() - .modify(|w| w.set_clr(1 << (output_number + 1))); + .modify(|w| w.set_clr(output_number, true)); } if config.phase_correct { @@ -239,87 +246,3 @@ impl<'d> Drop for Pwm<'d> { } } } - -trait SealedOutput { - /// Output number. - fn number(&self) -> usize; -} - -/// PWM Output. -#[allow(private_bounds)] -pub trait Output: PeripheralType + SealedOutput {} - -macro_rules! output { - ($name:ident, $num:expr) => { - impl SealedOutput for crate::peripherals::$name { - fn number(&self) -> usize { - $num - } - } - impl Output for crate::peripherals::$name {} - }; -} - -output!(PWM_OUTPUT0, 0); -output!(PWM_OUTPUT1, 1); -output!(PWM_OUTPUT2, 2); -output!(PWM_OUTPUT3, 3); -output!(PWM_OUTPUT4, 4); -output!(PWM_OUTPUT5, 5); -output!(PWM_OUTPUT6, 6); -output!(PWM_OUTPUT7, 7); -output!(PWM_OUTPUT8, 8); -output!(PWM_OUTPUT9, 9); - -/// PWM Output Channel. -pub trait OutputChannelPin: crate::gpio::Pin { - fn pin_func(&self) -> PioFunc; -} - -macro_rules! impl_pin { - ($pin:ident, $output:ident, $func:ident) => { - impl crate::pwm::inner::OutputChannelPin for crate::peripherals::$pin { - fn pin_func(&self) -> PioFunc { - PioFunc::$func - } - } - }; -} - -impl_pin!(PIO0_2, PWM_OUTPUT0, ALT3); -impl_pin!(PIO0_17, PWM_OUTPUT0, ALT4); -impl_pin!(PIO1_4, PWM_OUTPUT0, ALT4); -impl_pin!(PIO1_23, PWM_OUTPUT0, ALT2); - -impl_pin!(PIO0_3, PWM_OUTPUT1, ALT3); -impl_pin!(PIO0_18, PWM_OUTPUT1, ALT4); -impl_pin!(PIO1_8, PWM_OUTPUT1, ALT4); -impl_pin!(PIO1_24, PWM_OUTPUT1, ALT2); - -impl_pin!(PIO0_10, PWM_OUTPUT2, ALT5); -impl_pin!(PIO0_15, PWM_OUTPUT2, ALT4); -impl_pin!(PIO0_19, PWM_OUTPUT2, ALT4); -impl_pin!(PIO1_9, PWM_OUTPUT2, ALT4); -impl_pin!(PIO1_25, PWM_OUTPUT2, ALT2); - -impl_pin!(PIO0_22, PWM_OUTPUT3, ALT4); -impl_pin!(PIO0_31, PWM_OUTPUT3, ALT4); -impl_pin!(PIO1_10, PWM_OUTPUT3, ALT4); -impl_pin!(PIO1_26, PWM_OUTPUT3, ALT2); - -impl_pin!(PIO0_23, PWM_OUTPUT4, ALT4); -impl_pin!(PIO1_3, PWM_OUTPUT4, ALT4); -impl_pin!(PIO1_17, PWM_OUTPUT4, ALT4); - -impl_pin!(PIO0_26, PWM_OUTPUT5, ALT4); -impl_pin!(PIO1_18, PWM_OUTPUT5, ALT4); - -impl_pin!(PIO0_27, PWM_OUTPUT6, ALT4); -impl_pin!(PIO1_31, PWM_OUTPUT6, ALT4); - -impl_pin!(PIO0_28, PWM_OUTPUT7, ALT4); -impl_pin!(PIO1_19, PWM_OUTPUT7, ALT2); - -impl_pin!(PIO0_29, PWM_OUTPUT8, ALT4); - -impl_pin!(PIO0_30, PWM_OUTPUT9, ALT4); diff --git a/embassy-nxp/src/sct.rs b/embassy-nxp/src/sct.rs new file mode 100644 index 000000000..b6b0e35a9 --- /dev/null +++ b/embassy-nxp/src/sct.rs @@ -0,0 +1,56 @@ +#![macro_use] + +use embassy_hal_internal::PeripheralType; +use nxp_pac::iocon::vals::PioFunc; + +use crate::gpio; + +/// SCT instance. +#[allow(private_bounds)] +pub trait Instance: SealedInstance + PeripheralType {} + +pub(crate) trait SealedInstance {} + +/// An SCT output. +#[allow(private_bounds)] +pub trait Output: SealedOutput + PeripheralType {} + +pub(crate) trait SealedOutput { + /// Output number. + fn number(&self) -> usize; +} + +/// An SCT output capable pin. +pub trait OutputPin>: gpio::Pin { + fn pin_func(&self) -> PioFunc; +} + +macro_rules! impl_sct_instance { + ($instance: ident) => { + impl crate::sct::SealedInstance for crate::peripherals::$instance {} + impl crate::sct::Instance for crate::peripherals::$instance {} + }; +} + +macro_rules! impl_sct_output_instance { + ($instance: ident, $name: ident, $num: expr) => { + impl crate::sct::SealedOutput for crate::peripherals::$name { + fn number(&self) -> usize { + $num as usize + } + } + impl crate::sct::Output for crate::peripherals::$name {} + }; +} + +macro_rules! impl_sct_output_pin { + ($instance: ident, $output_instance: ident, $pin: ident, $alt: ident) => { + impl crate::sct::OutputPin + for crate::peripherals::$pin + { + fn pin_func(&self) -> crate::pac::iocon::vals::PioFunc { + crate::pac::iocon::vals::PioFunc::$alt + } + } + }; +} diff --git a/embassy-nxp/src/usart.rs b/embassy-nxp/src/usart.rs index 1d8886f24..af039dee4 100644 --- a/embassy-nxp/src/usart.rs +++ b/embassy-nxp/src/usart.rs @@ -1,3 +1,5 @@ +#![macro_use] + //! Universal Synchronous/Asynchronous Receiver/Transmitter (USART) driver. #[cfg_attr(feature = "lpc55-core0", path = "./usart/lpc55.rs")] diff --git a/embassy-nxp/src/usart/lpc55.rs b/embassy-nxp/src/usart/lpc55.rs index d54927b25..d77f08fd8 100644 --- a/embassy-nxp/src/usart/lpc55.rs +++ b/embassy-nxp/src/usart/lpc55.rs @@ -1,3 +1,5 @@ +#![macro_use] + use core::fmt::Debug; use core::future::poll_fn; use core::marker::PhantomData; @@ -13,7 +15,7 @@ use embedded_io::{self, ErrorKind}; use crate::dma::{AnyChannel, Channel}; use crate::gpio::{AnyPin, SealedPin}; use crate::interrupt::Interrupt; -use crate::interrupt::typelevel::{Binding, Interrupt as _}; +use crate::interrupt::typelevel::Binding; use crate::pac::flexcomm::Flexcomm as FlexcommReg; use crate::pac::iocon::vals::PioFunc; use crate::pac::usart::Usart as UsartReg; @@ -113,8 +115,8 @@ impl Default for Config { /// Internal DMA state of UART RX. pub struct DmaState { - rx_err_waker: AtomicWaker, - rx_err: AtomicBool, + pub(crate) rx_err_waker: AtomicWaker, + pub(crate) rx_err: AtomicBool, } /// # Type parameters @@ -818,13 +820,13 @@ impl<'d> embedded_io::Read for Usart<'d, Blocking> { } } -struct Info { - usart_reg: UsartReg, - fc_reg: FlexcommReg, - interrupt: Interrupt, +pub(crate) struct Info { + pub(crate) usart_reg: UsartReg, + pub(crate) fc_reg: FlexcommReg, + pub(crate) interrupt: Interrupt, } -trait SealedInstance { +pub(crate) trait SealedInstance { fn info() -> &'static Info; fn dma_state() -> &'static DmaState; fn instance_number() -> usize; @@ -837,10 +839,13 @@ pub trait Instance: SealedInstance + PeripheralType { type Interrupt: crate::interrupt::typelevel::Interrupt; } -macro_rules! impl_instance { +macro_rules! impl_usart_instance { ($inst:ident, $fc:ident, $fc_num:expr) => { - impl $crate::usart::inner::SealedInstance for $crate::peripherals::$inst { - fn info() -> &'static Info { + impl crate::usart::SealedInstance for $crate::peripherals::$inst { + fn info() -> &'static crate::usart::Info { + use crate::interrupt::typelevel::Interrupt; + use crate::usart::Info; + static INFO: Info = Info { usart_reg: crate::pac::$inst, fc_reg: crate::pac::$fc, @@ -849,7 +854,13 @@ macro_rules! impl_instance { &INFO } - fn dma_state() -> &'static DmaState { + fn dma_state() -> &'static crate::usart::DmaState { + use core::sync::atomic::AtomicBool; + + use embassy_sync::waitqueue::AtomicWaker; + + use crate::usart::DmaState; + static STATE: DmaState = DmaState { rx_err_waker: AtomicWaker::new(), rx_err: AtomicBool::new(false), @@ -867,15 +878,6 @@ macro_rules! impl_instance { }; } -impl_instance!(USART0, FLEXCOMM0, 0); -impl_instance!(USART1, FLEXCOMM1, 1); -impl_instance!(USART2, FLEXCOMM2, 2); -impl_instance!(USART3, FLEXCOMM3, 3); -impl_instance!(USART4, FLEXCOMM4, 4); -impl_instance!(USART5, FLEXCOMM5, 5); -impl_instance!(USART6, FLEXCOMM6, 6); -impl_instance!(USART7, FLEXCOMM7, 7); - pub(crate) trait SealedTxPin: crate::gpio::Pin { fn pin_func(&self) -> PioFunc; } @@ -892,75 +894,46 @@ pub trait TxPin: SealedTxPin + crate::gpio::Pin {} #[allow(private_bounds)] pub trait RxPin: SealedRxPin + crate::gpio::Pin {} -macro_rules! impl_tx_pin { +macro_rules! impl_usart_txd_pin { ($pin:ident, $instance:ident, $func: ident) => { - impl SealedTxPin for crate::peripherals::$pin { - fn pin_func(&self) -> PioFunc { + impl crate::usart::SealedTxPin for crate::peripherals::$pin { + fn pin_func(&self) -> crate::pac::iocon::vals::PioFunc { + use crate::pac::iocon::vals::PioFunc; PioFunc::$func } } - impl TxPin for crate::peripherals::$pin {} + impl crate::usart::TxPin for crate::peripherals::$pin {} }; } -macro_rules! impl_rx_pin { +macro_rules! impl_usart_rxd_pin { ($pin:ident, $instance:ident, $func: ident) => { - impl SealedRxPin for crate::peripherals::$pin { - fn pin_func(&self) -> PioFunc { + impl crate::usart::SealedRxPin for crate::peripherals::$pin { + fn pin_func(&self) -> crate::pac::iocon::vals::PioFunc { + use crate::pac::iocon::vals::PioFunc; PioFunc::$func } } - impl RxPin for crate::peripherals::$pin {} + impl crate::usart::RxPin for crate::peripherals::$pin {} }; } -impl_tx_pin!(PIO1_6, USART0, ALT1); -impl_tx_pin!(PIO1_11, USART1, ALT2); -impl_tx_pin!(PIO0_27, USART2, ALT1); -impl_tx_pin!(PIO0_2, USART3, ALT1); -impl_tx_pin!(PIO0_16, USART4, ALT1); -impl_tx_pin!(PIO0_9, USART5, ALT3); -impl_tx_pin!(PIO1_16, USART6, ALT2); -impl_tx_pin!(PIO0_19, USART7, ALT7); - -impl_rx_pin!(PIO1_5, USART0, ALT1); -impl_rx_pin!(PIO1_10, USART1, ALT2); -impl_rx_pin!(PIO1_24, USART2, ALT1); -impl_rx_pin!(PIO0_3, USART3, ALT1); -impl_rx_pin!(PIO0_5, USART4, ALT2); -impl_rx_pin!(PIO0_8, USART5, ALT3); -impl_rx_pin!(PIO1_13, USART6, ALT2); -impl_rx_pin!(PIO0_20, USART7, ALT7); - -/// Trait for TX DMA channels. +/// Marker trait indicating a DMA channel may be used for USART transmit. pub trait TxChannel: crate::dma::Channel {} -/// Trait for RX DMA channels. + +/// Marker trait indicating a DMA channel may be used for USART recieve. pub trait RxChannel: crate::dma::Channel {} -macro_rules! impl_channel { - ($dma:ident, $instance:ident, Tx) => { - impl TxChannel for crate::peripherals::$dma {} - }; - ($dma:ident, $instance:ident, Rx) => { - impl RxChannel for crate::peripherals::$dma {} +macro_rules! impl_usart_tx_channel { + ($instance: ident, $channel: ident) => { + impl crate::usart::TxChannel for crate::peripherals::$channel {} }; } -impl_channel!(DMA_CH4, USART0, Rx); -impl_channel!(DMA_CH5, USART0, Tx); -impl_channel!(DMA_CH6, USART1, Rx); -impl_channel!(DMA_CH7, USART1, Tx); -impl_channel!(DMA_CH10, USART2, Rx); -impl_channel!(DMA_CH11, USART2, Tx); -impl_channel!(DMA_CH8, USART3, Rx); -impl_channel!(DMA_CH9, USART3, Tx); -impl_channel!(DMA_CH12, USART4, Rx); -impl_channel!(DMA_CH13, USART4, Tx); -impl_channel!(DMA_CH14, USART5, Rx); -impl_channel!(DMA_CH15, USART5, Tx); -impl_channel!(DMA_CH16, USART6, Rx); -impl_channel!(DMA_CH17, USART6, Tx); -impl_channel!(DMA_CH18, USART7, Rx); -impl_channel!(DMA_CH19, USART7, Tx); +macro_rules! impl_usart_rx_channel { + ($instance: ident, $channel: ident) => { + impl crate::usart::RxChannel for crate::peripherals::$channel {} + }; +} diff --git a/examples/lpc55s69/src/bin/pwm.rs b/examples/lpc55s69/src/bin/pwm.rs index 93b898b9d..8a9894b94 100644 --- a/examples/lpc55s69/src/bin/pwm.rs +++ b/examples/lpc55s69/src/bin/pwm.rs @@ -10,7 +10,7 @@ use {defmt_rtt as _, panic_halt as _}; #[embassy_executor::main] async fn main(_spawner: Spawner) { let p = embassy_nxp::init(Default::default()); - let pwm = Pwm::new_output(p.PWM_OUTPUT1, p.PIO0_18, Config::new(1_000_000_000, 2_000_000_000)); + let pwm = Pwm::new_output(p.SCT0_OUT1, p.PIO0_18, Config::new(1_000_000_000, 2_000_000_000)); loop { info!("Counter: {}", pwm.counter()); Timer::after_millis(50).await; diff --git a/examples/lpc55s69/src/bin/usart_async.rs b/examples/lpc55s69/src/bin/usart_async.rs index b06abd477..a9815b920 100644 --- a/examples/lpc55s69/src/bin/usart_async.rs +++ b/examples/lpc55s69/src/bin/usart_async.rs @@ -38,8 +38,8 @@ async fn main(spawner: Spawner) { p.PIO0_27, p.PIO1_24, Irqs, - p.DMA_CH11, - p.DMA_CH10, + p.DMA0_CH11, + p.DMA0_CH10, Config::default(), ); let led = Output::new(p.PIO1_6, Level::Low); -- cgit