diff --git a/esp-hal-procmacros/src/lib.rs b/esp-hal-procmacros/src/lib.rs index de0cc6bae..9f5385382 100644 --- a/esp-hal-procmacros/src/lib.rs +++ b/esp-hal-procmacros/src/lib.rs @@ -74,7 +74,12 @@ mod embassy; mod enum_dispatch; #[cfg(feature = "interrupt")] mod interrupt; -#[cfg(any(feature = "is-lp-core", feature = "is-ulp-core"))] +#[cfg(any( + feature = "is-lp-core", + feature = "is-ulp-core", + feature = "has-lp-core", + feature = "has-ulp-core" +))] mod lp_core; #[cfg(feature = "ram")] @@ -318,283 +323,15 @@ pub fn make_gpio_enum_dispatch_macro(input: TokenStream) -> TokenStream { #[cfg(any(feature = "has-lp-core", feature = "has-ulp-core"))] #[proc_macro] pub fn load_lp_code(input: TokenStream) -> TokenStream { - use std::{fs, path::Path}; - - use litrs::StringLit; - use object::{File, Object, ObjectSection, ObjectSymbol, Section, SectionKind}; - use parse::Error; - use proc_macro::Span; - use proc_macro_crate::{crate_name, FoundCrate}; - use quote::quote; - use syn::{parse, Ident}; - - let hal_crate = if cfg!(any(feature = "is-lp-core", feature = "is-ulp-core")) { - crate_name("esp-lp-hal") - } else { - crate_name("esp-hal") - }; - - let hal_crate = if let Ok(FoundCrate::Name(ref name)) = hal_crate { - let ident = Ident::new(&name, Span::call_site().into()); - quote!( #ident ) - } else { - quote!(crate) - }; - - let first_token = match input.into_iter().next() { - Some(token) => token, - None => { - return Error::new( - Span::call_site().into(), - "You need to give the path to an ELF file", - ) - .to_compile_error() - .into(); - } - }; - let arg = match StringLit::try_from(&first_token) { - Ok(arg) => arg, - Err(_) => { - return Error::new( - Span::call_site().into(), - "You need to give the path to an ELF file", - ) - .to_compile_error() - .into(); - } - }; - let elf_file = arg.value(); - - if !Path::new(elf_file).exists() { - return Error::new(Span::call_site().into(), "File not found") - .to_compile_error() - .into(); - } - - let bin_data = fs::read(elf_file).unwrap(); - let obj_file = File::parse(&*bin_data).unwrap(); - let sections = obj_file.sections(); - - let mut sections: Vec
= sections - .into_iter() - .filter(|section| match section.kind() { - SectionKind::Text - | SectionKind::ReadOnlyData - | SectionKind::Data - | SectionKind::UninitializedData => true, - _ => false, - }) - .collect(); - sections.sort_by(|a, b| a.address().partial_cmp(&b.address()).unwrap()); - - let mut binary: Vec = Vec::new(); - let mut last_address = if cfg!(feature = "has-lp-core") { - 0x5000_0000 - } else { - 0x0 - }; - - for section in sections { - if section.address() > last_address { - for _ in 0..(section.address() - last_address) { - binary.push(0); - } - } - - binary.extend_from_slice(section.data().unwrap()); - last_address = section.address() + section.size(); - } - - let magic_symbol = obj_file - .symbols() - .find(|s| s.name().unwrap().starts_with("__ULP_MAGIC_")); - - if let None = magic_symbol { - return Error::new( - Span::call_site().into(), - "Given file doesn't seem to be an LP/ULP core application.", - ) - .to_compile_error() - .into(); - } - - let magic_symbol = magic_symbol.unwrap().name().unwrap(); - - let magic_symbol = magic_symbol.trim_start_matches("__ULP_MAGIC_"); - let args: Vec = magic_symbol - .split("$") - .into_iter() - .map(|t| { - let t = t.replace("GpioPin", "LowPowerPin"); - t.parse().unwrap() - }) - .filter(|v: &proc_macro2::TokenStream| !v.is_empty()) - .collect(); - - #[cfg(feature = "has-lp-core")] - let imports = quote! { - use #hal_crate::lp_core::LpCore; - use #hal_crate::lp_core::LpCoreWakeupSource; - use #hal_crate::gpio::lp_io::LowPowerPin; - use #hal_crate::gpio::*; - use #hal_crate::uart::lp_uart::LpUart; - use #hal_crate::i2c::lp_i2c::LpI2c; - }; - #[cfg(feature = "has-ulp-core")] - let imports = quote! { - use #hal_crate::ulp_core::UlpCore as LpCore; - use #hal_crate::ulp_core::UlpCoreWakeupSource as LpCoreWakeupSource; - use #hal_crate::gpio::*; - }; - - #[cfg(feature = "has-lp-core")] - let rtc_code_start = quote! { _rtc_fast_data_start }; - #[cfg(feature = "has-ulp-core")] - let rtc_code_start = quote! { _rtc_slow_data_start }; - - quote! { - { - #imports - - struct LpCoreCode {} - - static LP_CODE: &[u8] = &[#(#binary),*]; - - extern "C" { - static #rtc_code_start: u32; - } - - unsafe { - core::ptr::copy_nonoverlapping(LP_CODE as *const _ as *const u8, &#rtc_code_start as *const u32 as *mut u8, LP_CODE.len()); - } - - impl LpCoreCode { - pub fn run( - &self, - lp_core: &mut LpCore, - wakeup_source: LpCoreWakeupSource, - #(_: #args),* - ) { - lp_core.run(wakeup_source); - } - } - - LpCoreCode {} - } - } - .into() + lp_core::load_lp_code(input) } +/// Marks the entry function of a LP core / ULP program. #[cfg(any(feature = "is-lp-core", feature = "is-ulp-core"))] #[proc_macro_error::proc_macro_error] #[proc_macro_attribute] pub fn entry(args: TokenStream, input: TokenStream) -> TokenStream { - use proc_macro2::{Ident, Span}; - use proc_macro_crate::{crate_name, FoundCrate}; - use quote::{format_ident, quote}; - use syn::{ - parse::{self, Error}, - parse_macro_input, - spanned::Spanned, - FnArg, - ItemFn, - }; - - use self::lp_core::{extract_pin, get_simplename, make_magic_symbol_name}; - - let found_crate = crate_name("esp-lp-hal").expect("esp-lp-hal is present in `Cargo.toml`"); - let hal_crate = match found_crate { - FoundCrate::Itself => quote!(esp_lp_hal), - FoundCrate::Name(name) => { - let ident = Ident::new(&name, Span::call_site()); - quote!( #ident ) - } - }; - - if !args.is_empty() { - return Error::new(Span::call_site(), "This attribute accepts no arguments") - .to_compile_error() - .into(); - } - - let f = parse_macro_input!(input as ItemFn); - - let mut argument_types = Vec::new(); - let mut create_peripheral = Vec::new(); - - let mut used_pins: Vec = Vec::new(); - - for (num, arg) in f.sig.inputs.iter().enumerate() { - let param_name = format_ident!("param{}", num); - match arg { - FnArg::Receiver(_) => { - return Error::new(arg.span(), "invalid argument") - .to_compile_error() - .into(); - } - FnArg::Typed(t) => { - match get_simplename(&t.ty).as_str() { - "GpioPin" => { - let pin = extract_pin(&t.ty); - if used_pins.contains(&pin) { - return Error::new(arg.span(), "duplicate pin") - .to_compile_error() - .into(); - } - used_pins.push(pin); - create_peripheral.push(quote!( - let mut #param_name = unsafe { the_hal::gpio::conjure().unwrap() }; - )); - } - "LpUart" => { - create_peripheral.push(quote!( - let mut #param_name = unsafe { the_hal::uart::conjure() }; - )); - } - "LpI2c" => { - create_peripheral.push(quote!( - let mut #param_name = unsafe { the_hal::i2c::conjure() }; - )); - } - _ => { - return Error::new(arg.span(), "invalid argument to main") - .to_compile_error() - .into(); - } - } - argument_types.push(t); - } - } - } - - let magic_symbol_name = make_magic_symbol_name(&argument_types); - - let param_names: Vec = argument_types - .into_iter() - .enumerate() - .map(|(num, _)| format_ident!("param{}", num)) - .collect(); - - quote!( - #[allow(non_snake_case)] - #[export_name = "main"] - pub fn __risc_v_rt__main() -> ! { - #[export_name = #magic_symbol_name] - static ULP_MAGIC: [u32; 0] = [0u32; 0]; - - unsafe { ULP_MAGIC.as_ptr().read_volatile(); } - - use #hal_crate as the_hal; - #( - #create_peripheral; - )* - - main(#(#param_names),*); - } - - #f - ) - .into() + lp_core::entry(args, input) } /// Creates a new `executor` instance and declares an application entry point diff --git a/esp-hal-procmacros/src/lp_core.rs b/esp-hal-procmacros/src/lp_core.rs index 45fee2f76..96f69bfa4 100644 --- a/esp-hal-procmacros/src/lp_core.rs +++ b/esp-hal-procmacros/src/lp_core.rs @@ -1,71 +1,375 @@ +#[allow(unused)] +use proc_macro::TokenStream; use quote::quote; -use syn::{GenericArgument, PatType, PathArguments, Type}; -pub(crate) fn make_magic_symbol_name(args: &Vec<&PatType>) -> String { - let mut res = String::from("__ULP_MAGIC_"); - for &a in args { - let t = &a.ty; - let quoted = to_string(&t); - res.push_str("ed); - res.push_str("$"); +#[cfg(any(feature = "is-lp-core", feature = "is-ulp-core"))] +pub fn entry(args: TokenStream, input: TokenStream) -> TokenStream { + use proc_macro2::{Ident, Span}; + use proc_macro_crate::{crate_name, FoundCrate}; + use quote::{format_ident, quote}; + use syn::{ + parse::Error, + parse_macro_input, + spanned::Spanned, + FnArg, + GenericArgument, + ItemFn, + PatType, + PathArguments, + Type, + }; + + pub(crate) fn make_magic_symbol_name(args: &Vec<&PatType>) -> String { + let mut res = String::from("__ULP_MAGIC_"); + for &a in args { + let t = &a.ty; + let quoted = to_string(&t); + res.push_str("ed); + res.push_str("$"); + } + + res } - res -} + pub(crate) fn get_simplename(t: &Type) -> String { + String::from(match t { + Type::Path(p) => String::from(&p.path.segments.last().unwrap().ident.to_string()), + _ => String::new(), + }) + } -pub(crate) fn get_simplename(t: &Type) -> String { - String::from(match t { - Type::Path(p) => String::from(&p.path.segments.last().unwrap().ident.to_string()), - _ => String::new(), - }) -} - -pub(crate) fn extract_pin(ty: &Type) -> u8 { - let mut res = 255u8; - if let Type::Path(p) = ty { - let segment = p.path.segments.last().unwrap(); - if let PathArguments::AngleBracketed(g) = &segment.arguments { - for arg in &g.args { - match arg { - GenericArgument::Type(t) => { - res = extract_pin(t); + pub(crate) fn extract_pin(ty: &Type) -> u8 { + let mut res = 255u8; + if let Type::Path(p) = ty { + let segment = p.path.segments.last().unwrap(); + if let PathArguments::AngleBracketed(g) = &segment.arguments { + for arg in &g.args { + match arg { + GenericArgument::Type(t) => { + res = extract_pin(t); + } + GenericArgument::Const(c) => { + res = ("e! { #c }.to_string()).parse().unwrap(); + } + _ => (), } - GenericArgument::Const(c) => { - res = ("e! { #c }.to_string()).parse().unwrap(); - } - _ => (), } } } + + res } - res -} + // This is a specialized implementation - won't fit other use-cases + fn to_string(ty: &Type) -> String { + let mut res = String::new(); + if let Type::Path(p) = ty { + let segment = p.path.segments.last().unwrap(); + res.push_str(&segment.ident.to_string()); -// This is a specialized implementation - won't fit other use-cases -fn to_string(ty: &Type) -> String { - let mut res = String::new(); - if let Type::Path(p) = ty { - let segment = p.path.segments.last().unwrap(); - res.push_str(&segment.ident.to_string()); - - if let PathArguments::AngleBracketed(g) = &segment.arguments { - res.push_str("<"); - for arg in &g.args { - match arg { - GenericArgument::Type(t) => { - res.push_str(&to_string(t)); - } - GenericArgument::Const(c) => { + if let PathArguments::AngleBracketed(g) = &segment.arguments { + res.push_str("<"); + let mut pushed = false; + for arg in &g.args { + if pushed { res.push_str(","); - res.push_str("e! { #c }.to_string()); } - _ => (), + + match arg { + GenericArgument::Type(t) => { + pushed = true; + res.push_str(&to_string(t)); + } + GenericArgument::Const(c) => { + pushed = true; + res.push_str("e! { #c }.to_string()); + } + _ => (), + } } + res.push_str(">"); + } + } + + res + } + + let found_crate = crate_name("esp-lp-hal").expect("esp-lp-hal is present in `Cargo.toml`"); + let hal_crate = match found_crate { + FoundCrate::Itself => quote!(esp_lp_hal), + FoundCrate::Name(name) => { + let ident = Ident::new(&name, Span::call_site()); + quote!( #ident ) + } + }; + + if !args.is_empty() { + return Error::new(Span::call_site(), "This attribute accepts no arguments") + .to_compile_error() + .into(); + } + + let f = parse_macro_input!(input as ItemFn); + + let mut argument_types = Vec::new(); + let mut create_peripheral = Vec::new(); + + let mut used_pins: Vec = Vec::new(); + + for (num, arg) in f.sig.inputs.iter().enumerate() { + let param_name = format_ident!("param{}", num); + match arg { + FnArg::Receiver(_) => { + return Error::new(arg.span(), "invalid argument") + .to_compile_error() + .into(); + } + FnArg::Typed(t) => { + match get_simplename(&t.ty).as_str() { + "Output" => { + let pin = extract_pin(&t.ty); + if used_pins.contains(&pin) { + return Error::new(arg.span(), "duplicate pin") + .to_compile_error() + .into(); + } + used_pins.push(pin); + create_peripheral.push(quote!( + let mut #param_name = unsafe { the_hal::gpio::conjure_output().unwrap() }; + )); + } + "Input" => { + let pin = extract_pin(&t.ty); + if used_pins.contains(&pin) { + return Error::new(arg.span(), "duplicate pin") + .to_compile_error() + .into(); + } + used_pins.push(pin); + create_peripheral.push(quote!( + let mut #param_name = unsafe { the_hal::gpio::conjure_input().unwrap() }; + )); + } + "LpUart" => { + create_peripheral.push(quote!( + let mut #param_name = unsafe { the_hal::uart::conjure() }; + )); + } + "LpI2c" => { + create_peripheral.push(quote!( + let mut #param_name = unsafe { the_hal::i2c::conjure() }; + )); + } + _ => { + return Error::new(arg.span(), "invalid argument to main") + .to_compile_error() + .into(); + } + } + argument_types.push(t); } - res.push_str(">"); } } - res + let magic_symbol_name = make_magic_symbol_name(&argument_types); + + let param_names: Vec = argument_types + .into_iter() + .enumerate() + .map(|(num, _)| format_ident!("param{}", num)) + .collect(); + + quote!( + #[allow(non_snake_case)] + #[export_name = "main"] + pub fn __risc_v_rt__main() -> ! { + #[export_name = #magic_symbol_name] + static ULP_MAGIC: [u32; 0] = [0u32; 0]; + + unsafe { ULP_MAGIC.as_ptr().read_volatile(); } + + use #hal_crate as the_hal; + #( + #create_peripheral; + )* + + main(#(#param_names),*); + } + + #f + ) + .into() +} + +#[cfg(any(feature = "has-lp-core", feature = "has-ulp-core"))] +pub fn load_lp_code(input: TokenStream) -> TokenStream { + use std::{fs, path::Path}; + + use litrs::StringLit; + use object::{File, Object, ObjectSection, ObjectSymbol, Section, SectionKind}; + use parse::Error; + use proc_macro::Span; + use proc_macro_crate::{crate_name, FoundCrate}; + use syn::{parse, Ident}; + + let hal_crate = if cfg!(any(feature = "is-lp-core", feature = "is-ulp-core")) { + crate_name("esp-lp-hal") + } else { + crate_name("esp-hal") + }; + + let hal_crate = if let Ok(FoundCrate::Name(ref name)) = hal_crate { + let ident = Ident::new(&name, Span::call_site().into()); + quote!( #ident ) + } else { + quote!(crate) + }; + + let first_token = match input.into_iter().next() { + Some(token) => token, + None => { + return Error::new( + Span::call_site().into(), + "You need to give the path to an ELF file", + ) + .to_compile_error() + .into(); + } + }; + let arg = match StringLit::try_from(&first_token) { + Ok(arg) => arg, + Err(_) => { + return Error::new( + Span::call_site().into(), + "You need to give the path to an ELF file", + ) + .to_compile_error() + .into(); + } + }; + let elf_file = arg.value(); + + if !Path::new(elf_file).exists() { + return Error::new(Span::call_site().into(), "File not found") + .to_compile_error() + .into(); + } + + let bin_data = fs::read(elf_file).unwrap(); + let obj_file = File::parse(&*bin_data).unwrap(); + let sections = obj_file.sections(); + + let mut sections: Vec
= sections + .into_iter() + .filter(|section| match section.kind() { + SectionKind::Text + | SectionKind::ReadOnlyData + | SectionKind::Data + | SectionKind::UninitializedData => true, + _ => false, + }) + .collect(); + sections.sort_by(|a, b| a.address().partial_cmp(&b.address()).unwrap()); + + let mut binary: Vec = Vec::new(); + let mut last_address = if cfg!(feature = "has-lp-core") { + 0x5000_0000 + } else { + 0x0 + }; + + for section in sections { + if section.address() > last_address { + for _ in 0..(section.address() - last_address) { + binary.push(0); + } + } + + binary.extend_from_slice(section.data().unwrap()); + last_address = section.address() + section.size(); + } + + let magic_symbol = obj_file + .symbols() + .find(|s| s.name().unwrap().starts_with("__ULP_MAGIC_")); + + if let None = magic_symbol { + return Error::new( + Span::call_site().into(), + "Given file doesn't seem to be an LP/ULP core application.", + ) + .to_compile_error() + .into(); + } + + let magic_symbol = magic_symbol.unwrap().name().unwrap(); + + let magic_symbol = magic_symbol.trim_start_matches("__ULP_MAGIC_"); + let args: Vec = magic_symbol + .split("$") + .into_iter() + .map(|t| { + let t = if t.contains("OutputOpenDrain") { + t.replace("OutputOpenDrain", "LowPowerOutputOpenDrain") + } else { + t.replace("Output", "LowPowerOutput") + }; + let t = t.replace("Input", "LowPowerInput"); + t.parse().unwrap() + }) + .filter(|v: &proc_macro2::TokenStream| !v.is_empty()) + .collect(); + + #[cfg(feature = "has-lp-core")] + let imports = quote! { + use #hal_crate::lp_core::LpCore; + use #hal_crate::lp_core::LpCoreWakeupSource; + use #hal_crate::gpio::lp_io::LowPowerOutput; + use #hal_crate::gpio::*; + use #hal_crate::uart::lp_uart::LpUart; + use #hal_crate::i2c::lp_i2c::LpI2c; + }; + #[cfg(feature = "has-ulp-core")] + let imports = quote! { + use #hal_crate::ulp_core::UlpCore as LpCore; + use #hal_crate::ulp_core::UlpCoreWakeupSource as LpCoreWakeupSource; + use #hal_crate::gpio::*; + }; + + #[cfg(feature = "has-lp-core")] + let rtc_code_start = quote! { _rtc_fast_data_start }; + #[cfg(feature = "has-ulp-core")] + let rtc_code_start = quote! { _rtc_slow_data_start }; + + quote! { + { + #imports + + struct LpCoreCode {} + + static LP_CODE: &[u8] = &[#(#binary),*]; + + extern "C" { + static #rtc_code_start: u32; + } + + unsafe { + core::ptr::copy_nonoverlapping(LP_CODE as *const _ as *const u8, &#rtc_code_start as *const u32 as *mut u8, LP_CODE.len()); + } + + impl LpCoreCode { + pub fn run( + &self, + lp_core: &mut LpCore, + wakeup_source: LpCoreWakeupSource, + #(_: #args),* + ) { + lp_core.run(wakeup_source); + } + } + + LpCoreCode {} + } + } + .into() } diff --git a/esp-hal/CHANGELOG.md b/esp-hal/CHANGELOG.md index c905c5a26..4d32b22e1 100644 --- a/esp-hal/CHANGELOG.md +++ b/esp-hal/CHANGELOG.md @@ -40,6 +40,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Removed the `embassy-executor-thread` and `embassy-executor-interrupt` features, they are now enabled by default when `embassy` is enabled. (#1485) - Software interrupt 3 is now used instead of software interrupt 0 on the thread aware executor on multicore systems (#1485) - Timer abstraction: refactor `systimer` and `timer` modules into a common `timer` module (#1527) +- Refactoring of GPIO module, have drivers for Input,Output,OutputOpenDrain, all drivers setup their GPIOs correctly (#1542) ### Removed diff --git a/esp-hal/Cargo.toml b/esp-hal/Cargo.toml index 8b43b8604..19cfcefc8 100644 --- a/esp-hal/Cargo.toml +++ b/esp-hal/Cargo.toml @@ -20,6 +20,7 @@ bitfield = "0.15.0" cfg-if = "1.0.0" critical-section = "1.1.2" defmt = { version = "0.3.6", optional = true } +delegate = "0.12.0" document-features = "0.2.8" embassy-executor = { version = "0.5.0", optional = true } embassy-futures = { version = "0.1.1", optional = true } diff --git a/esp-hal/src/analog/adc/mod.rs b/esp-hal/src/analog/adc/mod.rs index 24c74cc06..0b479d053 100644 --- a/esp-hal/src/analog/adc/mod.rs +++ b/esp-hal/src/analog/adc/mod.rs @@ -9,7 +9,7 @@ //! ```no_run //! let mut adc1_config = AdcConfig::new(); //! let mut adc1 = ADC::::new(peripherals.ADC1, adc1_config); -//! let mut pin = adc1_config.enable_pin(io.pins.gpio2.into_analog(), Attenuation::Attenuation11dB); +//! let mut pin = adc1_config.enable_pin(io.pins.gpio2, Attenuation::Attenuation11dB); //! //! let mut delay = Delay::new(&clocks); //! @@ -24,6 +24,7 @@ use core::marker::PhantomData; pub use self::implementation::*; +use crate::gpio::AnalogPin; #[cfg_attr(esp32, path = "esp32.rs")] #[cfg_attr(riscv, path = "riscv.rs")] @@ -93,8 +94,10 @@ impl AdcConfig { /// Enable the specified pin with the given attenuation pub fn enable_pin(&mut self, pin: PIN, attenuation: Attenuation) -> AdcPin where - PIN: AdcChannel, + PIN: AdcChannel + AnalogPin, { + // TODO revert this on drop + pin.set_analog(crate::private::Internal); self.attenuations[PIN::CHANNEL as usize] = Some(attenuation); AdcPin { @@ -104,7 +107,7 @@ impl AdcConfig { } } - /// Enable the specified pin with the given attentuation and calibration + /// Enable the specified pin with the given attenuation and calibration /// scheme #[cfg(not(esp32))] pub fn enable_pin_with_cal( @@ -114,9 +117,11 @@ impl AdcConfig { ) -> AdcPin where ADCI: CalibrationAccess, - PIN: AdcChannel, + PIN: AdcChannel + AnalogPin, CS: AdcCalScheme, { + // TODO revert this on drop + pin.set_analog(crate::private::Internal); self.attenuations[PIN::CHANNEL as usize] = Some(attenuation); AdcPin { @@ -206,12 +211,12 @@ macro_rules! impl_adc_interface { $( ($pin:ident, $channel:expr) ,)+ ]) => { $( - impl $crate::analog::adc::AdcChannel for crate::gpio::$pin { + impl $crate::analog::adc::AdcChannel for crate::gpio::$pin { const CHANNEL: u8 = $channel; } #[cfg(feature = "embedded-hal-02")] - impl embedded_hal_02::adc::Channel for crate::gpio::$pin { + impl embedded_hal_02::adc::Channel for crate::gpio::$pin { type ID = u8; fn channel() -> u8 { $channel } diff --git a/esp-hal/src/analog/dac.rs b/esp-hal/src/analog/dac.rs index b2b3e71e8..be52b8f8e 100644 --- a/esp-hal/src/analog/dac.rs +++ b/esp-hal/src/analog/dac.rs @@ -13,8 +13,8 @@ //! //! ```no_run //! let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); -//! let gpio25 = io.pins.gpio25.into_analog(); -//! let gpio26 = io.pins.gpio26.into_analog(); +//! let gpio25 = io.pins.gpio25; +//! let gpio26 = io.pins.gpio26; //! //! let mut dac1 = Dac1::new(peripherals.DAC1, gpio25); //! let mut dac2 = Dac2::new(peripherals.DAC2, gpio26); @@ -37,18 +37,18 @@ //! ``` use crate::{ - gpio, + gpio::{self, AnalogPin}, peripheral::{Peripheral, PeripheralRef}, peripherals, }; cfg_if::cfg_if! { if #[cfg(esp32)] { - type Dac1Gpio = gpio::Gpio25; - type Dac2Gpio = gpio::Gpio26; + type Dac1Gpio = gpio::Gpio25; + type Dac2Gpio = gpio::Gpio26; } else if #[cfg(esp32s2)] { - type Dac1Gpio = gpio::Gpio17; - type Dac2Gpio = gpio::Gpio18; + type Dac1Gpio = gpio::Gpio17; + type Dac2Gpio = gpio::Gpio18; } } @@ -59,8 +59,10 @@ pub struct Dac1<'d> { impl<'d> Dac1<'d> { /// Constructs a new DAC instance. - pub fn new(dac: impl Peripheral

+ 'd, _pin: Dac1Gpio) -> Self { + pub fn new(dac: impl Peripheral

+ 'd, pin: Dac1Gpio) -> Self { crate::into_ref!(dac); + // TODO revert this on drop + pin.set_analog(crate::private::Internal); #[cfg(esp32s2)] unsafe { &*peripherals::SENS::PTR } @@ -96,8 +98,10 @@ pub struct Dac2<'d> { impl<'d> Dac2<'d> { /// Constructs a new DAC instance. - pub fn new(dac: impl Peripheral

+ 'd, _pin: Dac2Gpio) -> Self { + pub fn new(dac: impl Peripheral

+ 'd, pin: Dac2Gpio) -> Self { crate::into_ref!(dac); + // TODO revert this on drop + pin.set_analog(crate::private::Internal); #[cfg(esp32s2)] unsafe { &*peripherals::SENS::PTR } diff --git a/esp-hal/src/gpio/any_pin.rs b/esp-hal/src/gpio/any_pin.rs new file mode 100644 index 000000000..766a7ec2c --- /dev/null +++ b/esp-hal/src/gpio/any_pin.rs @@ -0,0 +1,286 @@ +//! Type-erased wrappers for GPIO pins. +//! These are useful to pass them into peripheral drivers. +//! +//! If you want a generic pin for GPIO input/output look into +//! [Output],[OutputOpenDrain] and [Input] + +use super::*; + +#[derive(Clone, Copy)] +enum Inverted { + NonInverted, + Inverted, +} + +impl Inverted { + fn is_inverted(&self) -> bool { + match self { + Inverted::NonInverted => false, + Inverted::Inverted => true, + } + } +} + +/// Generic pin wrapper for pins which can be Output or Input. +pub struct AnyPin<'d> { + pin: ErasedPin, + inverted: Inverted, + _phantom: PhantomData<&'d ()>, +} + +impl<'d> AnyPin<'d> { + /// Create wrapper for the given pin. + #[inline] + pub fn new( + pin: impl crate::peripheral::Peripheral

+ 'd, + ) -> Self { + crate::into_ref!(pin); + let pin = pin.erased_pin(private::Internal); + + Self { + pin, + inverted: Inverted::NonInverted, + _phantom: PhantomData, + } + } + + /// Create wrapper for the given pin. The peripheral signal will be + /// inverted. + #[inline] + pub fn new_inverted( + pin: impl crate::peripheral::Peripheral

+ 'd, + ) -> Self { + crate::into_ref!(pin); + let pin = pin.erased_pin(private::Internal); + + Self { + pin, + inverted: Inverted::Inverted, + _phantom: PhantomData, + } + } +} + +impl<'d> crate::peripheral::Peripheral for AnyPin<'d> { + type P = Self; + + unsafe fn clone_unchecked(&mut self) -> Self::P { + Self { + pin: unsafe { self.pin.clone_unchecked() }, + inverted: self.inverted, + _phantom: PhantomData, + } + } +} + +impl<'d> private::Sealed for AnyPin<'d> {} + +impl<'d> Pin for AnyPin<'d> { + delegate::delegate! { + to self.pin { + fn number(&self, _internal: private::Internal) -> u8; + fn sleep_mode(&mut self, on: bool, _internal: private::Internal); + fn set_alternate_function(&mut self, alternate: AlternateFunction, _internal: private::Internal); + fn is_listening(&self, _internal: private::Internal) -> bool; + fn listen_with_options( + &mut self, + event: Event, + int_enable: bool, + nmi_enable: bool, + wake_up_from_light_sleep: bool, + _internal: private::Internal, + ); + fn unlisten(&mut self, _internal: private::Internal); + fn is_interrupt_set(&self, _internal: private::Internal) -> bool; + fn clear_interrupt(&mut self, _internal: private::Internal); + } + } +} + +impl<'d> OutputPin for AnyPin<'d> { + delegate::delegate! { + to self.pin { + fn set_to_open_drain_output(&mut self, _internal: private::Internal); + fn set_to_push_pull_output(&mut self, _internal: private::Internal); + fn enable_output(&mut self, on: bool, _internal: private::Internal); + fn set_output_high(&mut self, on: bool, _internal: private::Internal); + fn set_drive_strength(&mut self, strength: DriveStrength, _internal: private::Internal); + fn enable_open_drain(&mut self, on: bool, _internal: private::Internal); + fn enable_output_in_sleep_mode(&mut self, on: bool, _internal: private::Internal); + fn internal_pull_up_in_sleep_mode(&mut self, on: bool, _internal: private::Internal); + fn internal_pull_down_in_sleep_mode(&mut self, on: bool, _internal: private::Internal); + fn internal_pull_up(&mut self, on: bool, _internal: private::Internal); + fn internal_pull_down(&mut self, on: bool, _internal: private::Internal); + fn disconnect_peripheral_from_output(&mut self, _internal: private::Internal); + fn is_set_high(&self, _internal: private::Internal) -> bool; + } + } + + fn connect_peripheral_to_output(&mut self, signal: OutputSignal, _internal: private::Internal) { + self.pin.connect_peripheral_to_output_with_options( + signal, + self.inverted.is_inverted(), + false, + false, + self.inverted.is_inverted(), + private::Internal, + ); + } + + fn connect_peripheral_to_output_with_options( + &mut self, + signal: OutputSignal, + invert: bool, + invert_enable: bool, + enable_from_gpio: bool, + force_via_gpio_mux: bool, + _internal: private::Internal, + ) { + if self.inverted.is_inverted() { + self.pin.connect_peripheral_to_output_with_options( + signal, + true, + false, + false, + true, + private::Internal, + ); + } else { + self.pin.connect_peripheral_to_output_with_options( + signal, + invert, + invert_enable, + enable_from_gpio, + force_via_gpio_mux, + private::Internal, + ); + } + } +} + +impl<'d> InputPin for AnyPin<'d> { + delegate::delegate! { + to self.pin { + fn init_input(&self, pull_down: bool, pull_up: bool, _internal: private::Internal); + fn set_to_input(&mut self, _internal: private::Internal); + fn enable_input(&mut self, on: bool, _internal: private::Internal); + fn enable_input_in_sleep_mode(&mut self, on: bool, _internal: private::Internal); + fn is_input_high(&self, _internal: private::Internal) -> bool; + fn disconnect_input_from_peripheral(&mut self, signal: InputSignal, _internal: private::Internal); + } + } + + fn connect_input_to_peripheral(&mut self, signal: InputSignal, _internal: private::Internal) { + self.pin.connect_input_to_peripheral_with_options( + signal, + self.inverted.is_inverted(), + self.inverted.is_inverted(), + private::Internal, + ); + } + + fn connect_input_to_peripheral_with_options( + &mut self, + signal: InputSignal, + invert: bool, + force_via_gpio_mux: bool, + _internal: private::Internal, + ) { + if self.inverted.is_inverted() { + self.pin.connect_input_to_peripheral_with_options( + signal, + true, + true, + private::Internal, + ); + } else { + self.pin.connect_input_to_peripheral_with_options( + signal, + invert, + force_via_gpio_mux, + private::Internal, + ); + } + } +} + +/// Generic pin wrapper for pins which can only be Input. +pub struct AnyInputOnlyPin<'d> { + pin: ErasedPin, + inverted: Inverted, + _phantom: PhantomData<&'d ()>, +} + +impl<'d> AnyInputOnlyPin<'d> { + /// Create wrapper for the given pin. + #[inline] + pub fn new( + pin: impl crate::peripheral::Peripheral

+ 'd, + ) -> Self { + crate::into_ref!(pin); + let pin = pin.erased_pin(private::Internal); + + Self { + pin, + inverted: Inverted::NonInverted, + _phantom: PhantomData, + } + } +} + +impl<'d> crate::peripheral::Peripheral for AnyInputOnlyPin<'d> { + type P = Self; + + unsafe fn clone_unchecked(&mut self) -> Self::P { + Self { + pin: unsafe { self.pin.clone_unchecked() }, + inverted: self.inverted, + _phantom: PhantomData, + } + } +} + +impl<'d> private::Sealed for AnyInputOnlyPin<'d> {} + +impl<'d> Pin for AnyInputOnlyPin<'d> { + delegate::delegate! { + to self.pin { + fn number(&self, _internal: private::Internal) -> u8; + fn sleep_mode(&mut self, on: bool, _internal: private::Internal); + fn set_alternate_function(&mut self, alternate: AlternateFunction, _internal: private::Internal); + fn is_listening(&self, _internal: private::Internal) -> bool; + fn listen_with_options( + &mut self, + event: Event, + int_enable: bool, + nmi_enable: bool, + wake_up_from_light_sleep: bool, + _internal: private::Internal, + ); + fn unlisten(&mut self, _internal: private::Internal); + fn is_interrupt_set(&self, _internal: private::Internal) -> bool; + fn clear_interrupt(&mut self, _internal: private::Internal); + } + } +} + +impl<'d> InputPin for AnyInputOnlyPin<'d> { + delegate::delegate! { + to self.pin { + fn init_input(&self, pull_down: bool, pull_up: bool, _internal: private::Internal); + fn set_to_input(&mut self, _internal: private::Internal); + fn enable_input(&mut self, on: bool, _internal: private::Internal); + fn enable_input_in_sleep_mode(&mut self, on: bool, _internal: private::Internal); + fn is_input_high(&self, _internal: private::Internal) -> bool; + fn connect_input_to_peripheral(&mut self, signal: InputSignal, _internal: private::Internal); + fn connect_input_to_peripheral_with_options( + &mut self, + signal: InputSignal, + invert: bool, + force_via_gpio_mux: bool, + _internal: private::Internal, + ); + fn disconnect_input_from_peripheral(&mut self, signal: InputSignal, _internal: private::Internal); + } + } +} diff --git a/esp-hal/src/gpio/etm.rs b/esp-hal/src/gpio/etm.rs index c0668660f..36f7dff4a 100644 --- a/esp-hal/src/gpio/etm.rs +++ b/esp-hal/src/gpio/etm.rs @@ -23,11 +23,24 @@ //! //! ## Example //! ```no_run -//! let led_task = gpio_ext.channel0_task.toggle(&mut led); -//! let button_event = gpio_ext.channel0_event.falling_edge(button); +//! let led_task = gpio_ext.channel0_task.toggle( +//! &mut led, +//! GpioEtmOutputConfig { +//! open_drain: false, +//! pull: Pull::None, +//! initial_state: false, +//! }, +//! ); +//! let button_event = gpio_ext +//! .channel0_event +//! .falling_edge(button, GpioEtmInputConfig { pull: Pull::Down }); //! ``` -use crate::peripheral::{Peripheral, PeripheralRef}; +use crate::{ + gpio::Pull, + peripheral::{Peripheral, PeripheralRef}, + private, +}; /// All the GPIO ETM channels #[non_exhaustive] @@ -79,6 +92,20 @@ impl<'d> GpioEtmChannels<'d> { } } +/// Configuration for an ETM controlled GPIO input pin +#[derive(Clone, Copy, Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub struct GpioEtmInputConfig { + /// Configuration for the internal pull-up resistors + pub pull: Pull, +} + +impl Default for GpioEtmInputConfig { + fn default() -> Self { + Self { pull: Pull::None } + } +} + /// An ETM controlled GPIO event pub struct GpioEtmEventChannel {} @@ -87,12 +114,20 @@ impl GpioEtmEventChannel { pub fn rising_edge<'d, PIN>( self, pin: impl Peripheral

+ 'd, + pin_config: GpioEtmInputConfig, ) -> GpioEtmEventChannelRising<'d, PIN, C> where - PIN: super::Pin, + PIN: super::InputPin, { crate::into_ref!(pin); - enable_event_channel(C, pin.number()); + + pin.init_input( + pin_config.pull == Pull::Down, + pin_config.pull == Pull::Up, + private::Internal, + ); + + enable_event_channel(C, pin.number(private::Internal)); GpioEtmEventChannelRising { _pin: pin } } @@ -100,12 +135,20 @@ impl GpioEtmEventChannel { pub fn falling_edge<'d, PIN>( self, pin: impl Peripheral

+ 'd, + pin_config: GpioEtmInputConfig, ) -> GpioEtmEventChannelFalling<'d, PIN, C> where - PIN: super::Pin, + PIN: super::InputPin, { crate::into_ref!(pin); - enable_event_channel(C, pin.number()); + + pin.init_input( + pin_config.pull == Pull::Down, + pin_config.pull == Pull::Up, + private::Internal, + ); + + enable_event_channel(C, pin.number(private::Internal)); GpioEtmEventChannelFalling { _pin: pin } } @@ -113,12 +156,20 @@ impl GpioEtmEventChannel { pub fn any_edge<'d, PIN>( self, pin: impl Peripheral

+ 'd, + pin_config: GpioEtmInputConfig, ) -> GpioEtmEventChannelAny<'d, PIN, C> where - PIN: super::Pin, + PIN: super::InputPin, { crate::into_ref!(pin); - enable_event_channel(C, pin.number()); + + pin.init_input( + pin_config.pull == Pull::Down, + pin_config.pull == Pull::Up, + private::Internal, + ); + + enable_event_channel(C, pin.number(private::Internal)); GpioEtmEventChannelAny { _pin: pin } } } @@ -132,7 +183,7 @@ where _pin: PeripheralRef<'d, PIN>, } -impl<'d, PIN, const C: u8> crate::private::Sealed for GpioEtmEventChannelRising<'d, PIN, C> where +impl<'d, PIN, const C: u8> private::Sealed for GpioEtmEventChannelRising<'d, PIN, C> where PIN: super::Pin { } @@ -155,7 +206,7 @@ where _pin: PeripheralRef<'d, PIN>, } -impl<'d, PIN, const C: u8> crate::private::Sealed for GpioEtmEventChannelFalling<'d, PIN, C> where +impl<'d, PIN, const C: u8> private::Sealed for GpioEtmEventChannelFalling<'d, PIN, C> where PIN: super::Pin { } @@ -178,7 +229,7 @@ where _pin: PeripheralRef<'d, PIN>, } -impl<'d, PIN, const C: u8> crate::private::Sealed for GpioEtmEventChannelAny<'d, PIN, C> where +impl<'d, PIN, const C: u8> private::Sealed for GpioEtmEventChannelAny<'d, PIN, C> where PIN: super::Pin { } @@ -192,6 +243,28 @@ where } } +/// Configuration for an ETM controlled GPIO output pin +#[derive(Clone, Copy, Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub struct GpioEtmOutputConfig { + /// Set to open-drain output + pub open_drain: bool, + /// Only used when open-drain + pub pull: Pull, + /// Initial pin state + pub initial_state: bool, +} + +impl Default for GpioEtmOutputConfig { + fn default() -> Self { + Self { + open_drain: false, + pull: Pull::None, + initial_state: false, + } + } +} + /// An ETM controlled GPIO task pub struct GpioEtmTaskChannel {} @@ -202,22 +275,50 @@ impl GpioEtmTaskChannel { // number is the pin-count /// Task to set a high level - pub fn set<'d, PIN>(self, pin: impl Peripheral

+ 'd) -> GpioEtmTaskSet<'d, PIN, C> + pub fn set<'d, PIN>( + self, + pin: impl Peripheral

+ 'd, + pin_config: GpioEtmOutputConfig, + ) -> GpioEtmTaskSet<'d, PIN, C> where - PIN: super::Pin, + PIN: super::OutputPin, { crate::into_ref!(pin); - enable_task_channel(C, pin.number()); + + pin.set_output_high(pin_config.initial_state, private::Internal); + if pin_config.open_drain { + pin.internal_pull_down(pin_config.pull == Pull::Down, private::Internal); + pin.internal_pull_up(pin_config.pull == Pull::Up, private::Internal); + pin.set_to_open_drain_output(private::Internal); + } else { + pin.set_to_push_pull_output(private::Internal); + } + + enable_task_channel(C, pin.number(private::Internal)); GpioEtmTaskSet { _pin: pin } } /// Task to set a low level - pub fn clear<'d, PIN>(self, pin: impl Peripheral

+ 'd) -> GpioEtmTaskClear<'d, PIN, C> + pub fn clear<'d, PIN>( + self, + pin: impl Peripheral

+ 'd, + pin_config: GpioEtmOutputConfig, + ) -> GpioEtmTaskClear<'d, PIN, C> where - PIN: super::Pin, + PIN: super::OutputPin, { crate::into_ref!(pin); - enable_task_channel(C, pin.number()); + + pin.set_output_high(pin_config.initial_state, private::Internal); + if pin_config.open_drain { + pin.internal_pull_down(pin_config.pull == Pull::Down, private::Internal); + pin.internal_pull_up(pin_config.pull == Pull::Up, private::Internal); + pin.set_to_open_drain_output(private::Internal); + } else { + pin.set_to_push_pull_output(private::Internal); + } + + enable_task_channel(C, pin.number(private::Internal)); GpioEtmTaskClear { _pin: pin } } @@ -225,12 +326,23 @@ impl GpioEtmTaskChannel { pub fn toggle<'d, PIN>( self, pin: impl Peripheral

+ 'd, + pin_config: GpioEtmOutputConfig, ) -> GpioEtmTaskToggle<'d, PIN, C> where - PIN: super::Pin, + PIN: super::OutputPin, { crate::into_ref!(pin); - enable_task_channel(C, pin.number()); + + pin.set_output_high(pin_config.initial_state, private::Internal); + if pin_config.open_drain { + pin.internal_pull_down(pin_config.pull == Pull::Down, private::Internal); + pin.internal_pull_up(pin_config.pull == Pull::Up, private::Internal); + pin.set_to_open_drain_output(private::Internal); + } else { + pin.set_to_push_pull_output(private::Internal); + } + + enable_task_channel(C, pin.number(private::Internal)); GpioEtmTaskToggle { _pin: pin } } } @@ -244,10 +356,7 @@ where _pin: PeripheralRef<'d, PIN>, } -impl<'d, PIN, const C: u8> crate::private::Sealed for GpioEtmTaskSet<'d, PIN, C> where - PIN: super::Pin -{ -} +impl<'d, PIN, const C: u8> private::Sealed for GpioEtmTaskSet<'d, PIN, C> where PIN: super::Pin {} impl<'d, PIN, const C: u8> crate::etm::EtmTask for GpioEtmTaskSet<'d, PIN, C> where @@ -264,10 +373,7 @@ pub struct GpioEtmTaskClear<'d, PIN, const C: u8> { _pin: PeripheralRef<'d, PIN>, } -impl<'d, PIN, const C: u8> crate::private::Sealed for GpioEtmTaskClear<'d, PIN, C> where - PIN: super::Pin -{ -} +impl<'d, PIN, const C: u8> private::Sealed for GpioEtmTaskClear<'d, PIN, C> where PIN: super::Pin {} impl<'d, PIN, const C: u8> crate::etm::EtmTask for GpioEtmTaskClear<'d, PIN, C> where @@ -284,10 +390,7 @@ pub struct GpioEtmTaskToggle<'d, PIN, const C: u8> { _pin: PeripheralRef<'d, PIN>, } -impl<'d, PIN, const C: u8> crate::private::Sealed for GpioEtmTaskToggle<'d, PIN, C> where - PIN: super::Pin -{ -} +impl<'d, PIN, const C: u8> private::Sealed for GpioEtmTaskToggle<'d, PIN, C> where PIN: super::Pin {} impl<'d, PIN, const C: u8> crate::etm::EtmTask for GpioEtmTaskToggle<'d, PIN, C> where diff --git a/esp-hal/src/gpio/lp_io.rs b/esp-hal/src/gpio/lp_io.rs index 56463d0be..3ea02108f 100644 --- a/esp-hal/src/gpio/lp_io.rs +++ b/esp-hal/src/gpio/lp_io.rs @@ -17,23 +17,111 @@ //! ```no_run //! let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); //! // configure GPIO 1 as LP output pin -//! let lp_pin = io.pins.gpio1.into_low_power().into_push_pull_output(); +//! let lp_pin = LowPowerOutput::new(io.pins.gpio1); //! ``` use core::marker::PhantomData; -#[cfg(esp32c6)] -use super::OpenDrain; -use super::{Floating, Input, Output, PullDown, PullUp, PushPull, Unknown}; - -/// A GPIO pin configured for low power operation -pub struct LowPowerPin { - pub(crate) private: PhantomData, +/// A GPIO output pin configured for low power operation +pub struct LowPowerOutput<'d, const PIN: u8> { + phantom: PhantomData<&'d ()>, } -impl LowPowerPin { - #[doc(hidden)] - pub fn output_enable(&self, enable: bool) { +impl<'d, const PIN: u8> LowPowerOutput<'d, PIN> { + /// Create a new output pin for use by the low-power core + pub fn new

(_pin: impl crate::peripheral::Peripheral

+ 'd) -> Self + where + P: super::OutputPin + RtcPin, + { + crate::gpio::lp_io::init_low_power_pin(PIN); + + let this = Self { + phantom: PhantomData, + }; + this.output_enable(true); + + this + } + + fn output_enable(&self, enable: bool) { + let lp_io = unsafe { &*crate::peripherals::LP_IO::PTR }; + if enable { + lp_io + .out_enable_w1ts() + .write(|w| unsafe { w.enable_w1ts().bits(1 << PIN) }); + } else { + lp_io + .out_enable_w1tc() + .write(|w| unsafe { w.enable_w1tc().bits(1 << PIN) }); + } + } +} + +/// A GPIO input pin configured for low power operation +pub struct LowPowerInput<'d, const PIN: u8> { + phantom: PhantomData<&'d ()>, +} + +impl<'d, const PIN: u8> LowPowerInput<'d, PIN> { + /// Create a new input pin for use by the low-power core + pub fn new

(_pin: impl crate::peripheral::Peripheral

+ 'd) -> Self + where + P: super::InputPin + RtcPin, + { + crate::gpio::lp_io::init_low_power_pin(PIN); + + let this = Self { + phantom: PhantomData, + }; + this.input_enable(true); + this.pullup_enable(false); + this.pulldown_enable(false); + + this + } + + fn input_enable(&self, enable: bool) { + get_pin_reg(PIN).modify(|_, w| w.fun_ie().bit(enable)); + } + + /// Sets pull-up enable for the pin + pub fn pullup_enable(&self, enable: bool) { + get_pin_reg(PIN).modify(|_, w| w.fun_wpu().bit(enable)); + } + + /// Sets pull-down enable for the pin + pub fn pulldown_enable(&self, enable: bool) { + get_pin_reg(PIN).modify(|_, w| w.fun_wpd().bit(enable)); + } +} + +/// A GPIO open-drain output pin configured for low power operation +pub struct LowPowerOutputOpenDrain<'d, const PIN: u8> { + phantom: PhantomData<&'d ()>, +} + +impl<'d, const PIN: u8> LowPowerOutputOpenDrain<'d, PIN> { + /// Create a new output pin for use by the low-power core + pub fn new

(_pin: impl crate::peripheral::Peripheral

+ 'd) -> Self + where + P: super::InputPin + super::OutputPin + RtcPin, + { + crate::gpio::lp_io::init_low_power_pin(PIN); + + let this = Self { + phantom: PhantomData, + }; + + this.set_open_drain_output(true); + this.input_enable(true); + this.pullup_enable(true); + this.pulldown_enable(false); + this.output_enable(true); + + this + } + + fn output_enable(&self, enable: bool) { let lp_io = unsafe { &*crate::peripherals::LP_IO::PTR }; if enable { lp_io @@ -50,88 +138,22 @@ impl LowPowerPin { get_pin_reg(PIN).modify(|_, w| w.fun_ie().bit(enable)); } - fn pullup_enable(&self, enable: bool) { + /// Sets pull-up enable for the pin + pub fn pullup_enable(&self, enable: bool) { get_pin_reg(PIN).modify(|_, w| w.fun_wpu().bit(enable)); } - fn pulldown_enable(&self, enable: bool) { + /// Sets pull-down enable for the pin + pub fn pulldown_enable(&self, enable: bool) { get_pin_reg(PIN).modify(|_, w| w.fun_wpd().bit(enable)); } - #[doc(hidden)] - pub fn set_level(&mut self, level: bool) { - let lp_io = unsafe { &*crate::peripherals::LP_IO::PTR }; - if level { - lp_io - .out_data_w1ts() - .write(|w| unsafe { w.out_data_w1ts().bits(1 << PIN) }); - } else { - lp_io - .out_data_w1tc() - .write(|w| unsafe { w.out_data_w1tc().bits(1 << PIN) }); - } - } - - #[doc(hidden)] - pub fn get_level(&self) -> bool { - let lp_io = unsafe { &*crate::peripherals::LP_IO::PTR }; - (lp_io.in_().read().data_next().bits() & 1 << PIN) != 0 - } - - /// Configures the pin as an input with the internal pull-up resistor - /// enabled. - pub fn into_pull_up_input(self) -> LowPowerPin, PIN> { - self.input_enable(true); - self.pullup_enable(true); - self.pulldown_enable(false); - LowPowerPin { - private: PhantomData, - } - } - - /// Configures the pin as an input with the internal pull-down resistor - /// enabled. - pub fn into_pull_down_input(self) -> LowPowerPin, PIN> { - self.input_enable(true); - self.pullup_enable(false); - self.pulldown_enable(true); - LowPowerPin { - private: PhantomData, - } - } - - /// Configures the pin as a floating input pin. - pub fn into_floating_input(self) -> LowPowerPin, PIN> { - self.input_enable(true); - self.pullup_enable(false); - self.pulldown_enable(false); - LowPowerPin { - private: PhantomData, - } - } - - /// Configures the pin as a push-pull output pin. - pub fn into_push_pull_output(self) -> LowPowerPin, PIN> { - self.output_enable(true); - LowPowerPin { - private: PhantomData, - } - } - - /// Configures the pin as an open-drain output pin. - pub fn into_open_drain_output(self) -> LowPowerPin { + fn set_open_drain_output(&self, enable: bool) { use crate::peripherals::GPIO; - let gpio = unsafe { &*GPIO::PTR }; gpio.pin(PIN as usize) - .modify(|_, w| w.pad_driver().bit(true)); - self.pulldown_enable(false); - self.into_pull_up_input().into_push_pull_output(); - - LowPowerPin { - private: PhantomData, - } + .modify(|_, w| w.pad_driver().bit(enable)); } } @@ -157,12 +179,6 @@ fn get_pin_reg(pin: u8) -> &'static crate::peripherals::lp_io::GPIO0 { } } -/// Configures a pin for use as a low power pin -pub trait IntoLowPowerPin { - /// Converts the pin into a low power pin - fn into_low_power(self) -> LowPowerPin; -} - #[doc(hidden)] #[macro_export] macro_rules! lp_gpio { @@ -171,16 +187,7 @@ macro_rules! lp_gpio { ) => { paste::paste!{ $( - impl $crate::gpio::lp_io::IntoLowPowerPin<$gpionum> for GpioPin { - fn into_low_power(self) -> $crate::gpio::lp_io::LowPowerPin { - $crate::gpio::lp_io::init_low_power_pin($gpionum); - $crate::gpio::lp_io::LowPowerPin { - private: core::marker::PhantomData, - } - } - } - - impl $crate::gpio::RtcPin for GpioPin { + impl $crate::gpio::RtcPin for GpioPin<$gpionum> { unsafe fn apply_wakeup(&mut self, wakeup: bool, level: u8) { let lp_io = &*$crate::peripherals::LP_IO::ptr(); lp_io.[< pin $gpionum >]().modify(|_, w| { @@ -232,7 +239,7 @@ macro_rules! lp_gpio { } } - impl $crate::gpio::RtcPinWithResistors for GpioPin { + impl $crate::gpio::RtcPinWithResistors for GpioPin<$gpionum> { fn rtcio_pullup(&mut self, enable: bool) { let lp_io = unsafe { &*$crate::peripherals::LP_IO::ptr() }; lp_io.[< gpio $gpionum >]().modify(|_, w| w.fun_wpu().bit(enable)); @@ -249,3 +256,5 @@ macro_rules! lp_gpio { } pub(crate) use lp_gpio; + +use super::RtcPin; diff --git a/esp-hal/src/gpio/mod.rs b/esp-hal/src/gpio/mod.rs index 1f4f22847..0a873f031 100644 --- a/esp-hal/src/gpio/mod.rs +++ b/esp-hal/src/gpio/mod.rs @@ -17,7 +17,7 @@ //! ## Example //! ```no_run //! let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); -//! let mut led = io.pins.gpio5.into_push_pull_output(); +//! let mut led = Output::new(io.pins.gpio5); //! ``` //! //! [embedded-hal]: https://docs.rs/embedded-hal/latest/embedded_hal/ @@ -35,9 +35,13 @@ pub(crate) use crate::rtc_pins; pub use crate::soc::gpio::*; use crate::{ interrupt::InterruptHandler, + peripheral::PeripheralRef, peripherals::{GPIO, IO_MUX}, + private, }; +pub mod any_pin; + #[cfg(soc_etm)] pub mod etm; #[cfg(lp_io)] @@ -46,7 +50,7 @@ pub mod lp_io; pub mod rtc_io; /// Convenience type-alias for a no-pin / don't care - pin -pub type NoPinType = Gpio0; +pub type NoPinType = Gpio0; /// Convenience constant for `Option::None` pin pub const NO_PIN: Option = None; @@ -55,6 +59,7 @@ static USER_INTERRUPT_HANDLER: Mutex>> = Mutex::ne /// Event used to trigger interrupts. #[derive(Copy, Clone)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum Event { /// Interrupts trigger on rising pin edge. RisingEdge = 1, @@ -68,89 +73,51 @@ pub enum Event { HighLevel = 5, } -/// Unknown pin mode -pub struct Unknown {} - -/// Input pin mode -pub struct Input { - _mode: PhantomData, +/// Digital input or output level. +#[derive(Debug, Eq, PartialEq, Copy, Clone)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub enum Level { + /// Low + Low, + /// High + High, } -/// Inverted input pin mode -pub struct InvertedInput { - _mode: PhantomData, +impl From for Level { + fn from(val: bool) -> Self { + match val { + true => Self::High, + false => Self::Low, + } + } } -/// Used to decide if the pin is inverted or not when the pin gets connected to -/// a peripheral -trait InputMode { - const PIN_IS_INVERTED: bool; +impl From for bool { + fn from(level: Level) -> bool { + match level { + Level::Low => false, + Level::High => true, + } + } } -impl InputMode for Input { - const PIN_IS_INVERTED: bool = false; -} - -impl InputMode for InvertedInput { - const PIN_IS_INVERTED: bool = true; -} - -impl InputMode for Unknown { - const PIN_IS_INVERTED: bool = false; +/// Pull setting for an input. +#[derive(Debug, Eq, PartialEq, Copy, Clone)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub enum Pull { + /// No pull + None, + /// Pull up + Up, + /// Pull down + Down, } /// RTC input pin mode -pub struct RtcInput { - _mode: PhantomData, -} - -/// Floating mode -pub struct Floating; - -/// Pull-down mode -pub struct PullDown; - -/// Pull-up mode -pub struct PullUp; - -/// Output pin mode -pub struct Output { - _mode: PhantomData, -} - -/// Inverted output pin mode -pub struct InvertedOutput { - _mode: PhantomData, -} - -/// Used to decide if the pin is inverted or not when the pin gets connected to -/// a peripheral -trait OutputMode { - const PIN_IS_INVERTED: bool; -} - -impl OutputMode for Output { - const PIN_IS_INVERTED: bool = false; -} - -impl OutputMode for InvertedOutput { - const PIN_IS_INVERTED: bool = true; -} - -impl OutputMode for Unknown { - const PIN_IS_INVERTED: bool = false; -} +pub struct RtcInput; /// RTC output pin mode -pub struct RtcOutput { - _mode: PhantomData, -} - -/// Open-drain mode -pub struct OpenDrain; - -/// Push-pull mode -pub struct PushPull; +pub struct RtcOutput; /// Analog mode pub struct Analog; @@ -219,27 +186,24 @@ pub trait RtcInputPin: RtcPin {} /// Marker for RTC pins which support output mode pub trait RtcOutputPin: RtcPin {} -/// Marker for pins which support analog mode -pub trait AnalogPin {} - /// Common trait implemented by pins -pub trait Pin: crate::private::Sealed { +pub trait Pin: private::Sealed { /// GPIO number - fn number(&self) -> u8; + fn number(&self, _: private::Internal) -> u8; /// Enable/disable sleep-mode - fn sleep_mode(&mut self, on: bool); + fn sleep_mode(&mut self, on: bool, _: private::Internal); /// Configure the alternate function - fn set_alternate_function(&mut self, alternate: AlternateFunction); + fn set_alternate_function(&mut self, alternate: AlternateFunction, _: private::Internal); /// Listen for interrupts - fn listen(&mut self, event: Event) { - self.listen_with_options(event, true, false, false) + fn listen(&mut self, event: Event, _: private::Internal) { + self.listen_with_options(event, true, false, false, private::Internal) } /// Checks if listening for interrupts is enabled for this Pin - fn is_listening(&self) -> bool; + fn is_listening(&self, _: private::Internal) -> bool; /// Listen for interrupts fn listen_with_options( @@ -248,34 +212,38 @@ pub trait Pin: crate::private::Sealed { int_enable: bool, nmi_enable: bool, wake_up_from_light_sleep: bool, + _: private::Internal, ); /// Stop listening for interrupts - fn unlisten(&mut self); + fn unlisten(&mut self, _: private::Internal); /// Checks if the interrupt status bit for this Pin is set - fn is_interrupt_set(&self) -> bool; + fn is_interrupt_set(&self, _: private::Internal) -> bool; /// Clear the interrupt status bit for this Pin - fn clear_interrupt(&mut self); + fn clear_interrupt(&mut self, _: private::Internal); } /// Trait implemented by pins which can be used as inputs pub trait InputPin: Pin { + /// Init as input with the given pull-up/pull-down + fn init_input(&self, pull_down: bool, pull_up: bool, _: private::Internal); + /// Set the pin to input mode without internal pull-up / pull-down resistors - fn set_to_input(&mut self) -> &mut Self; + fn set_to_input(&mut self, _: private::Internal); /// Enable input for the pin - fn enable_input(&mut self, on: bool) -> &mut Self; + fn enable_input(&mut self, on: bool, _: private::Internal); /// Enable input in sleep mode for the pin - fn enable_input_in_sleep_mode(&mut self, on: bool) -> &mut Self; + fn enable_input_in_sleep_mode(&mut self, on: bool, _: private::Internal); /// The current state of the input - fn is_input_high(&self) -> bool; + fn is_input_high(&self, _: private::Internal) -> bool; /// Connect the pin to a peripheral input signal - fn connect_input_to_peripheral(&mut self, signal: InputSignal) -> &mut Self; + fn connect_input_to_peripheral(&mut self, signal: InputSignal, _: private::Internal); /// Connect the pin to a peripheral input signal. /// @@ -286,53 +254,54 @@ pub trait InputPin: Pin { signal: InputSignal, invert: bool, force_via_gpio_mux: bool, - ) -> &mut Self; + _: private::Internal, + ); /// Remove a connected `signal` from this input pin. /// /// Clears the entry in the GPIO matrix / Io mux that associates this input /// pin with the given [input `signal`](`InputSignal`). Any other /// connected signals remain intact. - fn disconnect_input_from_peripheral(&mut self, signal: InputSignal) -> &mut Self; + fn disconnect_input_from_peripheral(&mut self, signal: InputSignal, _: private::Internal); } /// Trait implemented by pins which can be used as outputs pub trait OutputPin: Pin { /// Configure open-drain mode - fn set_to_open_drain_output(&mut self) -> &mut Self; + fn set_to_open_drain_output(&mut self, _: private::Internal); /// Configure output mode - fn set_to_push_pull_output(&mut self) -> &mut Self; + fn set_to_push_pull_output(&mut self, _: private::Internal); /// Enable/disable the pin as output - fn enable_output(&mut self, on: bool) -> &mut Self; + fn enable_output(&mut self, on: bool, _: private::Internal); /// Set the pin's level to high or low - fn set_output_high(&mut self, on: bool) -> &mut Self; + fn set_output_high(&mut self, on: bool, _: private::Internal); /// Configure the [DriveStrength] of the pin - fn set_drive_strength(&mut self, strength: DriveStrength) -> &mut Self; + fn set_drive_strength(&mut self, strength: DriveStrength, _: private::Internal); /// Enable/disable open-drain mode - fn enable_open_drain(&mut self, on: bool) -> &mut Self; + fn enable_open_drain(&mut self, on: bool, _: private::Internal); /// Enable/disable output in sleep mode - fn enable_output_in_sleep_mode(&mut self, on: bool) -> &mut Self; + fn enable_output_in_sleep_mode(&mut self, on: bool, _: private::Internal); /// Configure internal pull-up resistor in sleep mode - fn internal_pull_up_in_sleep_mode(&mut self, on: bool) -> &mut Self; + fn internal_pull_up_in_sleep_mode(&mut self, on: bool, _: private::Internal); /// Configure internal pull-down resistor in sleep mode - fn internal_pull_down_in_sleep_mode(&mut self, on: bool) -> &mut Self; + fn internal_pull_down_in_sleep_mode(&mut self, on: bool, _: private::Internal); /// Enable/disable internal pull-up resistor for normal operation - fn internal_pull_up(&mut self, on: bool) -> &mut Self; + fn internal_pull_up(&mut self, on: bool, _: private::Internal); /// Enable/disable internal pull-down resistor for normal operation - fn internal_pull_down(&mut self, on: bool) -> &mut Self; + fn internal_pull_down(&mut self, on: bool, _: private::Internal); /// Connect the pin to a peripheral output signal - fn connect_peripheral_to_output(&mut self, signal: OutputSignal) -> &mut Self; + fn connect_peripheral_to_output(&mut self, signal: OutputSignal, _: private::Internal); /// Connect the pin to a peripheral output signal. /// @@ -356,14 +325,29 @@ pub trait OutputPin: Pin { invert_enable: bool, enable_from_gpio: bool, force_via_gpio_mux: bool, - ) -> &mut Self; + _: private::Internal, + ); /// Remove this output pin from a connected [signal](`InputSignal`). /// /// Clears the entry in the GPIO matrix / Io mux that associates this output /// pin with a previously connected [signal](`InputSignal`). Any other /// outputs connected to the signal remain intact. - fn disconnect_peripheral_from_output(&mut self) -> &mut Self; + fn disconnect_peripheral_from_output(&mut self, _: private::Internal); + + /// Is the output set to high + fn is_set_high(&self, _: private::Internal) -> bool; +} + +/// Trait implemented by pins which can be used as analog pins +pub trait AnalogPin: Pin { + /// Configure the pin for analog operation + fn set_analog(&self, _: private::Internal); +} + +#[doc(hidden)] +pub trait CreateErasedPin: Pin { + fn erased_pin(&self, _: private::Internal) -> ErasedPin; } #[doc(hidden)] @@ -614,13 +598,12 @@ impl IsInputPin for InputOnlyAnalogPinType {} impl IsAnalogPin for InputOnlyAnalogPinType {} /// GPIO pin -pub struct GpioPin { - _mode: PhantomData, -} +pub struct GpioPin; -impl GpioPin, GPIONUM> +impl GpioPin where Self: GpioProperties, + ::PinType: IsOutputPin, { /// Is the input pin high? #[inline] @@ -635,32 +618,22 @@ where } } -impl GpioPin, GPIONUM> -where - Self: GpioProperties, -{ - /// Is the input pin high? - #[inline] - pub fn is_high(&self) -> bool { - ::Bank::read_input() & (1 << (GPIONUM % 32)) != 0 - } - - /// Is the input pin low? - #[inline] - pub fn is_low(&self) -> bool { - !self.is_high() - } -} - -impl GpioPin +impl GpioPin where Self: GpioProperties, + ::PinType: IsInputPin, { pub(crate) fn new() -> Self { - Self { _mode: PhantomData } + Self } +} - fn init_input(&self, pull_down: bool, pull_up: bool) { +impl InputPin for GpioPin +where + Self: GpioProperties, + ::PinType: IsInputPin, +{ + fn init_input(&self, pull_down: bool, pull_up: bool, _: private::Internal) { let gpio = unsafe { &*GPIO::PTR }; ::Bank::write_out_en_clear(1 << (GPIONUM % 32)); @@ -723,73 +696,24 @@ where }); } - /// Configures the pin to operate as a floating input pin - pub fn into_floating_input(self) -> GpioPin, GPIONUM> { - self.init_input(false, false); - GpioPin { _mode: PhantomData } + fn set_to_input(&mut self, _: private::Internal) { + self.init_input(false, false, private::Internal); } - /// Configures the pin to operate as a pulled up input pin - pub fn into_pull_up_input(self) -> GpioPin, GPIONUM> { - self.init_input(false, true); - GpioPin { _mode: PhantomData } - } - - /// Configures the pin to operate as a pulled down input pin - pub fn into_pull_down_input(self) -> GpioPin, GPIONUM> { - self.init_input(true, false); - GpioPin { _mode: PhantomData } - } - - /// Configures the pin to operate as an inverted floating input pin. - /// Only suitable to be passed into a peripheral driver. - pub fn into_inverted_floating_input(self) -> GpioPin, GPIONUM> { - self.init_input(false, false); - GpioPin { _mode: PhantomData } - } - - /// Configures the pin to operate as an inverted pulled up input pin. - /// Only suitable to be passed into a peripheral driver. - pub fn into_inverted_pull_up_input(self) -> GpioPin, GPIONUM> { - self.init_input(false, true); - GpioPin { _mode: PhantomData } - } - - /// Configures the pin to operate as an inverted pulled down input pin. - /// Only suitable to be passed into a peripheral driver. - pub fn into_inverted_pull_down_input(self) -> GpioPin, GPIONUM> { - self.init_input(true, false); - GpioPin { _mode: PhantomData } - } -} - -impl InputPin for GpioPin -where - Self: GpioProperties, - MODE: InputMode, -{ - fn set_to_input(&mut self) -> &mut Self { - self.init_input(false, false); - self - } - fn enable_input(&mut self, on: bool) -> &mut Self { + fn enable_input(&mut self, on: bool, _: private::Internal) { get_io_mux_reg(GPIONUM).modify(|_, w| w.fun_ie().bit(on)); - self } - fn enable_input_in_sleep_mode(&mut self, on: bool) -> &mut Self { + + fn enable_input_in_sleep_mode(&mut self, on: bool, _: private::Internal) { get_io_mux_reg(GPIONUM).modify(|_, w| w.mcu_ie().bit(on)); - self } - fn is_input_high(&self) -> bool { + + fn is_input_high(&self, _: private::Internal) -> bool { ::Bank::read_input() & (1 << (GPIONUM % 32)) != 0 } - fn connect_input_to_peripheral(&mut self, signal: InputSignal) -> &mut Self { - self.connect_input_to_peripheral_with_options( - signal, - MODE::PIN_IS_INVERTED, - MODE::PIN_IS_INVERTED, - ) + fn connect_input_to_peripheral(&mut self, signal: InputSignal, _: private::Internal) { + self.connect_input_to_peripheral_with_options(signal, false, false, private::Internal); } fn connect_input_to_peripheral_with_options( @@ -797,7 +721,8 @@ where signal: InputSignal, invert: bool, force_via_gpio_mux: bool, - ) -> &mut Self { + _: private::Internal, + ) { let af = if force_via_gpio_mux { GPIO_FUNCTION } else { @@ -826,7 +751,7 @@ where if af == GPIO_FUNCTION && signal as usize > INPUT_SIGNAL_MAX as usize { panic!("Cannot connect GPIO to this peripheral"); } - self.set_alternate_function(af); + self.set_alternate_function(af, private::Internal); if (signal as usize) <= INPUT_SIGNAL_MAX as usize { unsafe { &*GPIO::PTR } .func_in_sel_cfg(signal as usize - FUNC_IN_SEL_OFFSET) @@ -839,20 +764,18 @@ where .bits(GPIONUM) }); } - self } - fn disconnect_input_from_peripheral(&mut self, signal: InputSignal) -> &mut Self { - self.set_alternate_function(GPIO_FUNCTION); + fn disconnect_input_from_peripheral(&mut self, signal: InputSignal, _: private::Internal) { + self.set_alternate_function(GPIO_FUNCTION, private::Internal); unsafe { &*GPIO::PTR } .func_in_sel_cfg(signal as usize - FUNC_IN_SEL_OFFSET) .modify(|_, w| w.sel().clear_bit()); - self } } -impl GpioPin +impl GpioPin where Self: GpioProperties, { @@ -862,23 +785,23 @@ where /// /// Ensure that only one instance of a pin exists at one time. pub unsafe fn steal() -> Self { - Self { _mode: PhantomData } + Self } } -impl Pin for GpioPin +impl Pin for GpioPin where Self: GpioProperties, { - fn number(&self) -> u8 { + fn number(&self, _: private::Internal) -> u8 { GPIONUM } - fn sleep_mode(&mut self, on: bool) { + fn sleep_mode(&mut self, on: bool, _: private::Internal) { get_io_mux_reg(GPIONUM).modify(|_, w| w.slp_sel().bit(on)); } - fn set_alternate_function(&mut self, alternate: AlternateFunction) { + fn set_alternate_function(&mut self, alternate: AlternateFunction, _: private::Internal) { get_io_mux_reg(GPIONUM).modify(|_, w| unsafe { w.mcu_sel().bits(alternate as u8) }); } @@ -888,6 +811,7 @@ where int_enable: bool, nmi_enable: bool, wake_up_from_light_sleep: bool, + _: private::Internal, ) { if wake_up_from_light_sleep { match event { @@ -910,7 +834,7 @@ where } } - fn is_listening(&self) -> bool { + fn is_listening(&self, _: private::Internal) -> bool { let bits = unsafe { &*GPIO::PTR } .pin(GPIONUM as usize) .read() @@ -919,7 +843,7 @@ where bits != 0 } - fn unlisten(&mut self) { + fn unlisten(&mut self, _: private::Internal) { unsafe { (*GPIO::PTR) .pin(GPIONUM as usize) @@ -927,16 +851,16 @@ where } } - fn is_interrupt_set(&self) -> bool { + fn is_interrupt_set(&self, _: private::Internal) -> bool { ::Bank::read_interrupt_status() & 1 << (GPIONUM % 32) != 0 } - fn clear_interrupt(&mut self) { + fn clear_interrupt(&mut self, _: private::Internal) { ::Bank::write_interrupt_status_clear(1 << (GPIONUM % 32)); } } -impl GpioPin, GPIONUM> +impl GpioPin where Self: GpioProperties, ::PinType: IsOutputPin, @@ -985,159 +909,25 @@ where } } -impl crate::peripheral::Peripheral for GpioPin +impl crate::peripheral::Peripheral for GpioPin where Self: GpioProperties, { - type P = GpioPin; + type P = GpioPin; unsafe fn clone_unchecked(&mut self) -> Self::P { core::ptr::read(self as *const _) } } -impl crate::private::Sealed for GpioPin where - Self: GpioProperties -{ -} +impl private::Sealed for GpioPin where Self: GpioProperties {} -impl From> for GpioPin, GPIONUM> -where - Self: GpioProperties, - ::PinType: IsOutputPin, - GpioPin: GpioProperties, -{ - fn from(pin: GpioPin) -> Self { - pin.into_floating_input() - } -} - -impl From> - for GpioPin, GPIONUM> -where - Self: GpioProperties, - ::PinType: IsInputPin, - GpioPin: GpioProperties, -{ - fn from(pin: GpioPin) -> Self { - pin.into_inverted_floating_input() - } -} - -impl From> for GpioPin, GPIONUM> -where - Self: GpioProperties, - ::PinType: IsOutputPin, - GpioPin: GpioProperties, -{ - fn from(pin: GpioPin) -> Self { - pin.into_pull_up_input() - } -} - -impl From> for GpioPin, GPIONUM> -where - Self: GpioProperties, - ::PinType: IsOutputPin, - GpioPin: GpioProperties, -{ - fn from(pin: GpioPin) -> Self { - pin.into_inverted_pull_up_input() - } -} - -impl From> for GpioPin, GPIONUM> -where - Self: GpioProperties, - ::PinType: IsInputPin, - GpioPin: GpioProperties, -{ - fn from(pin: GpioPin) -> Self { - pin.into_pull_down_input() - } -} - -impl From> - for GpioPin, GPIONUM> -where - Self: GpioProperties, - ::PinType: IsInputPin, - GpioPin: GpioProperties, -{ - fn from(pin: GpioPin) -> Self { - pin.into_inverted_pull_down_input() - } -} - -impl From> for GpioPin, GPIONUM> -where - Self: GpioProperties, - ::PinType: IsOutputPin, - GpioPin: GpioProperties, - as GpioProperties>::PinType: IsOutputPin, -{ - fn from(pin: GpioPin) -> Self { - pin.into_push_pull_output() - } -} - -impl From> - for GpioPin, GPIONUM> -where - Self: GpioProperties, - ::PinType: IsOutputPin, - GpioPin: GpioProperties, - as GpioProperties>::PinType: IsOutputPin, -{ - fn from(pin: GpioPin) -> Self { - pin.into_inverted_push_pull_output() - } -} - -#[cfg(any(adc, dac))] -impl From> for GpioPin -where - Self: GpioProperties, - ::PinType: IsAnalogPin, - GpioPin: GpioProperties, - as GpioProperties>::PinType: IsAnalogPin, -{ - fn from(pin: GpioPin) -> Self { - pin.into_analog() - } -} - -impl From> for GpioPin, GPIONUM> -where - Self: GpioProperties, - ::PinType: IsOutputPin, - GpioPin: GpioProperties, - as GpioProperties>::PinType: IsOutputPin, -{ - fn from(pin: GpioPin) -> Self { - pin.into_open_drain_output() - } -} - -impl From> - for GpioPin, GPIONUM> -where - Self: GpioProperties, - ::PinType: IsOutputPin, - GpioPin: GpioProperties, - as GpioProperties>::PinType: IsOutputPin, -{ - fn from(pin: GpioPin) -> Self { - pin.into_inverted_open_drain_output() - } -} - -impl GpioPin +impl GpioPin where Self: GpioProperties, ::PinType: IsOutputPin, { - fn init_output(&self, alternate: AlternateFunction, open_drain: bool) { + fn init_output(&self, alternate: AlternateFunction, open_drain: bool, _: private::Internal) { let gpio = unsafe { &*GPIO::PTR }; #[cfg(esp32)] @@ -1182,116 +972,78 @@ where .clear_bit() }); } - - /// Configures the pin to operate as an push pull output pin - pub fn into_push_pull_output(self) -> GpioPin, GPIONUM> { - self.init_output(GPIO_FUNCTION, false); - GpioPin { _mode: PhantomData } - } - - /// Configures the pin to operate as an open drain output pin - pub fn into_open_drain_output(self) -> GpioPin, GPIONUM> { - self.init_output(GPIO_FUNCTION, true); - GpioPin { _mode: PhantomData } - } - - /// Configures the pin to operate as an inverted push pull output pin. - /// Only suitable to be passed into an peripheral driver - pub fn into_inverted_push_pull_output(self) -> GpioPin, GPIONUM> { - self.init_output(GPIO_FUNCTION, false); - GpioPin { _mode: PhantomData } - } - - /// Configures the pin to operate as an open drain output pin. - /// Only suitable to be passed into an peripheral driver - pub fn into_inverted_open_drain_output(self) -> GpioPin, GPIONUM> { - self.init_output(GPIO_FUNCTION, true); - GpioPin { _mode: PhantomData } - } } -impl OutputPin for GpioPin +impl OutputPin for GpioPin where Self: GpioProperties, ::PinType: IsOutputPin, - MODE: OutputMode, { - fn set_to_open_drain_output(&mut self) -> &mut Self { - self.init_output(GPIO_FUNCTION, true); - self + fn set_to_open_drain_output(&mut self, _: private::Internal) { + self.init_output(GPIO_FUNCTION, true, private::Internal); } - fn set_to_push_pull_output(&mut self) -> &mut Self { - self.init_output(GPIO_FUNCTION, false); - self + fn set_to_push_pull_output(&mut self, _: private::Internal) { + self.init_output(GPIO_FUNCTION, false, private::Internal); } - fn enable_output(&mut self, on: bool) -> &mut Self { + fn enable_output(&mut self, on: bool, _: private::Internal) { if on { ::Bank::write_out_en_set(1 << (GPIONUM % 32)); } else { ::Bank::write_out_en_clear(1 << (GPIONUM % 32)); } - self } - fn set_output_high(&mut self, high: bool) -> &mut Self { + fn set_output_high(&mut self, high: bool, _: private::Internal) { if high { ::Bank::write_output_set(1 << (GPIONUM % 32)); } else { ::Bank::write_output_clear(1 << (GPIONUM % 32)); } - self } - fn set_drive_strength(&mut self, strength: DriveStrength) -> &mut Self { + fn set_drive_strength(&mut self, strength: DriveStrength, _: private::Internal) { get_io_mux_reg(GPIONUM).modify(|_, w| unsafe { w.fun_drv().bits(strength as u8) }); - - self } - fn enable_open_drain(&mut self, on: bool) -> &mut Self { + fn enable_open_drain(&mut self, on: bool, _: private::Internal) { unsafe { &*GPIO::PTR } .pin(GPIONUM as usize) .modify(|_, w| w.pad_driver().bit(on)); - self } - fn internal_pull_up_in_sleep_mode(&mut self, on: bool) -> &mut Self { + fn internal_pull_up_in_sleep_mode(&mut self, on: bool, _: private::Internal) { get_io_mux_reg(GPIONUM).modify(|_, w| w.mcu_wpu().bit(on)); - self } - fn internal_pull_down_in_sleep_mode(&mut self, on: bool) -> &mut Self { + fn internal_pull_down_in_sleep_mode(&mut self, on: bool, _: private::Internal) { get_io_mux_reg(GPIONUM).modify(|_, w| w.mcu_wpd().bit(on)); - self } - fn enable_output_in_sleep_mode(&mut self, on: bool) -> &mut Self { + fn enable_output_in_sleep_mode(&mut self, on: bool, _: private::Internal) { get_io_mux_reg(GPIONUM).modify(|_, w| w.mcu_oe().bit(on)); - self } - fn internal_pull_up(&mut self, on: bool) -> &mut Self { + fn internal_pull_up(&mut self, on: bool, _: private::Internal) { #[cfg(esp32)] crate::soc::gpio::errata36(GPIONUM, Some(on), None); get_io_mux_reg(GPIONUM).modify(|_, w| w.fun_wpu().bit(on)); - self } - fn internal_pull_down(&mut self, on: bool) -> &mut Self { + fn internal_pull_down(&mut self, on: bool, _: private::Internal) { #[cfg(esp32)] crate::soc::gpio::errata36(GPIONUM, None, Some(on)); get_io_mux_reg(GPIONUM).modify(|_, w| w.fun_wpd().bit(on)); - self } - fn connect_peripheral_to_output(&mut self, signal: OutputSignal) -> &mut Self { + fn connect_peripheral_to_output(&mut self, signal: OutputSignal, _: private::Internal) { self.connect_peripheral_to_output_with_options( signal, - MODE::PIN_IS_INVERTED, false, false, - MODE::PIN_IS_INVERTED, + false, + false, + private::Internal, ) } @@ -1302,7 +1054,8 @@ where invert_enable: bool, enable_from_gpio: bool, force_via_gpio_mux: bool, - ) -> &mut Self { + _: private::Internal, + ) { let af = if force_via_gpio_mux { GPIO_FUNCTION } else { @@ -1331,7 +1084,7 @@ where if af == GPIO_FUNCTION && signal as usize > OUTPUT_SIGNAL_MAX as usize { panic!("Cannot connect this peripheral to GPIO"); } - self.set_alternate_function(af); + self.set_alternate_function(af, private::Internal); let clipped_signal = if signal as usize <= OUTPUT_SIGNAL_MAX as usize { signal as OutputSignalType } else { @@ -1349,481 +1102,29 @@ where .oen_inv_sel() .bit(invert_enable) }); - self } - fn disconnect_peripheral_from_output(&mut self) -> &mut Self { - self.set_alternate_function(GPIO_FUNCTION); + fn disconnect_peripheral_from_output(&mut self, _: private::Internal) { + self.set_alternate_function(GPIO_FUNCTION, private::Internal); unsafe { &*GPIO::PTR } .func_out_sel_cfg(GPIONUM as usize) .modify(|_, w| unsafe { w.out_sel().bits(OutputSignal::GPIO as OutputSignalType) }); - self + } + + fn is_set_high(&self, _: private::Internal) -> bool { + ::Bank::read_output() & (1 << (GPIONUM % 32)) != 0 } } #[cfg(any(adc, dac))] -impl GpioPin +impl AnalogPin for GpioPin where Self: GpioProperties, ::PinType: IsAnalogPin, { - /// Configures the pin into a an [Analog] pin. - pub fn into_analog(self) -> GpioPin { + /// Configures the pin for analog mode. + fn set_analog(&self, _: private::Internal) { crate::soc::gpio::internal_into_analog(GPIONUM); - - GpioPin { _mode: PhantomData } - } -} - -impl From> for AnyPin -where - TYPE: PinType, -{ - fn from(pin: AnyPin) -> Self { - Self { - inner: pin.inner, - _type: core::marker::PhantomData, - } - } -} - -impl crate::peripheral::Peripheral for AnyPin -where - TYPE: PinType, -{ - type P = Self; - - unsafe fn clone_unchecked(&mut self) -> Self::P { - let inner = &mut self.inner; - let this: AnyPin = handle_gpio_input!(inner, target, { - crate::peripheral::Peripheral::clone_unchecked(target).into() - }); - Self { - inner: this.inner, - _type: core::marker::PhantomData, - } - } -} - -impl crate::private::Sealed for AnyPin where TYPE: PinType {} - -impl AnyPin -where - TYPE: PinType, -{ - /// Degrade the pin to remove the pin number generics. - pub fn degrade(self) -> AnyPin { - AnyPin { - inner: self.inner, - _type: core::marker::PhantomData, - } - } -} - -impl AnyPin { - /// Convert the pin - pub fn into_input_type(self) -> AnyPin { - AnyPin { - inner: self.inner, - _type: core::marker::PhantomData, - } - } -} - -impl AnyPin { - /// Convert the pin - pub fn into_input_type(self) -> AnyPin { - AnyPin { - inner: self.inner, - _type: core::marker::PhantomData, - } - } - - /// Convert the pin - pub fn into_input_output_type(self) -> AnyPin { - AnyPin { - inner: self.inner, - _type: core::marker::PhantomData, - } - } - - /// Convert the pin - pub fn into_input_only_analog_type(self) -> AnyPin { - AnyPin { - inner: self.inner, - _type: core::marker::PhantomData, - } - } -} - -impl AnyPin { - /// Convert the pin - pub fn into_input_type(self) -> AnyPin { - AnyPin { - inner: self.inner, - _type: core::marker::PhantomData, - } - } -} - -impl Pin for AnyPin -where - TYPE: PinType, -{ - fn number(&self) -> u8 { - let inner = &self.inner; - handle_gpio_input!(inner, target, { Pin::number(target) }) - } - - fn sleep_mode(&mut self, on: bool) { - let inner = &mut self.inner; - handle_gpio_input!(inner, target, { Pin::sleep_mode(target, on) }) - } - - fn set_alternate_function(&mut self, alternate: AlternateFunction) { - let inner = &mut self.inner; - handle_gpio_input!(inner, target, { - Pin::set_alternate_function(target, alternate) - }) - } - - fn is_listening(&self) -> bool { - let inner = &self.inner; - handle_gpio_input!(inner, target, { Pin::is_listening(target) }) - } - - fn listen_with_options( - &mut self, - event: Event, - int_enable: bool, - nmi_enable: bool, - wake_up_from_light_sleep: bool, - ) { - let inner = &mut self.inner; - handle_gpio_input!(inner, target, { - Pin::listen_with_options( - target, - event, - int_enable, - nmi_enable, - wake_up_from_light_sleep, - ) - }) - } - - fn listen(&mut self, event: Event) { - let inner = &mut self.inner; - handle_gpio_input!(inner, target, { Pin::listen(target, event) }) - } - - fn unlisten(&mut self) { - let inner = &mut self.inner; - handle_gpio_input!(inner, target, { Pin::unlisten(target) }) - } - - fn is_interrupt_set(&self) -> bool { - let inner = &self.inner; - handle_gpio_input!(inner, target, { Pin::is_interrupt_set(target) }) - } - - fn clear_interrupt(&mut self) { - let inner = &mut self.inner; - handle_gpio_input!(inner, target, { Pin::clear_interrupt(target) }) - } -} - -impl InputPin for AnyPin -where - MODE: InputMode, - TYPE: IsInputPin, -{ - fn set_to_input(&mut self) -> &mut Self { - let inner = &mut self.inner; - handle_gpio_input!(inner, target, { - InputPin::set_to_input(target); - }); - self - } - - fn enable_input(&mut self, on: bool) -> &mut Self { - let inner = &mut self.inner; - handle_gpio_input!(inner, target, { - InputPin::enable_input(target, on); - }); - self - } - - fn enable_input_in_sleep_mode(&mut self, on: bool) -> &mut Self { - let inner = &mut self.inner; - handle_gpio_input!(inner, target, { - InputPin::enable_input_in_sleep_mode(target, on); - }); - self - } - - fn is_input_high(&self) -> bool { - let inner = &self.inner; - handle_gpio_input!(inner, target, { InputPin::is_input_high(target) }) - } - - fn connect_input_to_peripheral(&mut self, signal: InputSignal) -> &mut Self { - let inner = &mut self.inner; - handle_gpio_input!(inner, target, { - InputPin::connect_input_to_peripheral(target, signal); - }); - self - } - - fn connect_input_to_peripheral_with_options( - &mut self, - signal: InputSignal, - invert: bool, - force_via_gpio_mux: bool, - ) -> &mut Self { - let inner = &mut self.inner; - handle_gpio_input!(inner, target, { - InputPin::connect_input_to_peripheral_with_options( - target, - signal, - invert, - force_via_gpio_mux, - ); - }); - self - } - - fn disconnect_input_from_peripheral(&mut self, signal: InputSignal) -> &mut Self { - let inner = &mut self.inner; - handle_gpio_input!(inner, target, { - InputPin::disconnect_input_from_peripheral(target, signal); - }); - self - } -} - -impl OutputPin for AnyPin -where - MODE: OutputMode, - TYPE: IsOutputPin, -{ - fn set_to_open_drain_output(&mut self) -> &mut Self { - let inner = &mut self.inner; - handle_gpio_output!(inner, target, { - OutputPin::set_to_open_drain_output(target); - }); - self - } - - fn set_to_push_pull_output(&mut self) -> &mut Self { - let inner = &mut self.inner; - handle_gpio_output!(inner, target, { - OutputPin::set_to_push_pull_output(target); - }); - self - } - - fn enable_output(&mut self, on: bool) -> &mut Self { - let inner = &mut self.inner; - handle_gpio_output!(inner, target, { - OutputPin::enable_output(target, on); - }); - self - } - - fn set_output_high(&mut self, on: bool) -> &mut Self { - let inner = &mut self.inner; - handle_gpio_output!(inner, target, { - OutputPin::set_output_high(target, on); - }); - self - } - - fn set_drive_strength(&mut self, strength: DriveStrength) -> &mut Self { - let inner = &mut self.inner; - handle_gpio_output!(inner, target, { - OutputPin::set_drive_strength(target, strength); - }); - self - } - - fn enable_open_drain(&mut self, on: bool) -> &mut Self { - let inner = &mut self.inner; - handle_gpio_output!(inner, target, { - OutputPin::enable_open_drain(target, on); - }); - self - } - - fn enable_output_in_sleep_mode(&mut self, on: bool) -> &mut Self { - let inner = &mut self.inner; - handle_gpio_output!(inner, target, { - OutputPin::enable_output_in_sleep_mode(target, on); - }); - self - } - - fn internal_pull_up_in_sleep_mode(&mut self, on: bool) -> &mut Self { - let inner = &mut self.inner; - handle_gpio_output!(inner, target, { - OutputPin::internal_pull_up_in_sleep_mode(target, on); - }); - self - } - - fn internal_pull_down_in_sleep_mode(&mut self, on: bool) -> &mut Self { - let inner = &mut self.inner; - handle_gpio_output!(inner, target, { - OutputPin::internal_pull_down_in_sleep_mode(target, on); - }); - self - } - - fn internal_pull_up(&mut self, on: bool) -> &mut Self { - let inner = &mut self.inner; - handle_gpio_output!(inner, target, { - OutputPin::internal_pull_up(target, on); - }); - self - } - - fn internal_pull_down(&mut self, on: bool) -> &mut Self { - let inner = &mut self.inner; - handle_gpio_output!(inner, target, { - OutputPin::internal_pull_down(target, on); - }); - self - } - - fn connect_peripheral_to_output(&mut self, signal: OutputSignal) -> &mut Self { - let inner = &mut self.inner; - handle_gpio_output!(inner, target, { - OutputPin::connect_peripheral_to_output(target, signal); - }); - self - } - - fn connect_peripheral_to_output_with_options( - &mut self, - signal: OutputSignal, - invert: bool, - invert_enable: bool, - enable_from_gpio: bool, - force_via_gpio_mux: bool, - ) -> &mut Self { - let inner = &mut self.inner; - handle_gpio_output!(inner, target, { - OutputPin::connect_peripheral_to_output_with_options( - target, - signal, - invert, - invert_enable, - enable_from_gpio, - force_via_gpio_mux, - ); - }); - self - } - - fn disconnect_peripheral_from_output(&mut self) -> &mut Self { - let inner = &mut self.inner; - handle_gpio_output!(inner, target, { - OutputPin::disconnect_peripheral_from_output(target); - }); - self - } -} - -impl AnyPin, TYPE> { - /// Is the input pin high? - #[inline] - pub fn is_high(&self) -> bool { - let inner = &self.inner; - handle_gpio_input!(inner, target, { target.is_high() }) - } - - /// Is the input pin low? - #[inline] - pub fn is_low(&self) -> bool { - let inner = &self.inner; - handle_gpio_input!(inner, target, { target.is_low() }) - } -} - -impl AnyPin, TYPE> { - /// Drives the pin low. - #[inline] - pub fn set_low(&mut self) { - let inner = &mut self.inner; - handle_gpio_output!(inner, target, { target.set_low() }) - } - - /// Drives the pin high. - #[inline] - pub fn set_high(&mut self) { - let inner = &mut self.inner; - handle_gpio_output!(inner, target, { target.set_high() }) - } - - /// Drives the pin high or low depending on the provided value. - #[inline] - pub fn set_state(&mut self, state: bool) { - let inner = &mut self.inner; - handle_gpio_output!(inner, target, { target.set_state(state) }) - } - - /// Is the pin in drive high mode? - #[inline] - pub fn is_set_high(&self) -> bool { - let inner = &self.inner; - handle_gpio_output!(inner, target, { target.is_set_high() }) - } - - /// Is the pin in drive low mode? - #[inline] - pub fn is_set_low(&self) -> bool { - let inner = &self.inner; - handle_gpio_output!(inner, target, { target.is_set_low() }) - } - - /// Toggle pin output. - #[inline] - pub fn toggle(&mut self) { - let inner = &mut self.inner; - handle_gpio_output!(inner, target, { target.toggle() }) - } -} - -#[cfg(feature = "async")] -impl AnyPin, TYPE> { - /// Wait until the pin is high. If it is already high, return immediately. - pub async fn wait_for_high(&mut self) { - let inner = &mut self.inner; - handle_gpio_input!(inner, target, { target.wait_for_high().await }) - } - - /// Wait until the pin is low. If it is already low, return immediately. - pub async fn wait_for_low(&mut self) { - let inner = &mut self.inner; - handle_gpio_input!(inner, target, { target.wait_for_low().await }) - } - - /// Wait for the pin to undergo a transition from low to high. - pub async fn wait_for_rising_edge(&mut self) { - let inner = &mut self.inner; - handle_gpio_input!(inner, target, { target.wait_for_rising_edge().await }) - } - - /// Wait for the pin to undergo a transition from high to low. - pub async fn wait_for_falling_edge(&mut self) { - let inner = &mut self.inner; - handle_gpio_input!(inner, target, { target.wait_for_falling_edge().await }) - } - - /// Wait for the pin to undergo any transition, i.e low to high OR high to - /// low. - pub async fn wait_for_any_edge(&mut self) { - let inner = &mut self.inner; - handle_gpio_input!(inner, target, { target.wait_for_any_edge().await }) } } @@ -1920,7 +1221,7 @@ macro_rules! gpio { } $( - impl $crate::gpio::GpioProperties for GpioPin { + impl $crate::gpio::GpioProperties for GpioPin<$gpionum> { type Bank = $crate::gpio::[< Bank $bank GpioRegisterAccess >]; type InterruptStatus = $crate::gpio::[< InterruptStatusRegisterAccessBank $bank >]; type Signals = [< Gpio $gpionum Signals >]; @@ -1928,7 +1229,7 @@ macro_rules! gpio { } #[doc(hidden)] - pub struct [] {} + pub struct []; impl $crate::gpio::GpioSignal for [] { fn output_signals() -> [Option; 6]{ @@ -1956,75 +1257,46 @@ macro_rules! gpio { input_signals } } + + impl $crate::gpio::CreateErasedPin for GpioPin<$gpionum> { + fn erased_pin(&self, _: $crate::private::Internal) -> ErasedPin { + $crate::gpio::ErasedPin::[< Gpio $gpionum >](unsafe { Self::steal() }) + } + } )+ /// Pins available on this chip #[allow(missing_docs)] pub struct Pins { $( - pub [< gpio $gpionum >] : GpioPin, + pub [< gpio $gpionum >] : GpioPin<$gpionum>, )+ } $( #[doc = concat!("Alias for GpioPin")] - pub type [] = GpioPin; + pub type [] = GpioPin<$gpionum>; )+ - pub(crate) enum ErasedPin { + #[doc(hidden)] + pub enum ErasedPin { $( - []([]), + []([]), )+ } - /// Generic pin - /// - /// This is useful e.g. if you need an array of pins. - pub struct AnyPin { - pub(crate) inner: ErasedPin, - pub(crate) _type: core::marker::PhantomData, - } - - $( - impl From< [] > for AnyPin]> { - fn from(value: []) -> Self { - AnyPin { - inner: ErasedPin::[](value), - _type: core::marker::PhantomData, + impl ErasedPin { + pub(crate) unsafe fn clone_unchecked(&mut self) -> Self { + match self { + $( + ErasedPin::[](_) => { + $crate::gpio::ErasedPin::[< Gpio $gpionum >](unsafe { GpioPin::steal() }) + } + )+ } } } - impl From< [] > for AnyPin { - fn from(value: []) -> Self { - AnyPin { - inner: ErasedPin::[](value), - _type: core::marker::PhantomData, - } - } - } - - impl [] { - pub fn degrade(self) -> AnyPin]> { - AnyPin { - inner: ErasedPin::[](self), - _type: core::marker::PhantomData, - } - } - } - - impl TryInto<[]> for AnyPin { - type Error = (); - - fn try_into(self) -> Result<[], Self::Error> { - match self.inner { - ErasedPin::[](gpio) => Ok(gpio), - _ => Err(()), - } - } - } - )+ - procmacros::make_gpio_enum_dispatch_macro!( handle_gpio_output { InputOutputAnalog, InputOutput, } @@ -2055,7 +1327,7 @@ macro_rules! rtc_pins { ( $pin_num:expr, $rtc_pin:expr, $pin_reg:expr, $prefix:pat, $hold:ident $(, $rue:ident, $rde:ident)? ) => { - impl $crate::gpio::RtcPin for GpioPin + impl $crate::gpio::RtcPin for GpioPin<$pin_num> { fn rtc_number(&self) -> u8 { $rtc_pin @@ -2095,7 +1367,7 @@ macro_rules! rtc_pins { } $( - impl $crate::gpio::RtcPinWithResistors for GpioPin + impl $crate::gpio::RtcPinWithResistors for GpioPin<$pin_num> { fn rtcio_pullup(&mut self, enable: bool) { let rtcio = unsafe { &*$crate::peripherals::RTC_IO::PTR }; @@ -2113,21 +1385,6 @@ macro_rules! rtc_pins { } } } - - #[cfg(not(esp32))] - paste::paste!{ - impl $crate::gpio::rtc_io::IntoLowPowerPin<$pin_num> for GpioPin { - fn into_low_power(mut self) -> $crate::gpio::rtc_io::LowPowerPin { - use $crate::gpio::RtcPin; - - self.rtc_set_config(false, true, $crate::gpio::RtcFunction::Rtc); - - $crate::gpio::rtc_io::LowPowerPin { - private: core::marker::PhantomData, - } - } - } - } )? }; @@ -2147,7 +1404,7 @@ macro_rules! rtc_pins { ( $pin_num:expr ) => { - impl $crate::gpio::RtcPin for GpioPin { + impl $crate::gpio::RtcPin for GpioPin<$pin_num> { unsafe fn apply_wakeup(&mut self, wakeup: bool, level: u8) { let rtc_cntl = unsafe { &*$crate::peripherals::RTC_CNTL::ptr() }; paste::paste! { @@ -2164,7 +1421,7 @@ macro_rules! rtc_pins { } } - impl $crate::gpio::RtcPinWithResistors for GpioPin { + impl $crate::gpio::RtcPinWithResistors for GpioPin<$pin_num> { fn rtcio_pullup(&mut self, enable: bool) { let io_mux = unsafe { &*$crate::peripherals::IO_MUX::ptr() }; io_mux.gpio($pin_num).modify(|_, w| w.fun_wpu().bit(enable)); @@ -2289,6 +1546,699 @@ macro_rules! analog { } } +/// GPIO output driver. +pub struct Output<'d, P> { + pin: PeripheralRef<'d, P>, +} + +impl<'d, P> Output<'d, P> +where + P: OutputPin, +{ + /// Create GPIO output driver for a [GpioPin] with the provided level + #[inline] + pub fn new(pin: impl crate::peripheral::Peripheral

+ 'd, initial_output: bool) -> Self { + crate::into_ref!(pin); + + pin.set_output_high(initial_output, private::Internal); + pin.set_to_push_pull_output(private::Internal); + + Self { pin } + } + + /// Set the output as high. + #[inline] + pub fn set_high(&mut self) { + self.pin.set_output_high(true, private::Internal); + } + + /// Set the output as low. + #[inline] + pub fn set_low(&mut self) { + self.pin.set_output_high(false, private::Internal); + } + + /// Set the output level. + #[inline] + pub fn set_level(&mut self, level: Level) { + self.pin.set_output_high(level.into(), private::Internal); + } + + /// Is the output pin set as high? + #[inline] + pub fn is_set_high(&self) -> bool { + self.pin.is_set_high(private::Internal) + } + + /// Is the output pin set as low? + #[inline] + pub fn is_set_low(&self) -> bool { + !self.pin.is_set_high(private::Internal) + } + + /// What level output is set to + #[inline] + pub fn get_output_level(&self) -> Level { + self.pin.is_set_high(private::Internal).into() + } + + /// Toggle pin output + #[inline] + pub fn toggle(&mut self) { + let level = !self.pin.is_set_high(private::Internal); + self.pin.set_output_high(level, private::Internal); + } + + /// Configure the [DriveStrength] of the pin + pub fn set_drive_strength(&mut self, strength: DriveStrength) { + self.pin.set_drive_strength(strength, private::Internal); + } +} + +/// GPIO input driver. +pub struct Input<'d, P> { + pin: PeripheralRef<'d, P>, +} + +impl<'d, P> Input<'d, P> +where + P: InputPin, +{ + /// Create GPIO input driver for a [Pin] with the provided [Pull] + /// configuration. + #[inline] + pub fn new(pin: impl crate::peripheral::Peripheral

+ 'd, pull: Pull) -> Self { + crate::into_ref!(pin); + pin.init_input(pull == Pull::Down, pull == Pull::Up, private::Internal); + Self { pin } + } + + /// Get whether the pin input level is high. + #[inline] + pub fn is_high(&self) -> bool { + self.pin.is_input_high(private::Internal) + } + + /// Get whether the pin input level is low. + #[inline] + pub fn is_low(&self) -> bool { + !self.is_high() + } + + /// Get the current pin input level. + #[inline] + pub fn get_level(&self) -> Level { + self.is_high().into() + } + + /// Listen for interrupts + #[inline] + pub fn listen(&mut self, event: Event) { + self.pin.listen(event, private::Internal); + } + + /// Stop listening for interrupts + pub fn unlisten(&mut self) { + self.pin.unlisten(private::Internal); + } + + /// Clear the interrupt status bit for this Pin + #[inline] + pub fn clear_interrupt(&mut self) { + self.pin.clear_interrupt(private::Internal); + } +} + +/// GPIO open-drain output driver. +pub struct OutputOpenDrain<'d, P> { + pin: PeripheralRef<'d, P>, +} + +impl<'d, P> OutputOpenDrain<'d, P> +where + P: InputPin + OutputPin, +{ + /// Create GPIO open-drain output driver for a [Pin] with the provided + /// initial output-level and [Pull] configuration. + #[inline] + pub fn new( + pin: impl crate::peripheral::Peripheral

+ 'd, + initial_output: bool, + pull: Pull, + ) -> Self { + crate::into_ref!(pin); + pin.set_output_high(initial_output, private::Internal); + pin.set_to_open_drain_output(private::Internal); + pin.internal_pull_down(pull == Pull::Down, private::Internal); + pin.internal_pull_up(pull == Pull::Up, private::Internal); + + Self { pin } + } + + /// Get whether the pin input level is high. + #[inline] + pub fn is_high(&self) -> bool { + self.pin.is_input_high(private::Internal) + } + + /// Get whether the pin input level is low. + #[inline] + pub fn is_low(&self) -> bool { + !self.is_high() + } + + /// Get the current pin input level. + #[inline] + pub fn get_level(&self) -> Level { + self.is_high().into() + } + + /// Listen for interrupts + #[inline] + pub fn listen(&mut self, event: Event) { + self.pin.listen(event, private::Internal); + } + + /// Clear the interrupt status bit for this Pin + #[inline] + pub fn clear_interrupt(&mut self) { + self.pin.clear_interrupt(private::Internal); + } + + /// Set the output as high. + #[inline] + pub fn set_high(&mut self) { + self.pin.set_output_high(true, private::Internal); + } + + /// Set the output as low. + #[inline] + pub fn set_low(&mut self) { + self.pin.set_output_high(false, private::Internal); + } + + /// Set the output level. + #[inline] + pub fn set_level(&mut self, level: Level) { + self.pin.set_output_high(level.into(), private::Internal); + } + + /// Is the output pin set as high? + #[inline] + pub fn is_set_high(&self) -> bool { + self.pin.is_set_high(private::Internal) + } + + /// Is the output pin set as low? + #[inline] + pub fn is_set_low(&self) -> bool { + !self.pin.is_set_high(private::Internal) + } + + /// What level output is set to + #[inline] + pub fn get_output_level(&self) -> Level { + self.pin.is_set_high(private::Internal).into() + } + + /// Toggle pin output + #[inline] + pub fn toggle(&mut self) { + let level = !self.pin.is_set_high(private::Internal); + self.pin.set_output_high(level, private::Internal); + } + + /// Configure the [DriveStrength] of the pin + pub fn set_drive_strength(&mut self, strength: DriveStrength) { + self.pin.set_drive_strength(strength, private::Internal); + } +} + +/// Generic GPIO output driver. +pub struct AnyOutput<'d> { + pin: ErasedPin, + _phantom: PhantomData<&'d ()>, +} + +impl<'d> AnyOutput<'d> { + /// Create GPIO output driver for a [GpioPin] with the provided level + #[inline] + pub fn new( + pin: impl crate::peripheral::Peripheral

+ 'd, + initial_output: bool, + ) -> Self { + crate::into_ref!(pin); + + pin.set_output_high(initial_output, private::Internal); + pin.set_to_push_pull_output(private::Internal); + + let pin = pin.erased_pin(private::Internal); + + Self { + pin, + _phantom: PhantomData, + } + } + + /// Set the output as high. + #[inline] + pub fn set_high(&mut self) { + self.pin.set_output_high(true, private::Internal); + } + + /// Set the output as low. + #[inline] + pub fn set_low(&mut self) { + self.pin.set_output_high(false, private::Internal); + } + + /// Set the output level. + #[inline] + pub fn set_level(&mut self, level: Level) { + self.pin.set_output_high(level.into(), private::Internal); + } + + /// Is the output pin set as high? + #[inline] + pub fn is_set_high(&self) -> bool { + self.pin.is_set_high(private::Internal) + } + + /// Is the output pin set as low? + #[inline] + pub fn is_set_low(&self) -> bool { + !self.pin.is_set_high(private::Internal) + } + + /// What level output is set to + #[inline] + pub fn get_output_level(&self) -> Level { + self.pin.is_set_high(private::Internal).into() + } + + /// Toggle pin output + #[inline] + pub fn toggle(&mut self) { + let pin = &mut self.pin; + pin.set_output_high(!pin.is_set_high(private::Internal), private::Internal); + } +} + +/// Generic GPIO input driver. +pub struct AnyInput<'d> { + pin: ErasedPin, + _phantom: PhantomData<&'d ()>, +} + +impl<'d> AnyInput<'d> { + /// Create GPIO input driver for a [Pin] with the provided [Pull] + /// configuration. + #[inline] + pub fn new( + pin: impl crate::peripheral::Peripheral

+ 'd, + pull: Pull, + ) -> Self { + crate::into_ref!(pin); + pin.init_input(pull == Pull::Down, pull == Pull::Up, private::Internal); + + let pin = pin.erased_pin(private::Internal); + + Self { + pin, + _phantom: PhantomData, + } + } + + /// Get whether the pin input level is high. + #[inline] + pub fn is_high(&self) -> bool { + self.pin.is_input_high(private::Internal) + } + + /// Get whether the pin input level is low. + #[inline] + pub fn is_low(&self) -> bool { + !self.is_high() + } + + /// Get the current pin input level. + #[inline] + pub fn get_level(&self) -> Level { + self.is_high().into() + } + + /// Listen for interrupts + #[inline] + pub fn listen(&mut self, event: Event) { + self.pin.listen(event, private::Internal); + } + + /// Clear the interrupt status bit for this Pin + #[inline] + pub fn clear_interrupt(&mut self) { + self.pin.clear_interrupt(private::Internal); + } +} + +/// Generic GPIO open-drain output driver. +pub struct AnyOutputOpenDrain<'d> { + pin: ErasedPin, + _phantom: PhantomData<&'d ()>, +} + +impl<'d> AnyOutputOpenDrain<'d> { + /// Create GPIO open-drain output driver for a [Pin] with the provided + /// initial output-level and [Pull] configuration. + #[inline] + pub fn new( + pin: impl crate::peripheral::Peripheral

+ 'd, + initial_output: bool, + pull: Pull, + ) -> Self { + crate::into_ref!(pin); + pin.set_output_high(initial_output, private::Internal); + pin.internal_pull_down(pull == Pull::Down, private::Internal); + pin.internal_pull_up(pull == Pull::Up, private::Internal); + pin.set_to_open_drain_output(private::Internal); + + let pin = pin.erased_pin(private::Internal); + + Self { + pin, + _phantom: PhantomData, + } + } + + /// Get whether the pin input level is high. + #[inline] + pub fn is_high(&self) -> bool { + self.pin.is_input_high(private::Internal) + } + + /// Get whether the pin input level is low. + #[inline] + pub fn is_low(&self) -> bool { + !self.is_high() + } + + /// Get the current pin input level. + #[inline] + pub fn get_level(&self) -> Level { + self.is_high().into() + } + + /// Listen for interrupts + #[inline] + pub fn listen(&mut self, event: Event) { + self.pin.listen(event, private::Internal); + } + + /// Clear the interrupt status bit for this Pin + #[inline] + pub fn clear_interrupt(&mut self) { + self.pin.clear_interrupt(private::Internal); + } + + /// Set the output as high. + #[inline] + pub fn set_high(&mut self) { + self.pin.set_output_high(true, private::Internal); + } + + /// Set the output as low. + #[inline] + pub fn set_low(&mut self) { + self.pin.set_output_high(false, private::Internal); + } + + /// Set the output level. + #[inline] + pub fn set_level(&mut self, level: Level) { + self.pin.set_output_high(level.into(), private::Internal); + } + + /// Is the output pin set as high? + #[inline] + pub fn is_set_high(&self) -> bool { + self.pin.is_set_high(private::Internal) + } + + /// Is the output pin set as low? + #[inline] + pub fn is_set_low(&self) -> bool { + !self.pin.is_set_high(private::Internal) + } + + /// What level output is set to + #[inline] + pub fn get_output_level(&self) -> Level { + self.pin.is_set_high(private::Internal).into() + } + + /// Toggle pin output + #[inline] + pub fn toggle(&mut self) { + let pin = &mut self.pin; + pin.set_output_high(!pin.is_set_high(private::Internal), private::Internal); + } +} + +pub(crate) mod internal { + use super::*; + + impl private::Sealed for ErasedPin {} + + impl Pin for ErasedPin { + fn number(&self, _: private::Internal) -> u8 { + handle_gpio_input!(self, target, { Pin::number(target, private::Internal) }) + } + + fn sleep_mode(&mut self, on: bool, _: private::Internal) { + handle_gpio_input!(self, target, { + Pin::sleep_mode(target, on, private::Internal) + }) + } + + fn set_alternate_function(&mut self, alternate: AlternateFunction, _: private::Internal) { + handle_gpio_input!(self, target, { + Pin::set_alternate_function(target, alternate, private::Internal) + }) + } + + fn is_listening(&self, _: private::Internal) -> bool { + handle_gpio_input!(self, target, { + Pin::is_listening(target, private::Internal) + }) + } + + fn listen_with_options( + &mut self, + event: Event, + int_enable: bool, + nmi_enable: bool, + wake_up_from_light_sleep: bool, + _: private::Internal, + ) { + handle_gpio_input!(self, target, { + Pin::listen_with_options( + target, + event, + int_enable, + nmi_enable, + wake_up_from_light_sleep, + private::Internal, + ) + }) + } + + fn unlisten(&mut self, _: private::Internal) { + handle_gpio_input!(self, target, { Pin::unlisten(target, private::Internal) }) + } + + fn is_interrupt_set(&self, _: private::Internal) -> bool { + handle_gpio_input!(self, target, { + Pin::is_interrupt_set(target, private::Internal) + }) + } + + fn clear_interrupt(&mut self, _: private::Internal) { + handle_gpio_input!(self, target, { + Pin::clear_interrupt(target, private::Internal) + }) + } + } + + impl InputPin for ErasedPin { + fn init_input(&self, pull_down: bool, pull_up: bool, _: private::Internal) { + handle_gpio_input!(self, target, { + InputPin::init_input(target, pull_down, pull_up, private::Internal) + }) + } + + fn set_to_input(&mut self, _: private::Internal) { + handle_gpio_input!(self, target, { + InputPin::set_to_input(target, private::Internal); + }); + } + + fn enable_input(&mut self, on: bool, _: private::Internal) { + handle_gpio_input!(self, target, { + InputPin::enable_input(target, on, private::Internal) + }); + } + + fn enable_input_in_sleep_mode(&mut self, on: bool, _: private::Internal) { + handle_gpio_input!(self, target, { + InputPin::enable_input_in_sleep_mode(target, on, private::Internal) + }); + } + + fn is_input_high(&self, _: private::Internal) -> bool { + handle_gpio_input!(self, target, { + InputPin::is_input_high(target, private::Internal) + }) + } + + fn connect_input_to_peripheral(&mut self, signal: InputSignal, _: private::Internal) { + handle_gpio_input!(self, target, { + InputPin::connect_input_to_peripheral(target, signal, private::Internal) + }); + } + + fn connect_input_to_peripheral_with_options( + &mut self, + signal: InputSignal, + invert: bool, + force_via_gpio_mux: bool, + _: private::Internal, + ) { + handle_gpio_input!(self, target, { + InputPin::connect_input_to_peripheral_with_options( + target, + signal, + invert, + force_via_gpio_mux, + private::Internal, + ) + }); + } + + fn disconnect_input_from_peripheral(&mut self, signal: InputSignal, _: private::Internal) { + handle_gpio_input!(self, target, { + InputPin::disconnect_input_from_peripheral(target, signal, private::Internal) + }); + } + } + + impl OutputPin for ErasedPin { + fn set_to_open_drain_output(&mut self, _: private::Internal) { + handle_gpio_output!(self, target, { + OutputPin::set_to_open_drain_output(target, private::Internal) + }); + } + + fn set_to_push_pull_output(&mut self, _: private::Internal) { + handle_gpio_output!(self, target, { + OutputPin::set_to_push_pull_output(target, private::Internal) + }); + } + + fn enable_output(&mut self, on: bool, _: private::Internal) { + handle_gpio_output!(self, target, { + OutputPin::enable_output(target, on, private::Internal) + }); + } + + fn set_output_high(&mut self, on: bool, _: private::Internal) { + handle_gpio_output!(self, target, { + OutputPin::set_output_high(target, on, private::Internal) + }); + } + + fn set_drive_strength(&mut self, strength: DriveStrength, _: private::Internal) { + handle_gpio_output!(self, target, { + OutputPin::set_drive_strength(target, strength, private::Internal) + }); + } + + fn enable_open_drain(&mut self, on: bool, _: private::Internal) { + handle_gpio_output!(self, target, { + OutputPin::enable_open_drain(target, on, private::Internal) + }); + } + + fn enable_output_in_sleep_mode(&mut self, on: bool, _: private::Internal) { + handle_gpio_output!(self, target, { + OutputPin::enable_output_in_sleep_mode(target, on, private::Internal) + }); + } + + fn internal_pull_up_in_sleep_mode(&mut self, on: bool, _: private::Internal) { + handle_gpio_output!(self, target, { + OutputPin::internal_pull_up_in_sleep_mode(target, on, private::Internal) + }); + } + + fn internal_pull_down_in_sleep_mode(&mut self, on: bool, _: private::Internal) { + handle_gpio_output!(self, target, { + OutputPin::internal_pull_down_in_sleep_mode(target, on, private::Internal) + }); + } + + fn internal_pull_up(&mut self, on: bool, _: private::Internal) { + handle_gpio_output!(self, target, { + OutputPin::internal_pull_up(target, on, private::Internal) + }); + } + + fn internal_pull_down(&mut self, on: bool, _: private::Internal) { + handle_gpio_output!(self, target, { + OutputPin::internal_pull_down(target, on, private::Internal) + }); + } + + fn connect_peripheral_to_output(&mut self, signal: OutputSignal, _: private::Internal) { + handle_gpio_output!(self, target, { + OutputPin::connect_peripheral_to_output(target, signal, private::Internal) + }); + } + + fn connect_peripheral_to_output_with_options( + &mut self, + signal: OutputSignal, + invert: bool, + invert_enable: bool, + enable_from_gpio: bool, + force_via_gpio_mux: bool, + _: private::Internal, + ) { + handle_gpio_output!(self, target, { + OutputPin::connect_peripheral_to_output_with_options( + target, + signal, + invert, + invert_enable, + enable_from_gpio, + force_via_gpio_mux, + private::Internal, + ) + }); + } + + fn disconnect_peripheral_from_output(&mut self, _: private::Internal) { + handle_gpio_output!(self, target, { + OutputPin::disconnect_peripheral_from_output(target, private::Internal) + }); + } + + fn is_set_high(&self, _: private::Internal) -> bool { + handle_gpio_output!(self, target, { + OutputPin::is_set_high(target, private::Internal) + }) + } + } +} + #[cfg(feature = "async")] mod asynch { use core::task::{Context, Poll}; @@ -2301,98 +2251,96 @@ mod asynch { const NEW_AW: AtomicWaker = AtomicWaker::new(); static PIN_WAKERS: [AtomicWaker; NUM_PINS] = [NEW_AW; NUM_PINS]; - impl GpioPin, GPIONUM> + impl<'d, P> Input<'d, P> where - Self: GpioProperties, - ::PinType: IsInputPin, + P: InputPin, { /// Wait until the pin is high. If it is already high, return /// immediately. pub async fn wait_for_high(&mut self) { - PinFuture::new(self, Event::HighLevel).await + self.listen(Event::HighLevel); + PinFuture::new(self.pin.number(private::Internal)).await } /// Wait until the pin is low. If it is already low, return immediately. pub async fn wait_for_low(&mut self) { - PinFuture::new(self, Event::LowLevel).await + self.listen(Event::LowLevel); + PinFuture::new(self.pin.number(private::Internal)).await } /// Wait for the pin to undergo a transition from low to high. pub async fn wait_for_rising_edge(&mut self) { - PinFuture::new(self, Event::RisingEdge).await + self.listen(Event::RisingEdge); + PinFuture::new(self.pin.number(private::Internal)).await } /// Wait for the pin to undergo a transition from high to low. pub async fn wait_for_falling_edge(&mut self) { - PinFuture::new(self, Event::FallingEdge).await + self.listen(Event::FallingEdge); + PinFuture::new(self.pin.number(private::Internal)).await } /// Wait for the pin to undergo any transition, i.e low to high OR high /// to low. pub async fn wait_for_any_edge(&mut self) { - PinFuture::new(self, Event::AnyEdge).await + self.listen(Event::AnyEdge); + PinFuture::new(self.pin.number(private::Internal)).await } } - impl GpioPin, GPIONUM> - where - Self: GpioProperties, - ::PinType: IsInputPin + IsOutputPin, - { + impl<'d> AnyInput<'d> { /// Wait until the pin is high. If it is already high, return /// immediately. pub async fn wait_for_high(&mut self) { - PinFuture::new(self, Event::HighLevel).await + self.listen(Event::HighLevel); + PinFuture::new(self.pin.number(private::Internal)).await } /// Wait until the pin is low. If it is already low, return immediately. pub async fn wait_for_low(&mut self) { - PinFuture::new(self, Event::LowLevel).await + self.listen(Event::LowLevel); + PinFuture::new(self.pin.number(private::Internal)).await } /// Wait for the pin to undergo a transition from low to high. pub async fn wait_for_rising_edge(&mut self) { - PinFuture::new(self, Event::RisingEdge).await + self.listen(Event::RisingEdge); + PinFuture::new(self.pin.number(private::Internal)).await } /// Wait for the pin to undergo a transition from high to low. pub async fn wait_for_falling_edge(&mut self) { - PinFuture::new(self, Event::FallingEdge).await + self.listen(Event::FallingEdge); + PinFuture::new(self.pin.number(private::Internal)).await } /// Wait for the pin to undergo any transition, i.e low to high OR high /// to low. pub async fn wait_for_any_edge(&mut self) { - PinFuture::new(self, Event::AnyEdge).await + self.listen(Event::AnyEdge); + PinFuture::new(self.pin.number(private::Internal)).await } } - pub struct PinFuture<'a, P> { - pin: &'a mut P, + pub struct PinFuture { + pin_num: u8, } - impl<'a, P> PinFuture<'a, P> - where - P: crate::gpio::Pin, - { - pub fn new(pin: &'a mut P, event: Event) -> Self { - pin.listen(event); - Self { pin } + impl PinFuture { + pub fn new(pin_num: u8) -> Self { + Self { pin_num } } } - impl<'a, P> core::future::Future for PinFuture<'a, P> - where - P: crate::gpio::Pin, - { + impl core::future::Future for PinFuture { type Output = (); fn poll(self: core::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { - PIN_WAKERS[self.pin.number() as usize].register(cx.waker()); + PIN_WAKERS[self.pin_num as usize].register(cx.waker()); // if pin is no longer listening its been triggered // therefore the future has resolved - if !self.pin.is_listening() { + if !is_listening(self.pin_num) { Poll::Ready(()) } else { Poll::Pending @@ -2400,6 +2348,15 @@ mod asynch { } } + pub(crate) fn is_listening(gpio_num: u8) -> bool { + let bits = unsafe { &*GPIO::PTR } + .pin(gpio_num as usize) + .read() + .int_ena() + .bits(); + bits != 0 + } + pub(crate) fn set_int_enable( gpio_num: u8, int_ena: u8, @@ -2454,52 +2411,39 @@ mod embedded_hal_02_impls { use super::*; - impl digital::InputPin for GpioPin, GPIONUM> + impl<'d, P> digital::InputPin for Input<'d, P> where - Self: GpioProperties, + P: InputPin, { type Error = core::convert::Infallible; + fn is_high(&self) -> Result { - Ok(self.is_high()) + Ok(self.pin.is_input_high(private::Internal)) } fn is_low(&self) -> Result { - Ok(self.is_low()) + Ok(!self.pin.is_input_high(private::Internal)) } } - impl digital::InputPin for GpioPin, GPIONUM> + impl<'d, P> digital::OutputPin for Output<'d, P> where - Self: GpioProperties, + P: OutputPin, { type Error = core::convert::Infallible; - fn is_high(&self) -> Result { - Ok(::Bank::read_input() & (1 << (GPIONUM % 32)) != 0) - } - fn is_low(&self) -> Result { - Ok(self.is_low()) - } - } - impl digital::OutputPin for GpioPin, GPIONUM> - where - Self: GpioProperties, - ::PinType: IsOutputPin, - { - type Error = core::convert::Infallible; fn set_high(&mut self) -> Result<(), Self::Error> { - self.set_high(); + self.pin.set_output_high(true, private::Internal); Ok(()) } fn set_low(&mut self) -> Result<(), Self::Error> { - self.set_low(); + self.pin.set_output_high(false, private::Internal); Ok(()) } } - impl digital::StatefulOutputPin for GpioPin, GPIONUM> + impl<'d, P> digital::StatefulOutputPin for Output<'d, P> where - Self: GpioProperties, - ::PinType: IsOutputPin, + P: OutputPin, { fn is_set_high(&self) -> Result { Ok(self.is_set_high()) @@ -2509,55 +2453,150 @@ mod embedded_hal_02_impls { } } - impl digital::ToggleableOutputPin for GpioPin, GPIONUM> + impl<'d, P> digital::ToggleableOutputPin for Output<'d, P> where - Self: GpioProperties, - ::PinType: IsOutputPin, + P: OutputPin, { type Error = core::convert::Infallible; + fn toggle(&mut self) -> Result<(), Self::Error> { self.toggle(); Ok(()) } } - impl digital::InputPin for AnyPin, TYPE> { + impl<'d, P> digital::InputPin for OutputOpenDrain<'d, P> + where + P: InputPin + OutputPin, + { type Error = core::convert::Infallible; fn is_high(&self) -> Result { - Ok(self.is_high()) + Ok(self.pin.is_input_high(private::Internal)) } - fn is_low(&self) -> Result { - Ok(self.is_low()) + Ok(!self.pin.is_input_high(private::Internal)) } } - impl digital::OutputPin for AnyPin, TYPE> { + impl<'d, P> digital::OutputPin for OutputOpenDrain<'d, P> + where + P: InputPin + OutputPin, + { type Error = core::convert::Infallible; - fn set_low(&mut self) -> Result<(), Self::Error> { - self.set_low(); + fn set_high(&mut self) -> Result<(), Self::Error> { + self.pin.set_output_high(true, private::Internal); Ok(()) } - - fn set_high(&mut self) -> Result<(), Self::Error> { - self.set_high(); + fn set_low(&mut self) -> Result<(), Self::Error> { + self.pin.set_output_high(false, private::Internal); Ok(()) } } - impl digital::StatefulOutputPin for AnyPin, TYPE> { + impl<'d, P> digital::StatefulOutputPin for OutputOpenDrain<'d, P> + where + P: InputPin + OutputPin, + { fn is_set_high(&self) -> Result { Ok(self.is_set_high()) } - fn is_set_low(&self) -> Result { Ok(self.is_set_low()) } } - impl digital::ToggleableOutputPin for AnyPin, TYPE> { + impl<'d, P> digital::ToggleableOutputPin for OutputOpenDrain<'d, P> + where + P: InputPin + OutputPin, + { + type Error = core::convert::Infallible; + + fn toggle(&mut self) -> Result<(), Self::Error> { + self.toggle(); + Ok(()) + } + } + + // TODO AnyInput, AnyOutput, AnyOpenDrainOutput + + impl<'d> digital::InputPin for AnyInput<'d> { + type Error = core::convert::Infallible; + + fn is_high(&self) -> Result { + Ok(self.pin.is_input_high(private::Internal)) + } + fn is_low(&self) -> Result { + Ok(!self.pin.is_input_high(private::Internal)) + } + } + + impl<'d> digital::OutputPin for AnyOutput<'d> { + type Error = core::convert::Infallible; + + fn set_high(&mut self) -> Result<(), Self::Error> { + self.pin.set_output_high(true, private::Internal); + Ok(()) + } + fn set_low(&mut self) -> Result<(), Self::Error> { + self.pin.set_output_high(false, private::Internal); + Ok(()) + } + } + + impl<'d> digital::StatefulOutputPin for AnyOutput<'d> { + fn is_set_high(&self) -> Result { + Ok(self.is_set_high()) + } + fn is_set_low(&self) -> Result { + Ok(self.is_set_low()) + } + } + + impl<'d> digital::ToggleableOutputPin for AnyOutput<'d> { + type Error = core::convert::Infallible; + + fn toggle(&mut self) -> Result<(), Self::Error> { + self.toggle(); + Ok(()) + } + } + + impl<'d> digital::InputPin for AnyOutputOpenDrain<'d> { + type Error = core::convert::Infallible; + + fn is_high(&self) -> Result { + Ok(self.pin.is_input_high(private::Internal)) + } + fn is_low(&self) -> Result { + Ok(!self.pin.is_input_high(private::Internal)) + } + } + + impl<'d> digital::OutputPin for AnyOutputOpenDrain<'d> { + type Error = core::convert::Infallible; + + fn set_high(&mut self) -> Result<(), Self::Error> { + self.pin.set_output_high(true, private::Internal); + Ok(()) + } + fn set_low(&mut self) -> Result<(), Self::Error> { + self.pin.set_output_high(false, private::Internal); + Ok(()) + } + } + + impl<'d> digital::StatefulOutputPin for AnyOutputOpenDrain<'d> { + fn is_set_high(&self) -> Result { + Ok(self.is_set_high()) + } + fn is_set_low(&self) -> Result { + Ok(self.is_set_low()) + } + } + + impl<'d> digital::ToggleableOutputPin for AnyOutputOpenDrain<'d> { type Error = core::convert::Infallible; fn toggle(&mut self) -> Result<(), Self::Error> { @@ -2573,93 +2612,85 @@ mod embedded_hal_impls { use super::*; - impl digital::ErrorType for GpioPin, GPIONUM> + impl<'d, P> digital::ErrorType for Input<'d, P> where - Self: GpioProperties, + P: InputPin, { type Error = core::convert::Infallible; } - impl digital::InputPin for GpioPin, GPIONUM> + impl<'d, P> digital::InputPin for Input<'d, P> where - Self: GpioProperties, + P: InputPin, { fn is_high(&mut self) -> Result { - Ok(Self::is_high(self)) + Ok(Input::is_high(self)) } + fn is_low(&mut self) -> Result { - Ok(Self::is_low(self)) + Ok(Input::is_low(self)) } } - impl digital::InputPin for GpioPin, GPIONUM> + impl<'d, P> digital::ErrorType for Output<'d, P> where - Self: GpioProperties, - ::PinType: IsOutputPin, - { - fn is_high(&mut self) -> Result { - Ok(Self::is_high(self)) - } - fn is_low(&mut self) -> Result { - Ok(Self::is_low(self)) - } - } - - impl digital::ErrorType for GpioPin, GPIONUM> - where - Self: GpioProperties, - ::PinType: IsOutputPin, + P: OutputPin, { type Error = core::convert::Infallible; } - impl digital::OutputPin for GpioPin, GPIONUM> + impl<'d, P> digital::OutputPin for Output<'d, P> where - Self: GpioProperties, - ::PinType: IsOutputPin, + P: OutputPin, { fn set_low(&mut self) -> Result<(), Self::Error> { self.set_low(); Ok(()) } + fn set_high(&mut self) -> Result<(), Self::Error> { self.set_high(); Ok(()) } } - impl digital::StatefulOutputPin for GpioPin, GPIONUM> + impl<'d, P> digital::StatefulOutputPin for Output<'d, P> where - Self: GpioProperties, - ::PinType: IsOutputPin, + P: OutputPin, { fn is_set_high(&mut self) -> Result { Ok(Self::is_set_high(self)) } + fn is_set_low(&mut self) -> Result { Ok(Self::is_set_low(self)) } } - impl digital::ErrorType for AnyPin, TYPE> { - type Error = core::convert::Infallible; - } - - impl digital::InputPin for AnyPin, TYPE> { + impl<'d, P> digital::InputPin for OutputOpenDrain<'d, P> + where + P: InputPin + OutputPin, + { fn is_high(&mut self) -> Result { - Ok(Self::is_high(self)) + Ok(OutputOpenDrain::is_high(self)) } fn is_low(&mut self) -> Result { - Ok(Self::is_low(self)) + Ok(OutputOpenDrain::is_low(self)) } } - impl digital::ErrorType for AnyPin, TYPE> { + impl<'d, P> digital::ErrorType for OutputOpenDrain<'d, P> + where + P: InputPin + OutputPin, + { type Error = core::convert::Infallible; } - impl digital::OutputPin for AnyPin, TYPE> { + impl<'d, P> digital::OutputPin for OutputOpenDrain<'d, P> + where + P: InputPin + OutputPin, + { fn set_low(&mut self) -> Result<(), Self::Error> { self.set_low(); Ok(()) @@ -2671,7 +2702,76 @@ mod embedded_hal_impls { } } - impl digital::StatefulOutputPin for AnyPin, TYPE> { + impl<'d, P> digital::StatefulOutputPin for OutputOpenDrain<'d, P> + where + P: InputPin + OutputPin, + { + fn is_set_high(&mut self) -> Result { + Ok(Self::is_set_high(self)) + } + + fn is_set_low(&mut self) -> Result { + Ok(Self::is_set_low(self)) + } + } + + impl<'d> digital::ErrorType for AnyInput<'d> { + type Error = core::convert::Infallible; + } + + impl<'d> digital::InputPin for AnyInput<'d> { + fn is_high(&mut self) -> Result { + Ok(AnyInput::is_high(self)) + } + + fn is_low(&mut self) -> Result { + Ok(AnyInput::is_low(self)) + } + } + + impl<'d> digital::ErrorType for AnyOutput<'d> { + type Error = core::convert::Infallible; + } + + impl<'d> digital::OutputPin for AnyOutput<'d> { + fn set_low(&mut self) -> Result<(), Self::Error> { + self.set_low(); + Ok(()) + } + + fn set_high(&mut self) -> Result<(), Self::Error> { + self.set_high(); + Ok(()) + } + } + + impl<'d> digital::StatefulOutputPin for AnyOutput<'d> { + fn is_set_high(&mut self) -> Result { + Ok(Self::is_set_high(self)) + } + + fn is_set_low(&mut self) -> Result { + Ok(Self::is_set_low(self)) + } + } + + impl<'d> digital::ErrorType for AnyOutputOpenDrain<'d> { + type Error = core::convert::Infallible; + } + + impl<'d> digital::OutputPin for AnyOutputOpenDrain<'d> { + fn set_low(&mut self) -> Result<(), Self::Error> { + self.set_low(); + Ok(()) + } + + fn set_high(&mut self) -> Result<(), Self::Error> { + self.set_high(); + Ok(()) + } + } + + impl<'d> digital::StatefulOutputPin for AnyOutputOpenDrain<'d> { fn is_set_high(&mut self) -> Result { Ok(Self::is_set_high(self)) } @@ -2689,10 +2789,9 @@ mod embedded_hal_async_impls { use super::*; - impl Wait for GpioPin, GPIONUM> + impl<'d, P> Wait for Input<'d, P> where - Self: GpioProperties, - ::PinType: IsInputPin, + P: InputPin, { async fn wait_for_high(&mut self) -> Result<(), Self::Error> { self.wait_for_high().await; @@ -2720,38 +2819,7 @@ mod embedded_hal_async_impls { } } - impl Wait for GpioPin, GPIONUM> - where - Self: GpioProperties, - ::PinType: IsInputPin + IsOutputPin, - { - async fn wait_for_high(&mut self) -> Result<(), Self::Error> { - self.wait_for_high().await; - Ok(()) - } - - async fn wait_for_low(&mut self) -> Result<(), Self::Error> { - self.wait_for_low().await; - Ok(()) - } - - async fn wait_for_rising_edge(&mut self) -> Result<(), Self::Error> { - self.wait_for_rising_edge().await; - Ok(()) - } - - async fn wait_for_falling_edge(&mut self) -> Result<(), Self::Error> { - self.wait_for_falling_edge().await; - Ok(()) - } - - async fn wait_for_any_edge(&mut self) -> Result<(), Self::Error> { - self.wait_for_any_edge().await; - Ok(()) - } - } - - impl embedded_hal_async::digital::Wait for AnyPin, TYPE> { + impl<'d> Wait for AnyInput<'d> { async fn wait_for_high(&mut self) -> Result<(), Self::Error> { self.wait_for_high().await; Ok(()) diff --git a/esp-hal/src/gpio/rtc_io.rs b/esp-hal/src/gpio/rtc_io.rs index 8559bd4f3..51afd5bda 100644 --- a/esp-hal/src/gpio/rtc_io.rs +++ b/esp-hal/src/gpio/rtc_io.rs @@ -17,29 +17,120 @@ //! ```no_run //! let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); //! // configure GPIO 1 as ULP output pin -//! let lp_pin = io.pins.gpio1.into_low_power().into_push_pull_output(); +//! let lp_pin = LowPowerOutput::new(io.pins.gpio1); //! ``` use core::marker::PhantomData; #[cfg(esp32c6)] use super::OpenDrain; -use super::{Floating, Input, Output, PullDown, PullUp, PushPull, Unknown}; +use super::RtcPin; +use crate::into_ref; -/// A GPIO pin configured for low power operation -pub struct LowPowerPin { - pub(crate) private: PhantomData, +/// A GPIO output pin configured for low power operation +pub struct LowPowerOutput<'d, const PIN: u8> { + phantom: PhantomData<&'d ()>, } -/// Configures a pin for use as a low power pin -pub trait IntoLowPowerPin { - /// Convert into low power pin - fn into_low_power(self) -> LowPowerPin; +impl<'d, const PIN: u8> LowPowerOutput<'d, PIN> { + /// Create a new output pin for use by the low-power core + pub fn new

(pin: impl crate::peripheral::Peripheral

+ 'd) -> Self + where + P: super::OutputPin + RtcPin, + { + into_ref!(pin); + pin.rtc_set_config(false, true, crate::gpio::RtcFunction::Rtc); + + let this = Self { + phantom: PhantomData, + }; + this.output_enable(true); + + this + } + + fn output_enable(&self, enable: bool) { + let rtc_io = unsafe { crate::peripherals::RTC_IO::steal() }; + + if enable { + rtc_io + .rtc_gpio_enable_w1ts() + .write(|w| unsafe { w.rtc_gpio_enable_w1ts().bits(1 << PIN) }); + } else { + rtc_io + .enable_w1tc() + .write(|w| unsafe { w.enable_w1tc().bits(1 << PIN) }); + } + } } -impl LowPowerPin { - #[doc(hidden)] - pub fn output_enable(&self, enable: bool) { +/// A GPIO input pin configured for low power operation +pub struct LowPowerInput<'d, const PIN: u8> { + phantom: PhantomData<&'d ()>, +} + +impl<'d, const PIN: u8> LowPowerInput<'d, PIN> { + /// Create a new input pin for use by the low-power core + pub fn new

(pin: impl crate::peripheral::Peripheral

+ 'd) -> Self + where + P: super::InputPin + RtcPin, + { + into_ref!(pin); + pin.rtc_set_config(true, true, crate::gpio::RtcFunction::Rtc); + + let this = Self { + phantom: PhantomData, + }; + this.input_enable(true); + this.pullup_enable(false); + this.pulldown_enable(false); + + this + } + + fn input_enable(&self, enable: bool) { + get_pin_reg(PIN).modify(|_, w| w.fun_ie().bit(enable)); + } + + /// Sets pull-up enable for the pin + pub fn pullup_enable(&self, enable: bool) { + get_pin_reg(PIN).modify(|_, w| w.rue().bit(enable)); + } + + /// Sets pull-down enable for the pin + pub fn pulldown_enable(&self, enable: bool) { + get_pin_reg(PIN).modify(|_, w| w.rde().bit(enable)); + } +} + +/// A GPIO open-drain output pin configured for low power operation +pub struct LowPowerOutputOpenDrain<'d, const PIN: u8> { + phantom: PhantomData<&'d ()>, +} + +impl<'d, const PIN: u8> LowPowerOutputOpenDrain<'d, PIN> { + /// Create a new output pin for use by the low-power core + pub fn new

(pin: impl crate::peripheral::Peripheral

+ 'd) -> Self + where + P: super::InputPin + super::OutputPin + RtcPin, + { + into_ref!(pin); + pin.rtc_set_config(true, true, crate::gpio::RtcFunction::Rtc); + + let this = Self { + phantom: PhantomData, + }; + + this.set_open_drain_output(true); + this.input_enable(true); + this.pullup_enable(true); + this.pulldown_enable(false); + this.output_enable(true); + + this + } + + fn output_enable(&self, enable: bool) { let rtc_io = unsafe { crate::peripherals::RTC_IO::steal() }; if enable { @@ -57,90 +148,22 @@ impl LowPowerPin { get_pin_reg(PIN).modify(|_, w| w.fun_ie().bit(enable)); } - fn pullup_enable(&self, enable: bool) { + /// Sets pull-up enable for the pin + pub fn pullup_enable(&self, enable: bool) { get_pin_reg(PIN).modify(|_, w| w.rue().bit(enable)); } - fn pulldown_enable(&self, enable: bool) { + /// Sets pull-down enable for the pin + pub fn pulldown_enable(&self, enable: bool) { get_pin_reg(PIN).modify(|_, w| w.rde().bit(enable)); } - #[doc(hidden)] - pub fn set_level(&mut self, level: bool) { - let rtc_io = unsafe { &*crate::peripherals::RTC_IO::PTR }; - - if level { - rtc_io - .rtc_gpio_out_w1ts() - .write(|w| unsafe { w.rtc_gpio_out_data_w1ts().bits(1 << PIN) }); - } else { - rtc_io - .rtc_gpio_out_w1tc() - .write(|w| unsafe { w.rtc_gpio_out_data_w1tc().bits(1 << PIN) }); - } - } - - #[doc(hidden)] - pub fn get_level(&self) -> bool { - let rtc_io = unsafe { &*crate::peripherals::RTC_IO::PTR }; - (rtc_io.rtc_gpio_in().read().bits() & 1 << PIN) != 0 - } - - /// Configures the pin as an input with the internal pull-up resistor - /// enabled. - pub fn into_pull_up_input(self) -> LowPowerPin, PIN> { - self.input_enable(true); - self.pullup_enable(true); - self.pulldown_enable(false); - LowPowerPin { - private: PhantomData, - } - } - - /// Configures the pin as an input with the internal pull-down resistor - /// enabled. - pub fn into_pull_down_input(self) -> LowPowerPin, PIN> { - self.input_enable(true); - self.pullup_enable(false); - self.pulldown_enable(true); - LowPowerPin { - private: PhantomData, - } - } - - /// Configures the pin as a floating input pin. - pub fn into_floating_input(self) -> LowPowerPin, PIN> { - self.input_enable(true); - self.pullup_enable(false); - self.pulldown_enable(false); - LowPowerPin { - private: PhantomData, - } - } - - /// Configures the pin as an output pin. - pub fn into_push_pull_output(self) -> LowPowerPin, PIN> { - self.output_enable(true); - LowPowerPin { - private: PhantomData, - } - } - - #[cfg(esp32c6)] - /// Configures the pin as an pullup input and a push pull output pin. - pub fn into_open_drain_output(self) -> LowPowerPin { - self.into_pull_up_input(); - self.into_push_pull_output(); + fn set_open_drain_output(&self, enable: bool) { use crate::peripherals::GPIO; - let gpio = unsafe { &*GPIO::PTR }; - gpio.pin(PIN).modify(|_, w| w.pad_driver().bit(true)); - self.pulldown_enable(false); - - LowPowerPin { - private: PhantomData, - } + gpio.pin(PIN as usize) + .modify(|_, w| w.pad_driver().bit(enable)); } } diff --git a/esp-hal/src/i2c.rs b/esp-hal/src/i2c.rs index 97a2fc75b..76f018a78 100644 --- a/esp-hal/src/i2c.rs +++ b/esp-hal/src/i2c.rs @@ -432,20 +432,32 @@ where }; // avoid SCL/SDA going low during configuration - scl.set_output_high(true); - sda.set_output_high(true); + scl.set_output_high(true, crate::private::Internal); + sda.set_output_high(true, crate::private::Internal); - scl.set_to_open_drain_output() - .enable_input(true) - .internal_pull_up(true) - .connect_peripheral_to_output(i2c.peripheral.scl_output_signal()) - .connect_input_to_peripheral(i2c.peripheral.scl_input_signal()); + scl.set_to_open_drain_output(crate::private::Internal); + scl.enable_input(true, crate::private::Internal); + scl.internal_pull_up(true, crate::private::Internal); + scl.connect_peripheral_to_output( + i2c.peripheral.scl_output_signal(), + crate::private::Internal, + ); + scl.connect_input_to_peripheral( + i2c.peripheral.scl_input_signal(), + crate::private::Internal, + ); - sda.set_to_open_drain_output() - .enable_input(true) - .internal_pull_up(true) - .connect_peripheral_to_output(i2c.peripheral.sda_output_signal()) - .connect_input_to_peripheral(i2c.peripheral.sda_input_signal()); + sda.set_to_open_drain_output(crate::private::Internal); + sda.enable_input(true, crate::private::Internal); + sda.internal_pull_up(true, crate::private::Internal); + sda.connect_peripheral_to_output( + i2c.peripheral.sda_output_signal(), + crate::private::Internal, + ); + sda.connect_input_to_peripheral( + i2c.peripheral.sda_input_signal(), + crate::private::Internal, + ); i2c.peripheral.setup(frequency, clocks, timeout); @@ -2017,7 +2029,7 @@ pub mod lp_i2c { use fugit::HertzU32; use crate::{ - gpio::{lp_io::LowPowerPin, OpenDrain}, + gpio::lp_io::LowPowerOutputOpenDrain, peripherals::{LP_CLKRST, LP_I2C0}, }; @@ -2217,8 +2229,8 @@ pub mod lp_i2c { impl LpI2c { pub fn new( i2c: LP_I2C0, - _sda: LowPowerPin, - _scl: LowPowerPin, + _sda: LowPowerOutputOpenDrain<6>, + _scl: LowPowerOutputOpenDrain<7>, frequency: HertzU32, ) -> Self { let me = Self { i2c }; diff --git a/esp-hal/src/i2s.rs b/esp-hal/src/i2s.rs index 8a2c4fa67..45aa9ef51 100644 --- a/esp-hal/src/i2s.rs +++ b/esp-hal/src/i2s.rs @@ -578,8 +578,8 @@ where pub fn with_mclk(self, pin: impl Peripheral

+ 'd) -> Self { into_ref!(pin); - pin.set_to_push_pull_output() - .connect_peripheral_to_output(I::mclk_signal()); + pin.set_to_push_pull_output(crate::private::Internal); + pin.connect_peripheral_to_output(I::mclk_signal(), crate::private::Internal); self } } @@ -907,6 +907,7 @@ mod private { interrupt::InterruptHandler, into_ref, peripherals::I2S0, + private, system::Peripheral, Mode, }; @@ -937,8 +938,8 @@ mod private { P: OutputPin, { into_ref!(pin); - pin.set_to_push_pull_output() - .connect_peripheral_to_output(T::bclk_signal()); + pin.set_to_push_pull_output(private::Internal); + pin.connect_peripheral_to_output(T::bclk_signal(), private::Internal); self } @@ -947,8 +948,8 @@ mod private { P: OutputPin, { into_ref!(pin); - pin.set_to_push_pull_output() - .connect_peripheral_to_output(T::ws_signal()); + pin.set_to_push_pull_output(private::Internal); + pin.connect_peripheral_to_output(T::ws_signal(), private::Internal); self } @@ -957,8 +958,8 @@ mod private { P: OutputPin, { into_ref!(pin); - pin.set_to_push_pull_output() - .connect_peripheral_to_output(T::dout_signal()); + pin.set_to_push_pull_output(private::Internal); + pin.connect_peripheral_to_output(T::dout_signal(), private::Internal); self } } @@ -989,8 +990,8 @@ mod private { P: OutputPin, { into_ref!(pin); - pin.set_to_push_pull_output() - .connect_peripheral_to_output(T::bclk_rx_signal()); + pin.set_to_push_pull_output(crate::private::Internal); + pin.connect_peripheral_to_output(T::bclk_rx_signal(), crate::private::Internal); self } @@ -999,8 +1000,8 @@ mod private { P: OutputPin, { into_ref!(pin); - pin.set_to_push_pull_output() - .connect_peripheral_to_output(T::ws_rx_signal()); + pin.set_to_push_pull_output(crate::private::Internal); + pin.connect_peripheral_to_output(T::ws_rx_signal(), crate::private::Internal); self } @@ -1009,8 +1010,8 @@ mod private { P: InputPin, { into_ref!(pin); - pin.set_to_input() - .connect_input_to_peripheral(T::din_signal()); + pin.set_to_input(crate::private::Internal); + pin.connect_input_to_peripheral(T::din_signal(), crate::private::Internal); self } } diff --git a/esp-hal/src/lcd_cam/cam.rs b/esp-hal/src/lcd_cam/cam.rs index c27ee4ea9..98da53c8a 100644 --- a/esp-hal/src/lcd_cam/cam.rs +++ b/esp-hal/src/lcd_cam/cam.rs @@ -221,8 +221,8 @@ impl<'d, RX: Rx> Camera<'d, RX> { pub fn with_master_clock(self, mclk: impl Peripheral

+ 'd) -> Self { crate::into_ref!(mclk); - mclk.set_to_push_pull_output() - .connect_peripheral_to_output(OutputSignal::CAM_CLK); + mclk.set_to_push_pull_output(crate::private::Internal); + mclk.connect_peripheral_to_output(OutputSignal::CAM_CLK, crate::private::Internal); self } @@ -236,14 +236,12 @@ impl<'d, RX: Rx> Camera<'d, RX> { crate::into_ref!(h_enable); crate::into_ref!(pclk); - vsync - .set_to_input() - .connect_input_to_peripheral(InputSignal::CAM_V_SYNC); - h_enable - .set_to_input() - .connect_input_to_peripheral(InputSignal::CAM_H_ENABLE); - pclk.set_to_input() - .connect_input_to_peripheral(InputSignal::CAM_PCLK); + vsync.set_to_input(crate::private::Internal); + vsync.connect_input_to_peripheral(InputSignal::CAM_V_SYNC, crate::private::Internal); + h_enable.set_to_input(crate::private::Internal); + h_enable.connect_input_to_peripheral(InputSignal::CAM_H_ENABLE, crate::private::Internal); + pclk.set_to_input(crate::private::Internal); + pclk.connect_input_to_peripheral(InputSignal::CAM_PCLK, crate::private::Internal); self } @@ -425,30 +423,22 @@ impl RxEightBits { crate::into_ref!(pin_6); crate::into_ref!(pin_7); - pin_0 - .set_to_input() - .connect_input_to_peripheral(InputSignal::CAM_DATA_0); - pin_1 - .set_to_input() - .connect_input_to_peripheral(InputSignal::CAM_DATA_1); - pin_2 - .set_to_input() - .connect_input_to_peripheral(InputSignal::CAM_DATA_2); - pin_3 - .set_to_input() - .connect_input_to_peripheral(InputSignal::CAM_DATA_3); - pin_4 - .set_to_input() - .connect_input_to_peripheral(InputSignal::CAM_DATA_4); - pin_5 - .set_to_input() - .connect_input_to_peripheral(InputSignal::CAM_DATA_5); - pin_6 - .set_to_input() - .connect_input_to_peripheral(InputSignal::CAM_DATA_6); - pin_7 - .set_to_input() - .connect_input_to_peripheral(InputSignal::CAM_DATA_7); + pin_0.set_to_input(crate::private::Internal); + pin_0.connect_input_to_peripheral(InputSignal::CAM_DATA_0, crate::private::Internal); + pin_1.set_to_input(crate::private::Internal); + pin_1.connect_input_to_peripheral(InputSignal::CAM_DATA_1, crate::private::Internal); + pin_2.set_to_input(crate::private::Internal); + pin_2.connect_input_to_peripheral(InputSignal::CAM_DATA_2, crate::private::Internal); + pin_3.set_to_input(crate::private::Internal); + pin_3.connect_input_to_peripheral(InputSignal::CAM_DATA_3, crate::private::Internal); + pin_4.set_to_input(crate::private::Internal); + pin_4.connect_input_to_peripheral(InputSignal::CAM_DATA_4, crate::private::Internal); + pin_5.set_to_input(crate::private::Internal); + pin_5.connect_input_to_peripheral(InputSignal::CAM_DATA_5, crate::private::Internal); + pin_6.set_to_input(crate::private::Internal); + pin_6.connect_input_to_peripheral(InputSignal::CAM_DATA_6, crate::private::Internal); + pin_7.set_to_input(crate::private::Internal); + pin_7.connect_input_to_peripheral(InputSignal::CAM_DATA_7, crate::private::Internal); Self { _pins: () } } @@ -517,54 +507,38 @@ impl RxSixteenBits { crate::into_ref!(pin_14); crate::into_ref!(pin_15); - pin_0 - .set_to_input() - .connect_input_to_peripheral(InputSignal::CAM_DATA_0); - pin_1 - .set_to_input() - .connect_input_to_peripheral(InputSignal::CAM_DATA_1); - pin_2 - .set_to_input() - .connect_input_to_peripheral(InputSignal::CAM_DATA_2); - pin_3 - .set_to_input() - .connect_input_to_peripheral(InputSignal::CAM_DATA_3); - pin_4 - .set_to_input() - .connect_input_to_peripheral(InputSignal::CAM_DATA_4); - pin_5 - .set_to_input() - .connect_input_to_peripheral(InputSignal::CAM_DATA_5); - pin_6 - .set_to_input() - .connect_input_to_peripheral(InputSignal::CAM_DATA_6); - pin_7 - .set_to_input() - .connect_input_to_peripheral(InputSignal::CAM_DATA_7); - pin_8 - .set_to_input() - .connect_input_to_peripheral(InputSignal::CAM_DATA_8); - pin_9 - .set_to_input() - .connect_input_to_peripheral(InputSignal::CAM_DATA_9); - pin_10 - .set_to_input() - .connect_input_to_peripheral(InputSignal::CAM_DATA_10); - pin_11 - .set_to_input() - .connect_input_to_peripheral(InputSignal::CAM_DATA_11); - pin_12 - .set_to_input() - .connect_input_to_peripheral(InputSignal::CAM_DATA_12); - pin_13 - .set_to_input() - .connect_input_to_peripheral(InputSignal::CAM_DATA_13); - pin_14 - .set_to_input() - .connect_input_to_peripheral(InputSignal::CAM_DATA_14); - pin_15 - .set_to_input() - .connect_input_to_peripheral(InputSignal::CAM_DATA_15); + pin_0.set_to_input(crate::private::Internal); + pin_0.connect_input_to_peripheral(InputSignal::CAM_DATA_0, crate::private::Internal); + pin_1.set_to_input(crate::private::Internal); + pin_1.connect_input_to_peripheral(InputSignal::CAM_DATA_1, crate::private::Internal); + pin_2.set_to_input(crate::private::Internal); + pin_2.connect_input_to_peripheral(InputSignal::CAM_DATA_2, crate::private::Internal); + pin_3.set_to_input(crate::private::Internal); + pin_3.connect_input_to_peripheral(InputSignal::CAM_DATA_3, crate::private::Internal); + pin_4.set_to_input(crate::private::Internal); + pin_4.connect_input_to_peripheral(InputSignal::CAM_DATA_4, crate::private::Internal); + pin_5.set_to_input(crate::private::Internal); + pin_5.connect_input_to_peripheral(InputSignal::CAM_DATA_5, crate::private::Internal); + pin_6.set_to_input(crate::private::Internal); + pin_6.connect_input_to_peripheral(InputSignal::CAM_DATA_6, crate::private::Internal); + pin_7.set_to_input(crate::private::Internal); + pin_7.connect_input_to_peripheral(InputSignal::CAM_DATA_7, crate::private::Internal); + pin_8.set_to_input(crate::private::Internal); + pin_8.connect_input_to_peripheral(InputSignal::CAM_DATA_8, crate::private::Internal); + pin_9.set_to_input(crate::private::Internal); + pin_9.connect_input_to_peripheral(InputSignal::CAM_DATA_9, crate::private::Internal); + pin_10.set_to_input(crate::private::Internal); + pin_10.connect_input_to_peripheral(InputSignal::CAM_DATA_10, crate::private::Internal); + pin_11.set_to_input(crate::private::Internal); + pin_11.connect_input_to_peripheral(InputSignal::CAM_DATA_11, crate::private::Internal); + pin_12.set_to_input(crate::private::Internal); + pin_12.connect_input_to_peripheral(InputSignal::CAM_DATA_12, crate::private::Internal); + pin_13.set_to_input(crate::private::Internal); + pin_13.connect_input_to_peripheral(InputSignal::CAM_DATA_13, crate::private::Internal); + pin_14.set_to_input(crate::private::Internal); + pin_14.connect_input_to_peripheral(InputSignal::CAM_DATA_14, crate::private::Internal); + pin_15.set_to_input(crate::private::Internal); + pin_15.connect_input_to_peripheral(InputSignal::CAM_DATA_15, crate::private::Internal); Self { _pins: () } } diff --git a/esp-hal/src/lcd_cam/lcd/i8080.rs b/esp-hal/src/lcd_cam/lcd/i8080.rs index 895ddc543..855fcaab5 100644 --- a/esp-hal/src/lcd_cam/lcd/i8080.rs +++ b/esp-hal/src/lcd_cam/lcd/i8080.rs @@ -254,8 +254,8 @@ where pub fn with_cs(self, cs: impl Peripheral

+ 'd) -> Self { crate::into_ref!(cs); - cs.set_to_push_pull_output() - .connect_peripheral_to_output(OutputSignal::LCD_CS); + cs.set_to_push_pull_output(crate::private::Internal); + cs.connect_peripheral_to_output(OutputSignal::LCD_CS, crate::private::Internal); self } @@ -268,11 +268,11 @@ where crate::into_ref!(dc); crate::into_ref!(wrx); - dc.set_to_push_pull_output() - .connect_peripheral_to_output(OutputSignal::LCD_DC); + dc.set_to_push_pull_output(crate::private::Internal); + dc.connect_peripheral_to_output(OutputSignal::LCD_DC, crate::private::Internal); - wrx.set_to_push_pull_output() - .connect_peripheral_to_output(OutputSignal::LCD_PCLK); + wrx.set_to_push_pull_output(crate::private::Internal); + wrx.connect_peripheral_to_output(OutputSignal::LCD_PCLK, crate::private::Internal); self } @@ -610,30 +610,30 @@ where type Word = u8; fn configure(&mut self) { + self.pin_0.set_to_push_pull_output(crate::private::Internal); self.pin_0 - .set_to_push_pull_output() - .connect_peripheral_to_output(OutputSignal::LCD_DATA_0); + .connect_peripheral_to_output(OutputSignal::LCD_DATA_0, crate::private::Internal); + self.pin_1.set_to_push_pull_output(crate::private::Internal); self.pin_1 - .set_to_push_pull_output() - .connect_peripheral_to_output(OutputSignal::LCD_DATA_1); + .connect_peripheral_to_output(OutputSignal::LCD_DATA_1, crate::private::Internal); + self.pin_2.set_to_push_pull_output(crate::private::Internal); self.pin_2 - .set_to_push_pull_output() - .connect_peripheral_to_output(OutputSignal::LCD_DATA_2); + .connect_peripheral_to_output(OutputSignal::LCD_DATA_2, crate::private::Internal); + self.pin_3.set_to_push_pull_output(crate::private::Internal); self.pin_3 - .set_to_push_pull_output() - .connect_peripheral_to_output(OutputSignal::LCD_DATA_3); + .connect_peripheral_to_output(OutputSignal::LCD_DATA_3, crate::private::Internal); + self.pin_4.set_to_push_pull_output(crate::private::Internal); self.pin_4 - .set_to_push_pull_output() - .connect_peripheral_to_output(OutputSignal::LCD_DATA_4); + .connect_peripheral_to_output(OutputSignal::LCD_DATA_4, crate::private::Internal); + self.pin_5.set_to_push_pull_output(crate::private::Internal); self.pin_5 - .set_to_push_pull_output() - .connect_peripheral_to_output(OutputSignal::LCD_DATA_5); + .connect_peripheral_to_output(OutputSignal::LCD_DATA_5, crate::private::Internal); + self.pin_6.set_to_push_pull_output(crate::private::Internal); self.pin_6 - .set_to_push_pull_output() - .connect_peripheral_to_output(OutputSignal::LCD_DATA_6); + .connect_peripheral_to_output(OutputSignal::LCD_DATA_6, crate::private::Internal); + self.pin_7.set_to_push_pull_output(crate::private::Internal); self.pin_7 - .set_to_push_pull_output() - .connect_peripheral_to_output(OutputSignal::LCD_DATA_7); + .connect_peripheral_to_output(OutputSignal::LCD_DATA_7, crate::private::Internal); } } @@ -755,54 +755,60 @@ where { type Word = u16; fn configure(&mut self) { + self.pin_0.set_to_push_pull_output(crate::private::Internal); self.pin_0 - .set_to_push_pull_output() - .connect_peripheral_to_output(OutputSignal::LCD_DATA_0); + .connect_peripheral_to_output(OutputSignal::LCD_DATA_0, crate::private::Internal); + self.pin_1.set_to_push_pull_output(crate::private::Internal); self.pin_1 - .set_to_push_pull_output() - .connect_peripheral_to_output(OutputSignal::LCD_DATA_1); + .connect_peripheral_to_output(OutputSignal::LCD_DATA_1, crate::private::Internal); + self.pin_2.set_to_push_pull_output(crate::private::Internal); self.pin_2 - .set_to_push_pull_output() - .connect_peripheral_to_output(OutputSignal::LCD_DATA_2); + .connect_peripheral_to_output(OutputSignal::LCD_DATA_2, crate::private::Internal); + self.pin_3.set_to_push_pull_output(crate::private::Internal); self.pin_3 - .set_to_push_pull_output() - .connect_peripheral_to_output(OutputSignal::LCD_DATA_3); + .connect_peripheral_to_output(OutputSignal::LCD_DATA_3, crate::private::Internal); + self.pin_4.set_to_push_pull_output(crate::private::Internal); self.pin_4 - .set_to_push_pull_output() - .connect_peripheral_to_output(OutputSignal::LCD_DATA_4); + .connect_peripheral_to_output(OutputSignal::LCD_DATA_4, crate::private::Internal); + self.pin_5.set_to_push_pull_output(crate::private::Internal); self.pin_5 - .set_to_push_pull_output() - .connect_peripheral_to_output(OutputSignal::LCD_DATA_5); + .connect_peripheral_to_output(OutputSignal::LCD_DATA_5, crate::private::Internal); + self.pin_6.set_to_push_pull_output(crate::private::Internal); self.pin_6 - .set_to_push_pull_output() - .connect_peripheral_to_output(OutputSignal::LCD_DATA_6); + .connect_peripheral_to_output(OutputSignal::LCD_DATA_6, crate::private::Internal); + self.pin_7.set_to_push_pull_output(crate::private::Internal); self.pin_7 - .set_to_push_pull_output() - .connect_peripheral_to_output(OutputSignal::LCD_DATA_7); + .connect_peripheral_to_output(OutputSignal::LCD_DATA_7, crate::private::Internal); + self.pin_8.set_to_push_pull_output(crate::private::Internal); self.pin_8 - .set_to_push_pull_output() - .connect_peripheral_to_output(OutputSignal::LCD_DATA_8); + .connect_peripheral_to_output(OutputSignal::LCD_DATA_8, crate::private::Internal); + self.pin_9.set_to_push_pull_output(crate::private::Internal); self.pin_9 - .set_to_push_pull_output() - .connect_peripheral_to_output(OutputSignal::LCD_DATA_9); + .connect_peripheral_to_output(OutputSignal::LCD_DATA_9, crate::private::Internal); self.pin_10 - .set_to_push_pull_output() - .connect_peripheral_to_output(OutputSignal::LCD_DATA_10); + .set_to_push_pull_output(crate::private::Internal); + self.pin_10 + .connect_peripheral_to_output(OutputSignal::LCD_DATA_10, crate::private::Internal); self.pin_11 - .set_to_push_pull_output() - .connect_peripheral_to_output(OutputSignal::LCD_DATA_11); + .set_to_push_pull_output(crate::private::Internal); + self.pin_11 + .connect_peripheral_to_output(OutputSignal::LCD_DATA_11, crate::private::Internal); self.pin_12 - .set_to_push_pull_output() - .connect_peripheral_to_output(OutputSignal::LCD_DATA_12); + .set_to_push_pull_output(crate::private::Internal); + self.pin_12 + .connect_peripheral_to_output(OutputSignal::LCD_DATA_12, crate::private::Internal); self.pin_13 - .set_to_push_pull_output() - .connect_peripheral_to_output(OutputSignal::LCD_DATA_13); + .set_to_push_pull_output(crate::private::Internal); + self.pin_13 + .connect_peripheral_to_output(OutputSignal::LCD_DATA_13, crate::private::Internal); self.pin_14 - .set_to_push_pull_output() - .connect_peripheral_to_output(OutputSignal::LCD_DATA_14); + .set_to_push_pull_output(crate::private::Internal); + self.pin_14 + .connect_peripheral_to_output(OutputSignal::LCD_DATA_14, crate::private::Internal); self.pin_15 - .set_to_push_pull_output() - .connect_peripheral_to_output(OutputSignal::LCD_DATA_15); + .set_to_push_pull_output(crate::private::Internal); + self.pin_15 + .connect_peripheral_to_output(OutputSignal::LCD_DATA_15, crate::private::Internal); } } diff --git a/esp-hal/src/ledc/channel.rs b/esp-hal/src/ledc/channel.rs index 72fcc0cea..53e0a727a 100644 --- a/esp-hal/src/ledc/channel.rs +++ b/esp-hal/src/ledc/channel.rs @@ -536,8 +536,12 @@ where } match cfg { - config::PinConfig::PushPull => self.output_pin.set_to_push_pull_output(), - config::PinConfig::OpenDrain => self.output_pin.set_to_open_drain_output(), + config::PinConfig::PushPull => self + .output_pin + .set_to_push_pull_output(crate::private::Internal), + config::PinConfig::OpenDrain => self + .output_pin + .set_to_open_drain_output(crate::private::Internal), }; let timer_number = timer.get_number() as u8; @@ -585,7 +589,8 @@ where #[cfg(not(any(esp32c2, esp32c3, esp32c6, esp32h2)))] Number::Channel7 => OutputSignal::LEDC_LS_SIG7, }; - self.output_pin.connect_peripheral_to_output(signal); + self.output_pin + .connect_peripheral_to_output(signal, crate::private::Internal); } else { return Err(Error::Timer); } diff --git a/esp-hal/src/lib.rs b/esp-hal/src/lib.rs index 9f9cabaa0..eaca683c5 100644 --- a/esp-hal/src/lib.rs +++ b/esp-hal/src/lib.rs @@ -220,6 +220,8 @@ impl crate::private::Sealed for Async {} pub(crate) mod private { pub trait Sealed {} + + pub struct Internal; } /// Available CPU cores diff --git a/esp-hal/src/mcpwm/mod.rs b/esp-hal/src/mcpwm/mod.rs index 0b024a716..dbc3bcb6f 100644 --- a/esp-hal/src/mcpwm/mod.rs +++ b/esp-hal/src/mcpwm/mod.rs @@ -34,7 +34,7 @@ //! //! ```no_run //! # use esp_hal::{mcpwm, prelude::*}; -//! use mcpwm::{operator::PwmPinConfig, timer::PwmWorkingMode, PeripheralClockConfig, MCPWM}; +//! use mcpwm::{operator::PwmPinConfig, timer::PwmWorkingMode, McPwm, PeripheralClockConfig}; //! //! // initialize peripheral //! let clock_cfg = PeripheralClockConfig::with_frequency(&clocks, 40.MHz()).unwrap(); diff --git a/esp-hal/src/mcpwm/operator.rs b/esp-hal/src/mcpwm/operator.rs index e6c4f2f7d..5fe4e0193 100644 --- a/esp-hal/src/mcpwm/operator.rs +++ b/esp-hal/src/mcpwm/operator.rs @@ -16,6 +16,7 @@ use crate::{ gpio::OutputPin, mcpwm::{timer::Timer, PwmPeripheral}, peripheral::{Peripheral, PeripheralRef}, + private, }; /// Input/Output Stream descriptor for each channel @@ -302,8 +303,8 @@ impl<'d, Pin: OutputPin, PWM: PwmPeripheral, const OP: u8, const IS_A: bool> let output_signal = PWM::output_signal::(); pin.pin - .connect_peripheral_to_output(output_signal) - .enable_output(true); + .connect_peripheral_to_output(output_signal, private::Internal); + pin.pin.enable_output(true, private::Internal); pin } diff --git a/esp-hal/src/parl_io.rs b/esp-hal/src/parl_io.rs index c8fdc837c..43526f93c 100644 --- a/esp-hal/src/parl_io.rs +++ b/esp-hal/src/parl_io.rs @@ -331,9 +331,11 @@ where P: OutputPin, { fn configure(&mut self) { - self.pin - .set_to_push_pull_output() - .connect_peripheral_to_output(crate::gpio::OutputSignal::PARL_TX_CLK); + self.pin.set_to_push_pull_output(crate::private::Internal); + self.pin.connect_peripheral_to_output( + crate::gpio::OutputSignal::PARL_TX_CLK, + crate::private::Internal, + ); } } @@ -363,9 +365,11 @@ where pcr.parl_clk_tx_conf() .modify(|_, w| unsafe { w.parl_clk_tx_sel().bits(3).parl_clk_tx_div_num().bits(0) }); // PAD_CLK_TX, no divider - self.pin - .set_to_input() - .connect_input_to_peripheral(crate::gpio::InputSignal::PARL_TX_CLK); + self.pin.set_to_input(crate::private::Internal); + self.pin.connect_input_to_peripheral( + crate::gpio::InputSignal::PARL_TX_CLK, + crate::private::Internal, + ); } } @@ -396,9 +400,11 @@ where pcr.parl_clk_rx_conf() .modify(|_, w| unsafe { w.parl_clk_rx_sel().bits(3).parl_clk_rx_div_num().bits(0) }); // PAD_CLK_TX, no divider - self.pin - .set_to_input() - .connect_input_to_peripheral(crate::gpio::InputSignal::PARL_RX_CLK); + self.pin.set_to_input(crate::private::Internal); + self.pin.connect_input_to_peripheral( + crate::gpio::InputSignal::PARL_RX_CLK, + crate::private::Internal, + ); Instance::set_rx_clk_edge_sel(self.sample_edge); } @@ -441,8 +447,11 @@ where fn configure(&mut self) -> Result<(), Error> { self.tx_pins.configure()?; self.valid_pin - .set_to_push_pull_output() - .connect_peripheral_to_output(Instance::tx_valid_pin_signal()); + .set_to_push_pull_output(crate::private::Internal); + self.valid_pin.connect_peripheral_to_output( + Instance::tx_valid_pin_signal(), + crate::private::Internal, + ); Instance::set_tx_hw_valid_en(true); Ok(()) } @@ -516,9 +525,8 @@ macro_rules! tx_pins { { fn configure(&mut self) -> Result<(), Error>{ $( - self.[< pin_ $pin:lower >] - .set_to_push_pull_output() - .connect_peripheral_to_output(crate::gpio::OutputSignal::$signal); + self.[< pin_ $pin:lower >].set_to_push_pull_output(crate::private::Internal); + self.[< pin_ $pin:lower >].connect_peripheral_to_output(crate::gpio::OutputSignal::$signal, crate::private::Internal); )+ private::Instance::set_tx_bit_width( private::WidSel::[< Bits $width >]); @@ -659,9 +667,9 @@ where { fn configure(&mut self) -> Result<(), Error> { self.rx_pins.configure()?; + self.valid_pin.set_to_input(crate::private::Internal); self.valid_pin - .set_to_input() - .connect_input_to_peripheral(Instance::rx_valid_pin_signal()); + .connect_input_to_peripheral(Instance::rx_valid_pin_signal(), crate::private::Internal); Instance::set_rx_sw_en(false); if let Some(sel) = self.enable_mode.pulse_submode_sel() { Instance::set_rx_pulse_submode_sel(sel); @@ -763,9 +771,8 @@ macro_rules! rx_pins { { fn configure(&mut self) -> Result<(), Error> { $( - self.[< pin_ $pin:lower >] - .set_to_input() - .connect_input_to_peripheral(crate::gpio::InputSignal::$signal); + self.[< pin_ $pin:lower >].set_to_input($crate::private::Internal); + self.[< pin_ $pin:lower >].connect_input_to_peripheral(crate::gpio::InputSignal::$signal, $crate::private::Internal); )+ private::Instance::set_rx_bit_width( private::WidSel::[< Bits $width >]); diff --git a/esp-hal/src/pcnt/channel.rs b/esp-hal/src/pcnt/channel.rs index a9b6d17aa..47f25dafc 100644 --- a/esp-hal/src/pcnt/channel.rs +++ b/esp-hal/src/pcnt/channel.rs @@ -10,11 +10,25 @@ use super::unit; use crate::{ - gpio::{InputPin, InputSignal, ONE_INPUT, ZERO_INPUT}, + gpio::{InputPin, InputSignal, Pull, ONE_INPUT, ZERO_INPUT}, peripheral::Peripheral, peripherals::GPIO, }; +/// Configuration for an PCNT input pin +#[derive(Clone, Copy, Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub struct PcntInputConfig { + /// Configuration for the internal pull-up resistors + pub pull: Pull, +} + +impl Default for PcntInputConfig { + fn default() -> Self { + Self { pull: Pull::None } + } +} + /// Channel number #[derive(PartialEq, Eq, Copy, Clone, Debug)] pub enum Number { @@ -59,10 +73,20 @@ pub struct PcntSource { } impl PcntSource { - pub fn from_pin<'a, P: InputPin>(pin: impl Peripheral

+ 'a) -> Self { + pub fn from_pin<'a, P: InputPin>( + pin: impl Peripheral

+ 'a, + pin_config: PcntInputConfig, + ) -> Self { crate::into_ref!(pin); + + pin.init_input( + pin_config.pull == Pull::Down, + pin_config.pull == Pull::Up, + crate::private::Internal, + ); + Self { - source: pin.number(), + source: pin.number(crate::private::Internal), } } pub fn always_high() -> Self { diff --git a/esp-hal/src/pcnt/mod.rs b/esp-hal/src/pcnt/mod.rs index 844f7d7b1..a71978dc3 100644 --- a/esp-hal/src/pcnt/mod.rs +++ b/esp-hal/src/pcnt/mod.rs @@ -47,12 +47,12 @@ //! println!("setup channel 0"); //! let mut ch0 = u0.get_channel(channel::Number::Channel0); //! let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); -//! let mut pin_a = io.pins.gpio5.into_pull_up_input(); -//! let mut pin_b = io.pins.gpio6.into_pull_up_input(); +//! let mut pin_a = io.pins.gpio5; +//! let mut pin_b = io.pins.gpio6; //! //! ch0.configure( -//! PcntSource::from_pin(&mut pin_a), -//! PcntSource::from_pin(&mut pin_b), +//! PcntSource::from_pin(&mut pin_a, PcntInputConfig { pull: Pull::Up }), +//! PcntSource::from_pin(&mut pin_b, PcntInputConfig { pull: Pull::Up }), //! channel::Config { //! lctrl_mode: channel::CtrlMode::Reverse, //! hctrl_mode: channel::CtrlMode::Keep, @@ -66,8 +66,8 @@ //! println!("setup channel 1"); //! let mut ch1 = u0.get_channel(channel::Number::Channel1); //! ch1.configure( -//! PcntSource::from_pin(&mut pin_b), -//! PcntSource::from_pin(&mut pin_a), +//! PcntSource::from_pin(&mut pin_b, PcntInputConfig { pull: Pull::Up }), +//! PcntSource::from_pin(&mut pin_a, PcntInputConfig { pull: Pull::Up }), //! channel::Config { //! lctrl_mode: channel::CtrlMode::Reverse, //! hctrl_mode: channel::CtrlMode::Keep, diff --git a/esp-hal/src/rmt.rs b/esp-hal/src/rmt.rs index 70d098982..419f18248 100644 --- a/esp-hal/src/rmt.rs +++ b/esp-hal/src/rmt.rs @@ -317,8 +317,8 @@ where Self: Sized, { crate::into_ref!(pin); - pin.set_to_push_pull_output() - .connect_peripheral_to_output(T::output_signal()); + pin.set_to_push_pull_output(crate::private::Internal); + pin.connect_peripheral_to_output(T::output_signal(), crate::private::Internal); T::set_divider(config.clk_divider); T::set_carrier( config.carrier_modulation, @@ -349,8 +349,8 @@ where Self: Sized, { crate::into_ref!(pin); - pin.set_to_push_pull_output() - .connect_peripheral_to_output(T::output_signal()); + pin.set_to_push_pull_output(crate::private::Internal); + pin.connect_peripheral_to_output(T::output_signal(), crate::private::Internal); T::set_divider(config.clk_divider); T::set_carrier( config.carrier_modulation, @@ -394,8 +394,8 @@ where } crate::into_ref!(pin); - pin.set_to_input() - .connect_input_to_peripheral(T::input_signal()); + pin.set_to_input(crate::private::Internal); + pin.connect_input_to_peripheral(T::input_signal(), crate::private::Internal); T::set_divider(config.clk_divider); T::set_carrier( config.carrier_modulation, @@ -441,8 +441,8 @@ where } crate::into_ref!(pin); - pin.set_to_input() - .connect_input_to_peripheral(T::input_signal()); + pin.set_to_input(crate::private::Internal); + pin.connect_input_to_peripheral(T::input_signal(), crate::private::Internal); T::set_divider(config.clk_divider); T::set_carrier( config.carrier_modulation, diff --git a/esp-hal/src/rtc_cntl/sleep/esp32c6.rs b/esp-hal/src/rtc_cntl/sleep/esp32c6.rs index 26c924ba7..703da0db8 100644 --- a/esp-hal/src/rtc_cntl/sleep/esp32c6.rs +++ b/esp-hal/src/rtc_cntl/sleep/esp32c6.rs @@ -5,6 +5,7 @@ use crate::{ efuse::Efuse, gpio::{Pins, RtcFunction}, peripherals::Peripherals, + private, rtc_cntl::{ rtc::{ rtc_clk_cpu_freq_set_xtal, @@ -64,7 +65,7 @@ impl Ext1WakeupSource<'_, '_> { use crate::gpio::RtcPin; fn uninit_pin(pin: &mut impl RtcPin, wakeup_pins: u8) { - if wakeup_pins & (1 << pin.number()) != 0 { + if wakeup_pins & (1 << pin.number(private::Internal)) != 0 { pin.rtcio_pad_hold(false); pin.rtc_set_config(false, false, RtcFunction::Rtc); } @@ -92,9 +93,9 @@ impl WakeSource for Ext1WakeupSource<'_, '_> { let mut pin_mask = 0u8; let mut level_mask = 0u8; for (pin, level) in pins.iter_mut() { - pin_mask |= 1 << pin.number(); + pin_mask |= 1 << pin.number(private::Internal); level_mask |= match level { - WakeupLevel::High => 1 << pin.number(), + WakeupLevel::High => 1 << pin.number(private::Internal), WakeupLevel::Low => 0, }; diff --git a/esp-hal/src/rtc_cntl/sleep/esp32s3.rs b/esp-hal/src/rtc_cntl/sleep/esp32s3.rs index 13760c0ba..de58c1f7e 100644 --- a/esp-hal/src/rtc_cntl/sleep/esp32s3.rs +++ b/esp-hal/src/rtc_cntl/sleep/esp32s3.rs @@ -197,12 +197,14 @@ impl<'a, 'b> RtcioWakeupSource<'a, 'b> { pin.rtc_set_config(true, true, RtcFunction::Rtc); - rtcio.pin(pin.number() as usize).modify(|_, w| unsafe { - w.wakeup_enable().set_bit().int_type().bits(match level { - WakeupLevel::Low => 4, - WakeupLevel::High => 5, - }) - }); + rtcio + .pin(pin.number(crate::private::Internal) as usize) + .modify(|_, w| unsafe { + w.wakeup_enable().set_bit().int_type().bits(match level { + WakeupLevel::Low => 4, + WakeupLevel::High => 5, + }) + }); } } diff --git a/esp-hal/src/soc/esp32/gpio.rs b/esp-hal/src/soc/esp32/gpio.rs index 5f6314e78..1cd29c131 100644 --- a/esp-hal/src/soc/esp32/gpio.rs +++ b/esp-hal/src/soc/esp32/gpio.rs @@ -52,7 +52,6 @@ use crate::{ InterruptStatusRegisterAccess, InterruptStatusRegisterAccessBank0, InterruptStatusRegisterAccessBank1, - Unknown, }, peripherals::GPIO, Cpu, diff --git a/esp-hal/src/soc/esp32c2/gpio.rs b/esp-hal/src/soc/esp32c2/gpio.rs index 64ce4c470..41ec6ceea 100644 --- a/esp-hal/src/soc/esp32c2/gpio.rs +++ b/esp-hal/src/soc/esp32c2/gpio.rs @@ -45,7 +45,6 @@ use crate::{ GpioPin, InterruptStatusRegisterAccess, InterruptStatusRegisterAccessBank0, - Unknown, }, peripherals::GPIO, }; diff --git a/esp-hal/src/soc/esp32c3/gpio.rs b/esp-hal/src/soc/esp32c3/gpio.rs index 7a107fbcc..43385fd3c 100644 --- a/esp-hal/src/soc/esp32c3/gpio.rs +++ b/esp-hal/src/soc/esp32c3/gpio.rs @@ -46,7 +46,6 @@ use crate::{ GpioPin, InterruptStatusRegisterAccess, InterruptStatusRegisterAccessBank0, - Unknown, }, peripherals::GPIO, }; diff --git a/esp-hal/src/soc/esp32c6/gpio.rs b/esp-hal/src/soc/esp32c6/gpio.rs index 5479bfb23..8ff8e905f 100644 --- a/esp-hal/src/soc/esp32c6/gpio.rs +++ b/esp-hal/src/soc/esp32c6/gpio.rs @@ -46,7 +46,6 @@ use crate::{ GpioPin, InterruptStatusRegisterAccess, InterruptStatusRegisterAccessBank0, - Unknown, }, peripherals::GPIO, }; diff --git a/esp-hal/src/soc/esp32h2/gpio.rs b/esp-hal/src/soc/esp32h2/gpio.rs index 94af18b5d..a7983809c 100644 --- a/esp-hal/src/soc/esp32h2/gpio.rs +++ b/esp-hal/src/soc/esp32h2/gpio.rs @@ -46,7 +46,6 @@ use crate::{ GpioPin, InterruptStatusRegisterAccess, InterruptStatusRegisterAccessBank0, - Unknown, }, peripherals::GPIO, }; diff --git a/esp-hal/src/soc/esp32s2/gpio.rs b/esp-hal/src/soc/esp32s2/gpio.rs index 0c502b3b2..cdbdaa46e 100644 --- a/esp-hal/src/soc/esp32s2/gpio.rs +++ b/esp-hal/src/soc/esp32s2/gpio.rs @@ -59,7 +59,6 @@ use crate::{ InterruptStatusRegisterAccess, InterruptStatusRegisterAccessBank0, InterruptStatusRegisterAccessBank1, - Unknown, }, peripherals::GPIO, }; @@ -556,5 +555,5 @@ impl InterruptStatusRegisterAccess for InterruptStatusRegisterAccessBank1 { } // implement marker traits on USB pins -impl crate::otg_fs::UsbDp for Gpio19 {} -impl crate::otg_fs::UsbDm for Gpio20 {} +impl crate::otg_fs::UsbDp for Gpio19 {} +impl crate::otg_fs::UsbDm for Gpio20 {} diff --git a/esp-hal/src/soc/esp32s3/gpio.rs b/esp-hal/src/soc/esp32s3/gpio.rs index 79263f175..6a2529bf9 100644 --- a/esp-hal/src/soc/esp32s3/gpio.rs +++ b/esp-hal/src/soc/esp32s3/gpio.rs @@ -47,7 +47,6 @@ use crate::{ InterruptStatusRegisterAccess, InterruptStatusRegisterAccessBank0, InterruptStatusRegisterAccessBank1, - Unknown, }, peripherals::GPIO, }; @@ -490,5 +489,5 @@ impl InterruptStatusRegisterAccess for InterruptStatusRegisterAccessBank1 { } // implement marker traits on USB pins -impl crate::otg_fs::UsbDp for Gpio19 {} -impl crate::otg_fs::UsbDm for Gpio20 {} +impl crate::otg_fs::UsbDp for Gpio19 {} +impl crate::otg_fs::UsbDm for Gpio20 {} diff --git a/esp-hal/src/spi/master.rs b/esp-hal/src/spi/master.rs index d7cbbe3ed..844b81913 100644 --- a/esp-hal/src/spi/master.rs +++ b/esp-hal/src/spi/master.rs @@ -75,6 +75,7 @@ use crate::{ interrupt::InterruptHandler, peripheral::{Peripheral, PeripheralRef}, peripherals::spi2::RegisterBlock, + private, system::PeripheralClockControl, }; @@ -452,32 +453,32 @@ where pub fn with_sck(self, sck: impl Peripheral

+ 'd) -> Self { crate::into_ref!(sck); - sck.set_to_push_pull_output() - .connect_peripheral_to_output(self.spi.sclk_signal()); + sck.set_to_push_pull_output(private::Internal); + sck.connect_peripheral_to_output(self.spi.sclk_signal(), private::Internal); self } pub fn with_mosi(self, mosi: impl Peripheral

+ 'd) -> Self { crate::into_ref!(mosi); - mosi.set_to_push_pull_output() - .connect_peripheral_to_output(self.spi.mosi_signal()); + mosi.set_to_push_pull_output(private::Internal); + mosi.connect_peripheral_to_output(self.spi.mosi_signal(), private::Internal); self } pub fn with_miso(self, miso: impl Peripheral

+ 'd) -> Self { crate::into_ref!(miso); - miso.set_to_input() - .connect_input_to_peripheral(self.spi.miso_signal()); + miso.set_to_input(private::Internal); + miso.connect_input_to_peripheral(self.spi.miso_signal(), private::Internal); self } pub fn with_cs(self, cs: impl Peripheral

+ 'd) -> Self { crate::into_ref!(cs); - cs.set_to_push_pull_output() - .connect_peripheral_to_output(self.spi.cs_signal()); + cs.set_to_push_pull_output(private::Internal); + cs.connect_peripheral_to_output(self.spi.cs_signal(), private::Internal); self } @@ -503,26 +504,26 @@ where ) -> Self { if let Some(sck) = sck { crate::into_ref!(sck); - sck.set_to_push_pull_output() - .connect_peripheral_to_output(self.spi.sclk_signal()); + sck.set_to_push_pull_output(private::Internal); + sck.connect_peripheral_to_output(self.spi.sclk_signal(), private::Internal); } if let Some(mosi) = mosi { crate::into_ref!(mosi); - mosi.set_to_push_pull_output() - .connect_peripheral_to_output(self.spi.mosi_signal()); + mosi.set_to_push_pull_output(private::Internal); + mosi.connect_peripheral_to_output(self.spi.mosi_signal(), private::Internal); } if let Some(miso) = miso { crate::into_ref!(miso); - miso.set_to_input() - .connect_input_to_peripheral(self.spi.miso_signal()); + miso.set_to_input(private::Internal); + miso.connect_input_to_peripheral(self.spi.miso_signal(), private::Internal); } if let Some(cs) = cs { crate::into_ref!(cs); - cs.set_to_push_pull_output() - .connect_peripheral_to_output(self.spi.cs_signal()); + cs.set_to_push_pull_output(private::Internal); + cs.connect_peripheral_to_output(self.spi.cs_signal(), private::Internal); } self @@ -572,8 +573,8 @@ where pub fn with_sck(self, sck: impl Peripheral

+ 'd) -> Self { crate::into_ref!(sck); - sck.set_to_push_pull_output() - .connect_peripheral_to_output(self.spi.sclk_signal()); + sck.set_to_push_pull_output(private::Internal); + sck.connect_peripheral_to_output(self.spi.sclk_signal(), private::Internal); self } @@ -583,10 +584,10 @@ where mosi: impl Peripheral

+ 'd, ) -> Self { crate::into_ref!(mosi); - mosi.enable_output(true); - mosi.connect_peripheral_to_output(self.spi.mosi_signal()); - mosi.enable_input(true); - mosi.connect_input_to_peripheral(self.spi.sio0_input_signal()); + mosi.enable_output(true, private::Internal); + mosi.connect_peripheral_to_output(self.spi.mosi_signal(), private::Internal); + mosi.enable_input(true, private::Internal); + mosi.connect_input_to_peripheral(self.spi.sio0_input_signal(), private::Internal); self } @@ -596,10 +597,10 @@ where miso: impl Peripheral

+ 'd, ) -> Self { crate::into_ref!(miso); - miso.enable_output(true); - miso.connect_peripheral_to_output(self.spi.sio1_output_signal()); - miso.enable_input(true); - miso.connect_input_to_peripheral(self.spi.miso_signal()); + miso.enable_output(true, private::Internal); + miso.connect_peripheral_to_output(self.spi.sio1_output_signal(), private::Internal); + miso.enable_input(true, private::Internal); + miso.connect_input_to_peripheral(self.spi.miso_signal(), private::Internal); self } @@ -609,10 +610,10 @@ where sio2: impl Peripheral

+ 'd, ) -> Self { crate::into_ref!(sio2); - sio2.enable_output(true); - sio2.connect_peripheral_to_output(self.spi.sio2_output_signal()); - sio2.enable_input(true); - sio2.connect_input_to_peripheral(self.spi.sio2_input_signal()); + sio2.enable_output(true, private::Internal); + sio2.connect_peripheral_to_output(self.spi.sio2_output_signal(), private::Internal); + sio2.enable_input(true, private::Internal); + sio2.connect_input_to_peripheral(self.spi.sio2_input_signal(), private::Internal); self } @@ -622,18 +623,18 @@ where sio3: impl Peripheral

+ 'd, ) -> Self { crate::into_ref!(sio3); - sio3.enable_output(true); - sio3.connect_peripheral_to_output(self.spi.sio3_output_signal()); - sio3.enable_input(true); - sio3.connect_input_to_peripheral(self.spi.sio3_input_signal()); + sio3.enable_output(true, private::Internal); + sio3.connect_peripheral_to_output(self.spi.sio3_output_signal(), private::Internal); + sio3.enable_input(true, private::Internal); + sio3.connect_input_to_peripheral(self.spi.sio3_input_signal(), private::Internal); self } pub fn with_cs(self, cs: impl Peripheral

+ 'd) -> Self { crate::into_ref!(cs); - cs.set_to_push_pull_output() - .connect_peripheral_to_output(self.spi.cs_signal()); + cs.set_to_push_pull_output(private::Internal); + cs.connect_peripheral_to_output(self.spi.cs_signal(), private::Internal); self } @@ -660,46 +661,46 @@ where ) -> Self { if let Some(sck) = sck { crate::into_ref!(sck); - sck.set_to_push_pull_output() - .connect_peripheral_to_output(self.spi.sclk_signal()); + sck.set_to_push_pull_output(private::Internal); + sck.connect_peripheral_to_output(self.spi.sclk_signal(), private::Internal); } if let Some(mosi) = mosi { crate::into_ref!(mosi); - mosi.enable_output(true); - mosi.connect_peripheral_to_output(self.spi.mosi_signal()); - mosi.enable_input(true); - mosi.connect_input_to_peripheral(self.spi.sio0_input_signal()); + mosi.enable_output(true, private::Internal); + mosi.connect_peripheral_to_output(self.spi.mosi_signal(), private::Internal); + mosi.enable_input(true, private::Internal); + mosi.connect_input_to_peripheral(self.spi.sio0_input_signal(), private::Internal); } if let Some(miso) = miso { crate::into_ref!(miso); - miso.enable_output(true); - miso.connect_peripheral_to_output(self.spi.sio1_output_signal()); - miso.enable_input(true); - miso.connect_input_to_peripheral(self.spi.miso_signal()); + miso.enable_output(true, private::Internal); + miso.connect_peripheral_to_output(self.spi.sio1_output_signal(), private::Internal); + miso.enable_input(true, private::Internal); + miso.connect_input_to_peripheral(self.spi.miso_signal(), private::Internal); } if let Some(sio2) = sio2 { crate::into_ref!(sio2); - sio2.enable_output(true); - sio2.connect_peripheral_to_output(self.spi.sio2_output_signal()); - sio2.enable_input(true); - sio2.connect_input_to_peripheral(self.spi.sio2_input_signal()); + sio2.enable_output(true, private::Internal); + sio2.connect_peripheral_to_output(self.spi.sio2_output_signal(), private::Internal); + sio2.enable_input(true, private::Internal); + sio2.connect_input_to_peripheral(self.spi.sio2_input_signal(), private::Internal); } if let Some(sio3) = sio3 { crate::into_ref!(sio3); - sio3.enable_output(true); - sio3.connect_peripheral_to_output(self.spi.sio3_output_signal()); - sio3.enable_input(true); - sio3.connect_input_to_peripheral(self.spi.sio3_input_signal()); + sio3.enable_output(true, private::Internal); + sio3.connect_peripheral_to_output(self.spi.sio3_output_signal(), private::Internal); + sio3.enable_input(true, private::Internal); + sio3.connect_input_to_peripheral(self.spi.sio3_input_signal(), private::Internal); } if let Some(cs) = cs { crate::into_ref!(cs); - cs.set_to_push_pull_output() - .connect_peripheral_to_output(self.spi.cs_signal()); + cs.set_to_push_pull_output(private::Internal); + cs.connect_peripheral_to_output(self.spi.cs_signal(), private::Internal); } self @@ -2135,7 +2136,7 @@ pub trait ExtendedInstance: Instance { } #[doc(hidden)] -pub trait Instance: crate::private::Sealed { +pub trait Instance: private::Sealed { fn register_block(&self) -> &RegisterBlock; fn sclk_signal(&self) -> OutputSignal; diff --git a/esp-hal/src/spi/slave.rs b/esp-hal/src/spi/slave.rs index b64beb0f4..94b9b03ec 100644 --- a/esp-hal/src/spi/slave.rs +++ b/esp-hal/src/spi/slave.rs @@ -54,6 +54,7 @@ use crate::{ gpio::{InputPin, InputSignal, OutputPin, OutputSignal}, peripheral::{Peripheral, PeripheralRef}, peripherals::spi2::RegisterBlock, + private, system::PeripheralClockControl, }; @@ -92,17 +93,17 @@ where mode: SpiMode, ) -> Spi<'d, T, FullDuplexMode> { crate::into_ref!(spi, sck, mosi, miso, cs); - sck.set_to_input() - .connect_input_to_peripheral(spi.sclk_signal()); + sck.set_to_input(private::Internal); + sck.connect_input_to_peripheral(spi.sclk_signal(), private::Internal); - mosi.set_to_input() - .connect_input_to_peripheral(spi.mosi_signal()); + mosi.set_to_input(private::Internal); + mosi.connect_input_to_peripheral(spi.mosi_signal(), private::Internal); - miso.set_to_push_pull_output() - .connect_peripheral_to_output(spi.miso_signal()); + miso.set_to_push_pull_output(private::Internal); + miso.connect_peripheral_to_output(spi.miso_signal(), private::Internal); - cs.set_to_input() - .connect_input_to_peripheral(spi.cs_signal()); + cs.set_to_input(private::Internal); + cs.connect_input_to_peripheral(spi.cs_signal(), private::Internal); Self::new_internal(spi, mode) } @@ -736,7 +737,7 @@ where } #[doc(hidden)] -pub trait Instance: crate::private::Sealed { +pub trait Instance: private::Sealed { fn register_block(&self) -> &RegisterBlock; fn sclk_signal(&self) -> InputSignal; diff --git a/esp-hal/src/timer/systimer.rs b/esp-hal/src/timer/systimer.rs index e44b03d36..b48a4679a 100644 --- a/esp-hal/src/timer/systimer.rs +++ b/esp-hal/src/timer/systimer.rs @@ -42,7 +42,7 @@ pub struct SystemTimer<'d, DM: crate::Mode> { pub alarm0: Alarm, pub alarm1: Alarm, pub alarm2: Alarm, - _phantom: &'d PhantomData<()>, + _phantom: PhantomData<&'d ()>, } impl<'d> SystemTimer<'d, crate::Blocking> { @@ -67,7 +67,7 @@ impl<'d> SystemTimer<'d, crate::Blocking> { alarm0: Alarm::new(), alarm1: Alarm::new(), alarm2: Alarm::new(), - _phantom: &PhantomData, + _phantom: PhantomData, } } @@ -98,7 +98,7 @@ impl<'d> SystemTimer<'d, crate::Async> { alarm0: Alarm::new(), alarm1: Alarm::new(), alarm2: Alarm::new(), - _phantom: &PhantomData, + _phantom: PhantomData, } } } diff --git a/esp-hal/src/twai/mod.rs b/esp-hal/src/twai/mod.rs index 0177fd494..ca8ddc632 100644 --- a/esp-hal/src/twai/mod.rs +++ b/esp-hal/src/twai/mod.rs @@ -646,14 +646,18 @@ where clocks: &Clocks, baud_rate: BaudRate, interrupt: Option, + no_transceiver: bool, ) -> Self { // Enable the peripheral clock for the TWAI peripheral. T::enable_peripheral(); // Set up the GPIO pins. crate::into_ref!(tx_pin, rx_pin); - tx_pin.connect_peripheral_to_output(T::OUTPUT_SIGNAL); - rx_pin.connect_input_to_peripheral(T::INPUT_SIGNAL); + if no_transceiver { + tx_pin.set_to_open_drain_output(crate::private::Internal); + } + tx_pin.connect_peripheral_to_output(T::OUTPUT_SIGNAL, crate::private::Internal); + rx_pin.connect_input_to_peripheral(T::INPUT_SIGNAL, crate::private::Internal); let mut cfg = TwaiConfiguration { peripheral: PhantomData, @@ -775,6 +779,9 @@ impl<'d, T> TwaiConfiguration<'d, T, crate::Blocking> where T: Instance, { + /// Create a new instance of [TwaiConfiguration] + /// + /// You will need to use a transceiver to connect to the TWAI bus pub fn new( peripheral: impl Peripheral

+ 'd, tx_pin: impl Peripheral

+ 'd, @@ -783,7 +790,27 @@ where baud_rate: BaudRate, interrupt: Option, ) -> Self { - Self::new_internal(peripheral, tx_pin, rx_pin, clocks, baud_rate, interrupt) + Self::new_internal( + peripheral, tx_pin, rx_pin, clocks, baud_rate, interrupt, false, + ) + } + + /// Create a new instance of [TwaiConfiguration] meant to connect two ESP32s + /// directly + /// + /// You don't need a transceiver by following the description in the + /// `twai.rs` example + pub fn new_no_transceiver( + peripheral: impl Peripheral

+ 'd, + tx_pin: impl Peripheral

+ 'd, + rx_pin: impl Peripheral

+ 'd, + clocks: &Clocks, + baud_rate: BaudRate, + interrupt: Option, + ) -> Self { + Self::new_internal( + peripheral, tx_pin, rx_pin, clocks, baud_rate, interrupt, true, + ) } } @@ -792,6 +819,9 @@ impl<'d, T> TwaiConfiguration<'d, T, crate::Async> where T: Instance, { + /// Create a new instance of [TwaiConfiguration] in async mode + /// + /// You will need to use a transceiver to connect to the TWAI bus pub fn new_async( peripheral: impl Peripheral

+ 'd, tx_pin: impl Peripheral

+ 'd, @@ -807,6 +837,31 @@ where clocks, baud_rate, Some(interrupt), + false, + ) + } + + /// Create a new instance of [TwaiConfiguration] meant to connect two ESP32s + /// directly in async mode + /// + /// You don't need a transceiver by following the description in the + /// `twai.rs` example + pub fn new_async_no_transceiver( + peripheral: impl Peripheral

+ 'd, + tx_pin: impl Peripheral

+ 'd, + rx_pin: impl Peripheral

+ 'd, + clocks: &Clocks, + baud_rate: BaudRate, + ) -> Self { + let interrupt = T::async_handler(); + Self::new_internal( + peripheral, + tx_pin, + rx_pin, + clocks, + baud_rate, + Some(interrupt), + true, ) } } diff --git a/esp-hal/src/uart.rs b/esp-hal/src/uart.rs index c12f49895..d48a556ac 100644 --- a/esp-hal/src/uart.rs +++ b/esp-hal/src/uart.rs @@ -20,10 +20,7 @@ //! //! ```no_run //! let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); -//! let pins = TxRxPins::new_tx_rx( -//! io.pins.gpio1.into_push_pull_output(), -//! io.pins.gpio2.into_floating_input(), -//! ); +//! let pins = TxRxPins::new_tx_rx(io.pins.gpio1, io.pins.gpio2); //! //! let mut uart1 = //! Uart::new_with_config(peripherals.UART1, Config::default(), Some(pins), &clocks); @@ -332,21 +329,23 @@ impl UartPins rts_signal: OutputSignal, ) { if let Some(ref mut tx) = self.tx { - tx.set_to_push_pull_output() - .connect_peripheral_to_output(tx_signal); + tx.set_to_push_pull_output(crate::private::Internal); + tx.connect_peripheral_to_output(tx_signal, crate::private::Internal); } if let Some(ref mut rx) = self.rx { - rx.set_to_input().connect_input_to_peripheral(rx_signal); + rx.set_to_input(crate::private::Internal); + rx.connect_input_to_peripheral(rx_signal, crate::private::Internal); } if let Some(ref mut cts) = self.cts { - cts.set_to_input().connect_input_to_peripheral(cts_signal); + cts.set_to_input(crate::private::Internal); + cts.connect_input_to_peripheral(cts_signal, crate::private::Internal); } if let Some(ref mut rts) = self.rts { - rts.set_to_push_pull_output() - .connect_peripheral_to_output(rts_signal); + rts.set_to_push_pull_output(crate::private::Internal); + rts.connect_peripheral_to_output(rts_signal, crate::private::Internal); } } } @@ -379,12 +378,14 @@ impl UartPins for TxRxPins<'_, TX, RX> { _rts_signal: OutputSignal, ) { if let Some(ref mut tx) = self.tx { - tx.set_to_push_pull_output() - .connect_peripheral_to_output(tx_signal); + tx.set_to_push_pull_output(crate::private::Internal); + tx.set_output_high(true, crate::private::Internal); + tx.connect_peripheral_to_output(tx_signal, crate::private::Internal); } if let Some(ref mut rx) = self.rx { - rx.set_to_input().connect_input_to_peripheral(rx_signal); + rx.set_to_input(crate::private::Internal); + rx.connect_input_to_peripheral(rx_signal, crate::private::Internal); } } } @@ -586,10 +587,16 @@ where .modify(|_, w| w.err_wr_mask().set_bit()); // Reset Tx/Rx FIFOs - serial.txfifo_reset(); serial.rxfifo_reset(); + serial.txfifo_reset(); crate::rom::ets_delay_us(15); + // Make sure we are starting in a "clean state" - previous operations might have + // run into error conditions + T::register_block() + .int_clr() + .write(|w| unsafe { w.bits(u32::MAX) }); + serial } @@ -2110,9 +2117,9 @@ mod asynch { #[cfg(lp_uart)] pub mod lp_uart { use crate::{ - gpio::{lp_io::LowPowerPin, Floating, Input, Output, PushPull}, + gpio::lp_io::{LowPowerInput, LowPowerOutput}, peripherals::{LP_CLKRST, LP_UART}, - uart::{config, config::Config}, + uart::config::{self, Config}, }; /// LP-UART driver /// @@ -2124,11 +2131,7 @@ pub mod lp_uart { impl LpUart { /// Initialize the UART driver using the default configuration // TODO: CTS and RTS pins - pub fn new( - uart: LP_UART, - _tx: LowPowerPin, 5>, - _rx: LowPowerPin, 4>, - ) -> Self { + pub fn new(uart: LP_UART, _tx: LowPowerOutput<5>, _rx: LowPowerInput<4>) -> Self { let lp_io = unsafe { &*crate::peripherals::LP_IO::PTR }; let lp_aon = unsafe { &*crate::peripherals::LP_AON::PTR }; diff --git a/esp-lp-hal/.cargo/config.toml b/esp-lp-hal/.cargo/config.toml index 481bd89a0..3cf0f9207 100644 --- a/esp-lp-hal/.cargo/config.toml +++ b/esp-lp-hal/.cargo/config.toml @@ -1,9 +1,13 @@ +[alias] +esp32c6 = "build --release --examples --features=esp32c6 --target riscv32imac-unknown-none-elf" +esp32s2 = "build --release --example=blinky --features=esp32s2 --target riscv32imc-unknown-none-elf" +esp32s3 = "build --release --example=blinky --features=esp32s3 --target riscv32imc-unknown-none-elf" + [build] # target = "riscv32imc-unknown-none-elf" # ESP32-S2 + ESP32-S3 target = "riscv32imac-unknown-none-elf" # ESP32-C6 [target.'cfg(target_arch = "riscv32")'] -runner = "espflash flash --monitor" rustflags = [ "-C", "link-arg=-Tlink.x", ] diff --git a/esp-lp-hal/CHANGELOG.md b/esp-lp-hal/CHANGELOG.md index 5c23b5ff0..dd831b711 100644 --- a/esp-lp-hal/CHANGELOG.md +++ b/esp-lp-hal/CHANGELOG.md @@ -19,6 +19,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed - Renamed to `esp-ulp-riscv-hal` (#916) +- Remove 2nd level generics from GPIO pin (#1526) ### Fixed diff --git a/esp-lp-hal/examples/blinky.rs b/esp-lp-hal/examples/blinky.rs index 932da7871..94dda5293 100644 --- a/esp-lp-hal/examples/blinky.rs +++ b/esp-lp-hal/examples/blinky.rs @@ -11,11 +11,7 @@ #![no_main] use embedded_hal_02::{blocking::delay::DelayMs, digital::v2::OutputPin}; -use esp_lp_hal::{ - delay::Delay, - gpio::{GpioPin, Output, PushPull}, - prelude::*, -}; +use esp_lp_hal::{delay::Delay, gpio::Output, prelude::*}; use panic_halt as _; cfg_if::cfg_if! { @@ -27,7 +23,7 @@ cfg_if::cfg_if! { } #[entry] -fn main(mut gpio1: GpioPin, 1>) -> ! { +fn main(mut gpio1: Output<1>) -> ! { let mut i: u32 = 0; let ptr = ADDRESS as *mut u32; diff --git a/esp-lp-hal/src/gpio.rs b/esp-lp-hal/src/gpio.rs index 2fa539bfa..f1120fff5 100644 --- a/esp-lp-hal/src/gpio.rs +++ b/esp-lp-hal/src/gpio.rs @@ -2,42 +2,24 @@ //! //! It's assumed that GPIOs are already configured correctly by the HP core. -use core::marker::PhantomData; - #[cfg(feature = "esp32c6")] type LpIo = crate::pac::LP_IO; #[cfg(any(feature = "esp32s2", feature = "esp32s3"))] type LpIo = crate::pac::RTC_IO; -pub struct Unknown {} +#[non_exhaustive] +pub struct Input {} -pub struct Input { - _mode: PhantomData, -} - -pub struct Floating; - -pub struct PullDown; - -pub struct PullUp; - -pub struct Output { - _mode: PhantomData, -} - -pub struct PushPull; - -pub struct GpioPin { - phantom: PhantomData, -} - -impl GpioPin, PIN> { +impl Input { pub fn input_state(&self) -> bool { unsafe { &*LpIo::PTR }.in_().read().bits() >> PIN & 0x1 != 0 } } -impl GpioPin, PIN> { +#[non_exhaustive] +pub struct Output {} + +impl Output { pub fn output_state(&self) -> bool { unsafe { &*LpIo::PTR }.out().read().bits() >> PIN & 0x1 != 0 } @@ -57,18 +39,26 @@ impl GpioPin, PIN> { // Used by the `entry` procmacro: #[doc(hidden)] -pub unsafe fn conjure() -> Option> { +pub unsafe fn conjure_output() -> Option> { if PIN > 7 { None } else { - Some(GpioPin { - phantom: PhantomData, - }) + Some(Output {}) + } +} + +// Used by the `entry` procmacro: +#[doc(hidden)] +pub unsafe fn conjure_input() -> Option> { + if PIN > 7 { + None + } else { + Some(Input {}) } } #[cfg(feature = "embedded-hal-02")] -impl embedded_hal_02::digital::v2::InputPin for GpioPin, PIN> { +impl embedded_hal_02::digital::v2::InputPin for Input { type Error = core::convert::Infallible; fn is_high(&self) -> Result { @@ -81,7 +71,7 @@ impl embedded_hal_02::digital::v2::InputPin for GpioPin embedded_hal_02::digital::v2::OutputPin for GpioPin, PIN> { +impl embedded_hal_02::digital::v2::OutputPin for Output { type Error = core::convert::Infallible; fn set_low(&mut self) -> Result<(), Self::Error> { @@ -96,9 +86,7 @@ impl embedded_hal_02::digital::v2::OutputPin for GpioPin embedded_hal_02::digital::v2::StatefulOutputPin - for GpioPin, PIN> -{ +impl embedded_hal_02::digital::v2::StatefulOutputPin for Output { fn is_set_high(&self) -> Result { Ok(self.output_state()) } @@ -109,18 +97,20 @@ impl embedded_hal_02::digital::v2::StatefulOutputPin } #[cfg(feature = "embedded-hal-02")] -impl embedded_hal_02::digital::v2::toggleable::Default - for GpioPin, PIN> -{ -} +impl embedded_hal_02::digital::v2::toggleable::Default for Output {} #[cfg(feature = "embedded-hal-1")] -impl embedded_hal_1::digital::ErrorType for GpioPin { +impl embedded_hal_1::digital::ErrorType for Input { type Error = core::convert::Infallible; } #[cfg(feature = "embedded-hal-1")] -impl embedded_hal_1::digital::InputPin for GpioPin, PIN> { +impl embedded_hal_1::digital::ErrorType for Output { + type Error = core::convert::Infallible; +} + +#[cfg(feature = "embedded-hal-1")] +impl embedded_hal_1::digital::InputPin for Input { fn is_high(&mut self) -> Result { Ok(self.input_state()) } @@ -131,7 +121,7 @@ impl embedded_hal_1::digital::InputPin for GpioPin embedded_hal_1::digital::OutputPin for GpioPin, PIN> { +impl embedded_hal_1::digital::OutputPin for Output { fn set_low(&mut self) -> Result<(), Self::Error> { self.set_output(false); Ok(()) @@ -144,9 +134,7 @@ impl embedded_hal_1::digital::OutputPin for GpioPin embedded_hal_1::digital::StatefulOutputPin - for GpioPin, PIN> -{ +impl embedded_hal_1::digital::StatefulOutputPin for Output { fn is_set_high(&mut self) -> Result { Ok(self.output_state()) } diff --git a/examples/src/bin/adc.rs b/examples/src/bin/adc.rs index 399807bb2..066c056fe 100644 --- a/examples/src/bin/adc.rs +++ b/examples/src/bin/adc.rs @@ -30,11 +30,11 @@ fn main() -> ! { let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); cfg_if::cfg_if! { if #[cfg(feature = "esp32")] { - let analog_pin = io.pins.gpio32.into_analog(); + let analog_pin = io.pins.gpio32; } else if #[cfg(any(feature = "esp32s2", feature = "esp32s3"))] { - let analog_pin = io.pins.gpio3.into_analog(); + let analog_pin = io.pins.gpio3; } else { - let analog_pin = io.pins.gpio2.into_analog(); + let analog_pin = io.pins.gpio2; } } diff --git a/examples/src/bin/adc_cal.rs b/examples/src/bin/adc_cal.rs index 8a2c9e957..a07f20f70 100644 --- a/examples/src/bin/adc_cal.rs +++ b/examples/src/bin/adc_cal.rs @@ -28,9 +28,9 @@ fn main() -> ! { let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); cfg_if::cfg_if! { if #[cfg(feature = "esp32s3")] { - let analog_pin = io.pins.gpio3.into_analog(); + let analog_pin = io.pins.gpio3; } else { - let analog_pin = io.pins.gpio2.into_analog(); + let analog_pin = io.pins.gpio2; } } @@ -39,8 +39,8 @@ fn main() -> ! { // them. Note that only AdcCalLine returns readings in mV; the other two // return raw readings in some unspecified scale. // - type AdcCal = (); - // type AdcCal = esp_hal::analog::adc::AdcCalBasic; + //type AdcCal = (); + type AdcCal = esp_hal::analog::adc::AdcCalBasic; // type AdcCal = esp_hal::analog::adc::AdcCalLine; // type AdcCal = esp_hal::analog::adc::AdcCalCurve; diff --git a/examples/src/bin/advanced_serial.rs b/examples/src/bin/advanced_serial.rs index c19f27a02..98afe1197 100644 --- a/examples/src/bin/advanced_serial.rs +++ b/examples/src/bin/advanced_serial.rs @@ -1,6 +1,6 @@ //! This shows how to configure UART //! You can short the TX and RX pin and see it reads what was written. -//! Additionally you can connect a logic analzyer to TX and see how the changes +//! Additionally you can connect a logic analyzer to TX and see how the changes //! of the configuration change the output signal. //! //! The following wiring is assumed: @@ -32,10 +32,7 @@ fn main() -> ! { let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); - let pins = TxRxPins::new_tx_rx( - io.pins.gpio4.into_push_pull_output(), - io.pins.gpio5.into_floating_input(), - ); + let pins = TxRxPins::new_tx_rx(io.pins.gpio4, io.pins.gpio5); let mut serial1 = Uart::new_with_config( peripherals.UART1, diff --git a/examples/src/bin/blinky.rs b/examples/src/bin/blinky.rs index 27d2d00d3..9b04ae96f 100644 --- a/examples/src/bin/blinky.rs +++ b/examples/src/bin/blinky.rs @@ -11,7 +11,7 @@ use esp_backtrace as _; use esp_hal::{ clock::ClockControl, delay::Delay, - gpio::Io, + gpio::{Io, Output}, peripherals::Peripherals, prelude::*, system::SystemControl, @@ -25,9 +25,7 @@ fn main() -> ! { // Set GPIO0 as an output, and set its state high initially. let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); - let mut led = io.pins.gpio8.into_push_pull_output(); - - led.set_high(); + let mut led = Output::new(io.pins.gpio0, true); // Initialize the Delay peripheral, and use it to toggle the LED state in a // loop. diff --git a/examples/src/bin/blinky_erased_pins.rs b/examples/src/bin/blinky_erased_pins.rs index 9864fa524..f63aad287 100644 --- a/examples/src/bin/blinky_erased_pins.rs +++ b/examples/src/bin/blinky_erased_pins.rs @@ -1,6 +1,6 @@ //! Blinks 3 LEDs //! -//! This assumes that LEDs are connected to GPIO8, 9 and 10. +//! This assumes that LEDs are connected to GPIO2, 4 and 5. //! //! GPIO1 is treated as an input, and will print a message when pressed. This //! Additionally demonstrates passing GPIO to a function in a generic way. @@ -14,7 +14,7 @@ use esp_backtrace as _; use esp_hal::{ clock::ClockControl, delay::Delay, - gpio::{AnyPin, Input, Io, Output, PullDown, PushPull}, + gpio::{AnyInput, AnyOutput, Io, Pull}, peripherals::Peripherals, prelude::*, system::SystemControl, @@ -29,15 +29,20 @@ fn main() -> ! { let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); // Set LED GPIOs as an output: - let led1 = io.pins.gpio8.into_push_pull_output(); - let led2 = io.pins.gpio9.into_push_pull_output(); - let led3 = io.pins.gpio10.into_push_pull_output(); + let led1 = AnyOutput::new(io.pins.gpio2, false); + let led2 = AnyOutput::new(io.pins.gpio4, false); + let led3 = AnyOutput::new(io.pins.gpio5, false); - // Set GPIO0 as an input: - let button = io.pins.gpio0.into_pull_down_input().into(); + // Use boot button as an input: + #[cfg(any(feature = "esp32", feature = "esp32s2", feature = "esp32s3"))] + let button = io.pins.gpio0; + #[cfg(not(any(feature = "esp32", feature = "esp32s2", feature = "esp32s3")))] + let button = io.pins.gpio9; + + let button = AnyInput::new(button, Pull::Up); // You can use `into` or `degrade`: - let mut pins = [led1.into(), led2.into(), led3.degrade().into()]; + let mut pins = [led1, led2, led3]; // Initialize the `Delay` peripheral, and use it to toggle the LED state // in a loop: @@ -49,7 +54,7 @@ fn main() -> ! { } } -fn toggle_pins(leds: &mut [AnyPin>], button: &AnyPin>) { +fn toggle_pins(leds: &mut [AnyOutput], button: &AnyInput) { for pin in leds.iter_mut() { pin.toggle(); } diff --git a/examples/src/bin/dac.rs b/examples/src/bin/dac.rs index 4eb86ddb0..d603f608a 100644 --- a/examples/src/bin/dac.rs +++ b/examples/src/bin/dac.rs @@ -32,11 +32,11 @@ fn main() -> ! { cfg_if::cfg_if! { if #[cfg(feature = "esp32")] { - let dac1_pin = io.pins.gpio25.into_analog(); - let dac2_pin = io.pins.gpio26.into_analog(); + let dac1_pin = io.pins.gpio25; + let dac2_pin = io.pins.gpio26; } else if #[cfg(feature = "esp32s2")] { - let dac1_pin = io.pins.gpio17.into_analog(); - let dac2_pin = io.pins.gpio18.into_analog(); + let dac1_pin = io.pins.gpio17; + let dac2_pin = io.pins.gpio18; } } diff --git a/examples/src/bin/embassy_multicore.rs b/examples/src/bin/embassy_multicore.rs index b0bf2a76a..96079f401 100644 --- a/examples/src/bin/embassy_multicore.rs +++ b/examples/src/bin/embassy_multicore.rs @@ -20,7 +20,7 @@ use esp_hal::{ cpu_control::{CpuControl, Stack}, embassy::{self, executor::Executor}, get_core, - gpio::{GpioPin, Io, Output, PushPull}, + gpio::{AnyOutput, Io}, peripherals::Peripherals, prelude::*, system::SystemControl, @@ -35,7 +35,7 @@ static mut APP_CORE_STACK: Stack<8192> = Stack::new(); /// duration of time. #[embassy_executor::task] async fn control_led( - mut led: GpioPin, 0>, + mut led: AnyOutput<'static>, control: &'static Signal, ) { println!("Starting control_led() on core {}", get_core() as usize); @@ -66,7 +66,7 @@ async fn main(_spawner: Spawner) { static LED_CTRL: StaticCell> = StaticCell::new(); let led_ctrl_signal = &*LED_CTRL.init(Signal::new()); - let led = io.pins.gpio0.into_push_pull_output(); + let led = AnyOutput::new(io.pins.gpio0, false); let _guard = cpu_control .start_app_core(unsafe { &mut *addr_of_mut!(APP_CORE_STACK) }, move || { diff --git a/examples/src/bin/embassy_multicore_interrupt.rs b/examples/src/bin/embassy_multicore_interrupt.rs index b62e3a2ff..5dccb071f 100644 --- a/examples/src/bin/embassy_multicore_interrupt.rs +++ b/examples/src/bin/embassy_multicore_interrupt.rs @@ -19,7 +19,7 @@ use esp_hal::{ cpu_control::{CpuControl, Stack}, embassy::{self, executor::InterruptExecutor}, get_core, - gpio::{GpioPin, Io, Output, PushPull}, + gpio::{AnyOutput, Io}, interrupt::Priority, peripherals::Peripherals, prelude::*, @@ -35,7 +35,7 @@ static mut APP_CORE_STACK: Stack<8192> = Stack::new(); /// duration of time. #[embassy_executor::task] async fn control_led( - mut led: GpioPin, 0>, + mut led: AnyOutput<'static>, control: &'static Signal, ) { println!("Starting control_led() on core {}", get_core() as usize); @@ -85,7 +85,7 @@ fn main() -> ! { static LED_CTRL: StaticCell> = StaticCell::new(); let led_ctrl_signal = &*LED_CTRL.init(Signal::new()); - let led = io.pins.gpio0.into_push_pull_output(); + let led = AnyOutput::new(io.pins.gpio0, false); static EXECUTOR_CORE_1: StaticCell> = StaticCell::new(); let executor_core1 = diff --git a/examples/src/bin/embassy_rmt_rx.rs b/examples/src/bin/embassy_rmt_rx.rs index d559cbae1..4e7da6acc 100644 --- a/examples/src/bin/embassy_rmt_rx.rs +++ b/examples/src/bin/embassy_rmt_rx.rs @@ -13,7 +13,7 @@ use esp_backtrace as _; use esp_hal::{ clock::ClockControl, embassy::{self}, - gpio::{Gpio5, Io, Output, PushPull}, + gpio::{Gpio5, Io, Output}, peripherals::Peripherals, prelude::*, rmt::{asynch::RxChannelAsync, PulseCode, Rmt, RxChannelConfig, RxChannelCreatorAsync}, @@ -27,7 +27,7 @@ const WIDTH: usize = 80; compile_error!("Run this example in release mode"); #[embassy_executor::task] -async fn signal_task(mut pin: Gpio5>) { +async fn signal_task(mut pin: Output<'static, Gpio5>) { loop { for _ in 0..10 { pin.toggle(); @@ -75,7 +75,7 @@ async fn main(spawner: Spawner) { } spawner - .spawn(signal_task(io.pins.gpio5.into_push_pull_output())) + .spawn(signal_task(Output::new(io.pins.gpio5, false))) .unwrap(); let mut data = [PulseCode { diff --git a/examples/src/bin/embassy_rmt_tx.rs b/examples/src/bin/embassy_rmt_tx.rs index d0b9456e7..9c254ab40 100644 --- a/examples/src/bin/embassy_rmt_tx.rs +++ b/examples/src/bin/embassy_rmt_tx.rs @@ -48,7 +48,7 @@ async fn main(_spawner: Spawner) { let mut channel = rmt .channel0 .configure( - io.pins.gpio4.into_push_pull_output(), + io.pins.gpio4, TxChannelConfig { clk_divider: 255, ..TxChannelConfig::default() diff --git a/examples/src/bin/embassy_twai.rs b/examples/src/bin/embassy_twai.rs index 35aa26404..9247ffc27 100644 --- a/examples/src/bin/embassy_twai.rs +++ b/examples/src/bin/embassy_twai.rs @@ -91,16 +91,17 @@ async fn main(spawner: Spawner) { let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); - // Set the tx pin as open drain. Skip this if using transceivers. - let can_tx_pin = io.pins.gpio0.into_open_drain_output(); + let can_tx_pin = io.pins.gpio0; let can_rx_pin = io.pins.gpio2; // The speed of the CAN bus. const CAN_BAUDRATE: twai::BaudRate = twai::BaudRate::B1000K; + // !!! Use `new_async` when using a transceiver. `new_async_no_transceiver` sets TX to open-drain + // Begin configuring the TWAI peripheral. The peripheral is in a reset like // state that prevents transmission but allows configuration. - let mut can_config = twai::TwaiConfiguration::new_async( + let mut can_config = twai::TwaiConfiguration::new_async_no_transceiver( peripherals.TWAI0, can_tx_pin, can_rx_pin, diff --git a/examples/src/bin/embassy_wait.rs b/examples/src/bin/embassy_wait.rs index d4ca2ef46..628c4105b 100644 --- a/examples/src/bin/embassy_wait.rs +++ b/examples/src/bin/embassy_wait.rs @@ -13,8 +13,8 @@ use embassy_time::{Duration, Timer}; use esp_backtrace as _; use esp_hal::{ clock::ClockControl, - embassy::{self}, - gpio::Io, + embassy, + gpio::{Input, Io, Pull}, peripherals::Peripherals, prelude::*, system::SystemControl, @@ -33,9 +33,9 @@ async fn main(_spawner: Spawner) { let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); #[cfg(any(feature = "esp32", feature = "esp32s2", feature = "esp32s3"))] - let mut input = io.pins.gpio0.into_pull_down_input(); + let mut input = Input::new(io.pins.gpio0, Pull::Down); #[cfg(not(any(feature = "esp32", feature = "esp32s2", feature = "esp32s3")))] - let mut input = io.pins.gpio9.into_pull_down_input(); + let mut input = Input::new(io.pins.gpio9, Pull::Down); loop { esp_println::println!("Waiting..."); diff --git a/examples/src/bin/etm_blinky_systimer.rs b/examples/src/bin/etm_blinky_systimer.rs index 65ad3b5a4..959c2da28 100644 --- a/examples/src/bin/etm_blinky_systimer.rs +++ b/examples/src/bin/etm_blinky_systimer.rs @@ -8,7 +8,11 @@ use esp_backtrace as _; use esp_hal::{ etm::Etm, - gpio::{etm::GpioEtmChannels, Io}, + gpio::{ + etm::{GpioEtmChannels, GpioEtmOutputConfig}, + Io, + Pull, + }, peripherals::Peripherals, prelude::*, timer::systimer::{etm::SysTimerEtmEvent, SystemTimer}, @@ -24,11 +28,18 @@ fn main() -> ! { alarm0.set_period(1u32.secs()); let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); - let mut led = io.pins.gpio1.into_push_pull_output(); + let mut led = io.pins.gpio1; // setup ETM let gpio_ext = GpioEtmChannels::new(peripherals.GPIO_SD); - let led_task = gpio_ext.channel0_task.toggle(&mut led); + let led_task = gpio_ext.channel0_task.toggle( + &mut led, + GpioEtmOutputConfig { + open_drain: false, + pull: Pull::None, + initial_state: true, + }, + ); let timer_event = SysTimerEtmEvent::new(&mut alarm0); diff --git a/examples/src/bin/etm_gpio.rs b/examples/src/bin/etm_gpio.rs index f0e2e78b4..a966e6e95 100644 --- a/examples/src/bin/etm_gpio.rs +++ b/examples/src/bin/etm_gpio.rs @@ -8,7 +8,11 @@ use esp_backtrace as _; use esp_hal::{ etm::Etm, - gpio::{etm::GpioEtmChannels, Io}, + gpio::{ + etm::{GpioEtmChannels, GpioEtmInputConfig, GpioEtmOutputConfig}, + Io, + Pull, + }, peripherals::Peripherals, prelude::*, }; @@ -18,15 +22,24 @@ fn main() -> ! { let peripherals = Peripherals::take(); let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); - let mut led = io.pins.gpio1.into_push_pull_output(); - let button = io.pins.gpio9.into_pull_down_input(); + let mut led = io.pins.gpio1; + let button = io.pins.gpio9; led.set_high(); // setup ETM let gpio_ext = GpioEtmChannels::new(peripherals.GPIO_SD); - let led_task = gpio_ext.channel0_task.toggle(&mut led); - let button_event = gpio_ext.channel0_event.falling_edge(button); + let led_task = gpio_ext.channel0_task.toggle( + &mut led, + GpioEtmOutputConfig { + open_drain: false, + pull: Pull::None, + initial_state: false, + }, + ); + let button_event = gpio_ext + .channel0_event + .falling_edge(button, GpioEtmInputConfig { pull: Pull::Down }); let etm = Etm::new(peripherals.SOC_ETM); let channel0 = etm.channel0; diff --git a/examples/src/bin/gpio_interrupt.rs b/examples/src/bin/gpio_interrupt.rs index 3d2300216..ddbe03e46 100644 --- a/examples/src/bin/gpio_interrupt.rs +++ b/examples/src/bin/gpio_interrupt.rs @@ -15,7 +15,7 @@ use esp_backtrace as _; use esp_hal::{ clock::ClockControl, delay::Delay, - gpio::{self, Event, Input, Io, PullDown}, + gpio::{self, Event, Input, Io, Output, Pull}, macros::ram, peripherals::Peripherals, prelude::*, @@ -23,11 +23,9 @@ use esp_hal::{ }; #[cfg(any(feature = "esp32", feature = "esp32s2", feature = "esp32s3"))] -static BUTTON: Mutex>>>> = - Mutex::new(RefCell::new(None)); +static BUTTON: Mutex>>> = Mutex::new(RefCell::new(None)); #[cfg(not(any(feature = "esp32", feature = "esp32s2", feature = "esp32s3")))] -static BUTTON: Mutex>>>> = - Mutex::new(RefCell::new(None)); +static BUTTON: Mutex>>> = Mutex::new(RefCell::new(None)); #[entry] fn main() -> ! { @@ -38,12 +36,14 @@ fn main() -> ! { // Set GPIO2 as an output, and set its state high initially. let mut io = Io::new(peripherals.GPIO, peripherals.IO_MUX); io.set_interrupt_handler(handler); - let mut led = io.pins.gpio2.into_push_pull_output(); + let mut led = Output::new(io.pins.gpio2, false); #[cfg(any(feature = "esp32", feature = "esp32s2", feature = "esp32s3"))] - let mut button = io.pins.gpio0.into_pull_down_input(); + let button = io.pins.gpio0; #[cfg(not(any(feature = "esp32", feature = "esp32s2", feature = "esp32s3")))] - let mut button = io.pins.gpio9.into_pull_down_input(); + let button = io.pins.gpio9; + + let mut button = Input::new(button, Pull::Up); critical_section::with(|cs| { button.listen(Event::FallingEdge); diff --git a/examples/src/bin/lcd_i8080.rs b/examples/src/bin/lcd_i8080.rs index d54ee4e58..509d8358d 100644 --- a/examples/src/bin/lcd_i8080.rs +++ b/examples/src/bin/lcd_i8080.rs @@ -28,7 +28,7 @@ use esp_hal::{ delay::Delay, dma::{Dma, DmaPriority}, dma_buffers, - gpio::Io, + gpio::{Io, Output}, lcd_cam::{ lcd::i8080::{Config, TxEightBits, I8080}, LcdCam, @@ -67,8 +67,8 @@ fn main() -> ! { let delay = Delay::new(&clocks); - let mut backlight = lcd_backlight.into_push_pull_output(); - let mut reset = lcd_reset.into_push_pull_output(); + let mut backlight = Output::new(lcd_backlight, false); + let mut reset = Output::new(lcd_reset, false); let tx_pins = TxEightBits::new( io.pins.gpio9, diff --git a/examples/src/bin/ledc.rs b/examples/src/bin/ledc.rs index 42d0b2e25..4a131e157 100644 --- a/examples/src/bin/ledc.rs +++ b/examples/src/bin/ledc.rs @@ -31,7 +31,7 @@ fn main() -> ! { let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); - let led = io.pins.gpio0.into_push_pull_output(); + let led = io.pins.gpio0; let mut ledc = Ledc::new(peripherals.LEDC, &clocks); diff --git a/examples/src/bin/lp_core_basic.rs b/examples/src/bin/lp_core_basic.rs index 4d5758a20..550f77f78 100644 --- a/examples/src/bin/lp_core_basic.rs +++ b/examples/src/bin/lp_core_basic.rs @@ -12,7 +12,7 @@ use esp_backtrace as _; use esp_hal::{ - gpio::{lp_io::IntoLowPowerPin, Io}, + gpio::{lp_io::LowPowerOutput, Io}, lp_core::{LpCore, LpCoreWakeupSource}, peripherals::Peripherals, prelude::*, @@ -25,7 +25,7 @@ fn main() -> ! { // configure GPIO 1 as LP output pin let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); - let lp_pin = io.pins.gpio1.into_low_power().into_push_pull_output(); + let lp_pin = LowPowerOutput::new(io.pins.gpio1); let mut lp_core = LpCore::new(peripherals.LP_CORE); lp_core.stop(); diff --git a/examples/src/bin/lp_core_i2c.rs b/examples/src/bin/lp_core_i2c.rs index 4f813cf9b..a0d3646e2 100644 --- a/examples/src/bin/lp_core_i2c.rs +++ b/examples/src/bin/lp_core_i2c.rs @@ -12,7 +12,7 @@ use esp_backtrace as _; use esp_hal::{ - gpio::{lp_io::IntoLowPowerPin, Io}, + gpio::{lp_io::LowPowerOutputOpenDrain, Io}, i2c::lp_i2c::LpI2c, lp_core::{LpCore, LpCoreWakeupSource}, peripherals::Peripherals, @@ -26,8 +26,8 @@ fn main() -> ! { let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); - let lp_sda = io.pins.gpio6.into_low_power().into_open_drain_output(); - let lp_scl = io.pins.gpio7.into_low_power().into_open_drain_output(); + let lp_sda = LowPowerOutputOpenDrain::new(io.pins.gpio6); + let lp_scl = LowPowerOutputOpenDrain::new(io.pins.gpio7); let lp_i2c = LpI2c::new(peripherals.LP_I2C0, lp_sda, lp_scl, 100.kHz()); diff --git a/examples/src/bin/lp_core_uart.rs b/examples/src/bin/lp_core_uart.rs index 04f2c2fbb..b9d0823f3 100644 --- a/examples/src/bin/lp_core_uart.rs +++ b/examples/src/bin/lp_core_uart.rs @@ -13,7 +13,10 @@ use esp_backtrace as _; use esp_hal::{ clock::ClockControl, - gpio::{lp_io::IntoLowPowerPin, Io}, + gpio::{ + lp_io::{LowPowerInput, LowPowerOutput}, + Io, + }, lp_core::{LpCore, LpCoreWakeupSource}, peripherals::Peripherals, prelude::*, @@ -32,10 +35,7 @@ fn main() -> ! { // Set up (HP) UART1: - let pins = TxRxPins::new_tx_rx( - io.pins.gpio6.into_push_pull_output(), - io.pins.gpio7.into_floating_input(), - ); + let pins = TxRxPins::new_tx_rx(io.pins.gpio6, io.pins.gpio7); let mut uart1 = Uart::new_with_config( peripherals.UART1, @@ -46,8 +46,8 @@ fn main() -> ! { ); // Set up (LP) UART: - let lp_tx = io.pins.gpio5.into_low_power().into_push_pull_output(); - let lp_rx = io.pins.gpio4.into_low_power().into_floating_input(); + let lp_tx = LowPowerOutput::new(io.pins.gpio5); + let lp_rx = LowPowerInput::new(io.pins.gpio4); let lp_uart = LpUart::new(peripherals.LP_UART, lp_tx, lp_rx); let mut lp_core = LpCore::new(peripherals.LP_CORE); diff --git a/examples/src/bin/pcnt_encoder.rs b/examples/src/bin/pcnt_encoder.rs index 0f081ee76..9fe5e643b 100644 --- a/examples/src/bin/pcnt_encoder.rs +++ b/examples/src/bin/pcnt_encoder.rs @@ -16,9 +16,13 @@ use core::{cell::RefCell, cmp::min, sync::atomic::Ordering}; use critical_section::Mutex; use esp_backtrace as _; use esp_hal::{ - gpio::Io, + gpio::{Io, Pull}, interrupt::Priority, - pcnt::{channel, channel::PcntSource, unit, Pcnt}, + pcnt::{ + channel::{self, PcntInputConfig, PcntSource}, + unit, + Pcnt, + }, peripherals::Peripherals, prelude::*, }; @@ -48,12 +52,12 @@ fn main() -> ! { println!("setup channel 0"); let mut ch0 = u0.get_channel(channel::Number::Channel0); - let mut pin_a = io.pins.gpio4.into_pull_up_input(); - let mut pin_b = io.pins.gpio5.into_pull_up_input(); + let mut pin_a = io.pins.gpio4; + let mut pin_b = io.pins.gpio5; ch0.configure( - PcntSource::from_pin(&mut pin_a), - PcntSource::from_pin(&mut pin_b), + PcntSource::from_pin(&mut pin_a, PcntInputConfig { pull: Pull::Up }), + PcntSource::from_pin(&mut pin_b, PcntInputConfig { pull: Pull::Up }), channel::Config { lctrl_mode: channel::CtrlMode::Reverse, hctrl_mode: channel::CtrlMode::Keep, @@ -67,8 +71,8 @@ fn main() -> ! { println!("setup channel 1"); let mut ch1 = u0.get_channel(channel::Number::Channel1); ch1.configure( - PcntSource::from_pin(&mut pin_b), - PcntSource::from_pin(&mut pin_a), + PcntSource::from_pin(&mut pin_b, PcntInputConfig { pull: Pull::Up }), + PcntSource::from_pin(&mut pin_a, PcntInputConfig { pull: Pull::Up }), channel::Config { lctrl_mode: channel::CtrlMode::Reverse, hctrl_mode: channel::CtrlMode::Keep, diff --git a/examples/src/bin/rmt_rx.rs b/examples/src/bin/rmt_rx.rs index 07a6d0387..e82d9ea1b 100644 --- a/examples/src/bin/rmt_rx.rs +++ b/examples/src/bin/rmt_rx.rs @@ -27,7 +27,7 @@ fn main() -> ! { let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); - let mut out = io.pins.gpio5.into_push_pull_output(); + let mut out = io.pins.gpio5; cfg_if::cfg_if! { if #[cfg(feature = "esp32h2")] { diff --git a/examples/src/bin/sleep_timer.rs b/examples/src/bin/sleep_timer.rs index ae47dec39..b5663e9ca 100644 --- a/examples/src/bin/sleep_timer.rs +++ b/examples/src/bin/sleep_timer.rs @@ -13,7 +13,6 @@ use esp_hal::{ delay::Delay, entry, peripherals::Peripherals, - prelude::*, rtc_cntl::{get_reset_reason, get_wakeup_cause, sleep::TimerWakeupSource, Rtc, SocResetReason}, system::SystemControl, Cpu, diff --git a/examples/src/bin/sleep_timer_ext0.rs b/examples/src/bin/sleep_timer_ext0.rs index 57f225b5c..df45ac30e 100644 --- a/examples/src/bin/sleep_timer_ext0.rs +++ b/examples/src/bin/sleep_timer_ext0.rs @@ -14,7 +14,6 @@ use esp_hal::{ entry, gpio::Io, peripherals::Peripherals, - prelude::*, rtc_cntl::{ get_reset_reason, get_wakeup_cause, diff --git a/examples/src/bin/sleep_timer_ext1.rs b/examples/src/bin/sleep_timer_ext1.rs index b400f95e4..726549c26 100644 --- a/examples/src/bin/sleep_timer_ext1.rs +++ b/examples/src/bin/sleep_timer_ext1.rs @@ -14,7 +14,6 @@ use esp_hal::{ entry, gpio::{Io, RtcPin}, peripherals::Peripherals, - prelude::*, rtc_cntl::{ get_reset_reason, get_wakeup_cause, diff --git a/examples/src/bin/sleep_timer_lpio.rs b/examples/src/bin/sleep_timer_lpio.rs index b3e392d91..3dbf9a171 100644 --- a/examples/src/bin/sleep_timer_lpio.rs +++ b/examples/src/bin/sleep_timer_lpio.rs @@ -14,7 +14,6 @@ use esp_hal::{ entry, gpio::{Io, RtcPinWithResistors}, peripherals::Peripherals, - prelude::*, rtc_cntl::{ get_reset_reason, get_wakeup_cause, diff --git a/examples/src/bin/sleep_timer_rtcio.rs b/examples/src/bin/sleep_timer_rtcio.rs index e1e488c49..cf06e5a62 100644 --- a/examples/src/bin/sleep_timer_rtcio.rs +++ b/examples/src/bin/sleep_timer_rtcio.rs @@ -16,7 +16,6 @@ use esp_hal::{ gpio, gpio::Io, peripherals::Peripherals, - prelude::*, rtc_cntl::{ get_reset_reason, get_wakeup_cause, diff --git a/examples/src/bin/spi_eh1_device_loopback.rs b/examples/src/bin/spi_eh1_device_loopback.rs index 614ea5dd0..26c4496de 100644 --- a/examples/src/bin/spi_eh1_device_loopback.rs +++ b/examples/src/bin/spi_eh1_device_loopback.rs @@ -37,7 +37,7 @@ use esp_backtrace as _; use esp_hal::{ clock::ClockControl, delay::Delay, - gpio::{self, Io}, + gpio::{self, Io, Output}, peripherals::Peripherals, prelude::*, spi::{master::Spi, SpiMode}, @@ -63,20 +63,19 @@ fn main() -> ! { gpio::NO_PIN, ); let spi_bus = RefCell::new(spi_bus); - let mut spi_device_1 = - RefCellDevice::new_no_delay(&spi_bus, io.pins.gpio5.into_push_pull_output()); + let mut spi_device_1 = RefCellDevice::new_no_delay(&spi_bus, Output::new(io.pins.gpio5, false)); cfg_if::cfg_if! { if #[cfg(feature = "esp32")] { let mut spi_device_2 = - RefCellDevice::new_no_delay(&spi_bus, io.pins.gpio13.into_push_pull_output()); + RefCellDevice::new_no_delay(&spi_bus, Output::new(io.pins.gpio13, false)); let mut spi_device_3 = - RefCellDevice::new_no_delay(&spi_bus, io.pins.gpio14.into_push_pull_output()); + RefCellDevice::new_no_delay(&spi_bus, Output::new(io.pins.gpio14,false)); } else { let mut spi_device_2 = - RefCellDevice::new_no_delay(&spi_bus, io.pins.gpio6.into_push_pull_output()); + RefCellDevice::new_no_delay(&spi_bus, Output::new(io.pins.gpio6,false)); let mut spi_device_3 = - RefCellDevice::new_no_delay(&spi_bus, io.pins.gpio7.into_push_pull_output()); + RefCellDevice::new_no_delay(&spi_bus, Output::new(io.pins.gpio7, false)); } } diff --git a/examples/src/bin/spi_loopback.rs b/examples/src/bin/spi_loopback.rs index 3a7e870ef..9129f5007 100644 --- a/examples/src/bin/spi_loopback.rs +++ b/examples/src/bin/spi_loopback.rs @@ -22,7 +22,7 @@ use esp_backtrace as _; use esp_hal::{ clock::ClockControl, delay::Delay, - gpio::Io, + gpio::{any_pin::AnyPin, Io}, peripherals::Peripherals, prelude::*, spi::{master::Spi, SpiMode}, @@ -42,6 +42,9 @@ fn main() -> ! { let mosi = io.pins.gpio4; let cs = io.pins.gpio5; + let miso = AnyPin::new(miso); + let mosi = AnyPin::new(mosi); + let mut spi = Spi::new(peripherals.SPI2, 100.kHz(), SpiMode::Mode0, &clocks).with_pins( Some(sclk), Some(mosi), diff --git a/examples/src/bin/spi_slave_dma.rs b/examples/src/bin/spi_slave_dma.rs index c65cabfd9..32b005501 100644 --- a/examples/src/bin/spi_slave_dma.rs +++ b/examples/src/bin/spi_slave_dma.rs @@ -34,7 +34,7 @@ use esp_hal::{ delay::Delay, dma::{Dma, DmaPriority}, dma_buffers, - gpio::Io, + gpio::{Input, Io, Output, Pull}, peripherals::Peripherals, prelude::*, spi::{ @@ -53,13 +53,13 @@ fn main() -> ! { let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); let slave_sclk = io.pins.gpio0; - let mut master_sclk = io.pins.gpio4.into_push_pull_output(); + let mut master_sclk = Output::new(io.pins.gpio4, false); let slave_miso = io.pins.gpio1; - let master_miso = io.pins.gpio5.into_floating_input(); + let master_miso = Input::new(io.pins.gpio5, Pull::None); let slave_mosi = io.pins.gpio2; - let mut master_mosi = io.pins.gpio8.into_push_pull_output(); + let mut master_mosi = Output::new(io.pins.gpio8, false); let slave_cs = io.pins.gpio3; - let mut master_cs = io.pins.gpio9.into_push_pull_output(); + let mut master_cs = Output::new(io.pins.gpio9, false); master_cs.set_high(); master_sclk.set_low(); master_mosi.set_low(); diff --git a/examples/src/bin/twai.rs b/examples/src/bin/twai.rs index 076ba2b98..2641e0fb4 100644 --- a/examples/src/bin/twai.rs +++ b/examples/src/bin/twai.rs @@ -38,16 +38,17 @@ fn main() -> ! { let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); - // Set the tx pin as open drain. Skip this if using transceivers. - let can_tx_pin = io.pins.gpio0.into_open_drain_output(); + let can_tx_pin = io.pins.gpio0; let can_rx_pin = io.pins.gpio2; // The speed of the CAN bus. const CAN_BAUDRATE: twai::BaudRate = twai::BaudRate::B1000K; + // !!! Use `new` when using a transceiver. `new_no_transceiver` sets TX to open-drain + // Begin configuring the TWAI peripheral. The peripheral is in a reset like // state that prevents transmission but allows configuration. - let mut can_config = twai::TwaiConfiguration::new( + let mut can_config = twai::TwaiConfiguration::new_no_transceiver( peripherals.TWAI0, can_tx_pin, can_rx_pin, diff --git a/examples/src/bin/ulp_riscv_core_basic.rs b/examples/src/bin/ulp_riscv_core_basic.rs index a63942d79..4970dfa95 100644 --- a/examples/src/bin/ulp_riscv_core_basic.rs +++ b/examples/src/bin/ulp_riscv_core_basic.rs @@ -22,7 +22,7 @@ fn main() -> ! { let peripherals = Peripherals::take(); let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); - let pin = io.pins.gpio1.into_low_power().into_push_pull_output(); + let pin = LowPowerOutput::new(io.pins.gpio1); let mut ulp_core = ulp_core::UlpCore::new(peripherals.ULP_RISCV_CORE); diff --git a/hil-test/tests/gpio.rs b/hil-test/tests/gpio.rs index 1cfc878b0..b36f83651 100644 --- a/hil-test/tests/gpio.rs +++ b/hil-test/tests/gpio.rs @@ -18,7 +18,7 @@ use esp_hal::{ clock::ClockControl, delay::Delay, embassy, - gpio::{GpioPin, Input, Io, Output, OutputPin, PullDown, PushPull, Unknown}, + gpio::{Gpio2, Gpio4, GpioPin, Input, Io, Output, Pull}, macros::handler, peripherals::Peripherals, system::SystemControl, @@ -26,16 +26,15 @@ use esp_hal::{ }; static COUNTER: Mutex> = Mutex::new(RefCell::new(0)); -static INPUT_PIN: Mutex>>>> = - Mutex::new(RefCell::new(None)); +static INPUT_PIN: Mutex>>> = Mutex::new(RefCell::new(None)); -struct Context { - io2: GpioPin, 2>, - io4: GpioPin, 4>, +struct Context<'d> { + io2: Input<'d, Gpio2>, + io4: Output<'d, Gpio4>, delay: Delay, } -impl Context { +impl<'d> Context<'d> { pub fn init() -> Self { let peripherals = Peripherals::take(); let system = SystemControl::new(peripherals.SYSTEM); @@ -50,8 +49,8 @@ impl Context { embassy::init(&clocks, timg0); Context { - io2: io.pins.gpio2.into_pull_down_input(), - io4: io.pins.gpio4.into_push_pull_output(), + io2: Input::new(io.pins.gpio2, Pull::Down), + io4: Output::new(io.pins.gpio4, false), delay, } } @@ -60,8 +59,6 @@ impl Context { #[handler] pub fn interrupt_handler() { critical_section::with(|cs| { - use esp_hal::gpio::Pin; - *COUNTER.borrow_ref_mut(cs) += 1; INPUT_PIN .borrow_ref_mut(cs) @@ -75,13 +72,13 @@ pub fn interrupt_handler() { mod tests { use defmt::assert_eq; use embassy_time::{Duration, Timer}; - use esp_hal::gpio::{Event, Pin}; + use esp_hal::gpio::{Event, OutputOpenDrain}; use portable_atomic::{AtomicUsize, Ordering}; use super::*; #[init] - fn init() -> Context { + fn init() -> Context<'static> { let mut ctx = Context::init(); // make sure tests don't interfere with each other ctx.io4.set_low(); @@ -89,7 +86,7 @@ mod tests { } #[test] - async fn test_async_edge(ctx: Context) { + async fn test_async_edge(ctx: Context<'static>) { let counter = AtomicUsize::new(0); let Context { mut io2, mut io4, .. @@ -115,8 +112,8 @@ mod tests { } #[test] - async fn test_a_pin_can_wait(_ctx: Context) { - let mut first = unsafe { GpioPin::::steal() }.into_pull_down_input(); + async fn test_a_pin_can_wait(_ctx: Context<'static>) { + let mut first = Input::new( unsafe { GpioPin::<0>::steal() } , Pull::Down); embassy_futures::select::select( first.wait_for_rising_edge(), @@ -128,14 +125,14 @@ mod tests { } #[test] - fn test_gpio_input(ctx: Context) { + fn test_gpio_input(ctx: Context<'static>) { // `InputPin`: assert_eq!(ctx.io2.is_low(), true); assert_eq!(ctx.io2.is_high(), false); } #[test] - fn test_gpio_output(mut ctx: Context) { + fn test_gpio_output(mut ctx: Context<'static>) { // `StatefulOutputPin`: assert_eq!(ctx.io4.is_set_low(), true); assert_eq!(ctx.io4.is_set_high(), false); @@ -154,7 +151,7 @@ mod tests { #[test] #[cfg(not(any(feature = "esp32", feature = "esp32s2", feature = "esp32s3")))] - fn test_gpio_interrupt(mut ctx: Context) { + fn test_gpio_interrupt(mut ctx: Context<'static>) { critical_section::with(|cs| { *COUNTER.borrow_ref_mut(cs) = 0; ctx.io2.listen(Event::AnyEdge); @@ -187,14 +184,10 @@ mod tests { } #[test] - fn test_gpio_od(ctx: Context) { - let mut io2 = ctx.io2.into_open_drain_output(); - io2.internal_pull_up(true); - let mut io4 = ctx.io4.into_open_drain_output(); - io4.internal_pull_up(true); + fn test_gpio_od(ctx: Context<'static>) { + let mut io2 = OutputOpenDrain::new(unsafe { GpioPin::<2>::steal() }, true, Pull::Up); + let mut io4 = OutputOpenDrain::new(unsafe { GpioPin::<4>::steal() }, true, Pull::Up); - io2.set_high(); - io4.set_high(); ctx.delay.delay_millis(1); assert_eq!(io2.is_high(), true); @@ -220,5 +213,20 @@ mod tests { assert_eq!(io2.is_low(), true); assert_eq!(io4.is_low(), true); + + io2.set_high(); + io4.set_high(); + ctx.delay.delay_millis(1); + + assert_eq!(io2.is_high(), true); + assert_eq!(io4.is_high(), true); + + io2.set_low(); + io4.set_low(); + ctx.delay.delay_millis(1); + + assert_eq!(io2.is_low(), true); + assert_eq!(io4.is_low(), true); + } } diff --git a/hil-test/tests/uart.rs b/hil-test/tests/uart.rs index b2418cf71..c5c0fdbcd 100644 --- a/hil-test/tests/uart.rs +++ b/hil-test/tests/uart.rs @@ -37,10 +37,7 @@ impl Context { let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); - let pins = TxRxPins::new_tx_rx( - io.pins.gpio2.into_push_pull_output(), - io.pins.gpio4.into_floating_input(), - ); + let pins = TxRxPins::new_tx_rx(io.pins.gpio2, io.pins.gpio4); let uart = Uart::new_with_config( peripherals.UART0, diff --git a/hil-test/tests/uart_async.rs b/hil-test/tests/uart_async.rs index 4a282f95d..6b1ff31de 100644 --- a/hil-test/tests/uart_async.rs +++ b/hil-test/tests/uart_async.rs @@ -33,10 +33,7 @@ impl Context { let system = SystemControl::new(peripherals.SYSTEM); let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); - let pins = TxRxPins::new_tx_rx( - io.pins.gpio2.into_push_pull_output(), - io.pins.gpio4.into_floating_input(), - ); + let pins = TxRxPins::new_tx_rx(io.pins.gpio2, io.pins.gpio4); let uart = Uart::new_async_with_config(peripherals.UART0, Config::default(), Some(pins), &clocks);