GPIO Refactoring (#1542)

* GPIO Refactoring

* CHANGELOG.md

* Addressed review comments

* Use `Level` instead of plain bool in public API

* Let drivers enable analog functions
This commit is contained in:
Björn Quentin 2024-05-15 10:49:33 +02:00 committed by GitHub
parent 68628fc008
commit 2faa2654cb
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
76 changed files with 2798 additions and 2151 deletions

View File

@ -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<Section> = 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<u8> = 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<proc_macro2::TokenStream> = 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<u8> = 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<Ident> = 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

View File

@ -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(&quoted);
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(&quoted);
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 = (&quote! { #c }.to_string()).parse().unwrap();
}
_ => (),
}
GenericArgument::Const(c) => {
res = (&quote! { #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(&quote! { #c }.to_string());
}
_ => (),
match arg {
GenericArgument::Type(t) => {
pushed = true;
res.push_str(&to_string(t));
}
GenericArgument::Const(c) => {
pushed = true;
res.push_str(&quote! { #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<u8> = 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<Ident> = 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<Section> = 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<u8> = 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<proc_macro2::TokenStream> = 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()
}

View File

@ -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

View File

@ -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 }

View File

@ -9,7 +9,7 @@
//! ```no_run
//! let mut adc1_config = AdcConfig::new();
//! let mut adc1 = ADC::<ADC1>::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<ADCI> AdcConfig<ADCI> {
/// Enable the specified pin with the given attenuation
pub fn enable_pin<PIN>(&mut self, pin: PIN, attenuation: Attenuation) -> AdcPin<PIN, ADCI>
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<ADCI> AdcConfig<ADCI> {
}
}
/// 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<PIN, CS>(
@ -114,9 +117,11 @@ impl<ADCI> AdcConfig<ADCI> {
) -> AdcPin<PIN, ADCI, CS>
where
ADCI: CalibrationAccess,
PIN: AdcChannel,
PIN: AdcChannel + AnalogPin,
CS: AdcCalScheme<ADCI>,
{
// 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<crate::gpio::Analog> {
impl $crate::analog::adc::AdcChannel for crate::gpio::$pin {
const CHANNEL: u8 = $channel;
}
#[cfg(feature = "embedded-hal-02")]
impl embedded_hal_02::adc::Channel<crate::peripherals::$adc> for crate::gpio::$pin<crate::gpio::Analog> {
impl embedded_hal_02::adc::Channel<crate::peripherals::$adc> for crate::gpio::$pin {
type ID = u8;
fn channel() -> u8 { $channel }

View File

@ -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<gpio::Analog>;
type Dac2Gpio = gpio::Gpio26<gpio::Analog>;
type Dac1Gpio = gpio::Gpio25;
type Dac2Gpio = gpio::Gpio26;
} else if #[cfg(esp32s2)] {
type Dac1Gpio = gpio::Gpio17<gpio::Analog>;
type Dac2Gpio = gpio::Gpio18<gpio::Analog>;
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<P = peripherals::DAC1> + 'd, _pin: Dac1Gpio) -> Self {
pub fn new(dac: impl Peripheral<P = peripherals::DAC1> + '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<P = peripherals::DAC2> + 'd, _pin: Dac2Gpio) -> Self {
pub fn new(dac: impl Peripheral<P = peripherals::DAC2> + '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 }

286
esp-hal/src/gpio/any_pin.rs Normal file
View File

@ -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<P: OutputPin + InputPin + CreateErasedPin>(
pin: impl crate::peripheral::Peripheral<P = P> + '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<P: OutputPin + InputPin + CreateErasedPin>(
pin: impl crate::peripheral::Peripheral<P = P> + '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<P: InputPin + CreateErasedPin>(
pin: impl crate::peripheral::Peripheral<P = P> + '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);
}
}
}

View File

@ -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<const C: u8> {}
@ -87,12 +114,20 @@ impl<const C: u8> GpioEtmEventChannel<C> {
pub fn rising_edge<'d, PIN>(
self,
pin: impl Peripheral<P = PIN> + '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<const C: u8> GpioEtmEventChannel<C> {
pub fn falling_edge<'d, PIN>(
self,
pin: impl Peripheral<P = PIN> + '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<const C: u8> GpioEtmEventChannel<C> {
pub fn any_edge<'d, PIN>(
self,
pin: impl Peripheral<P = PIN> + '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<const C: u8> {}
@ -202,22 +275,50 @@ impl<const C: u8> GpioEtmTaskChannel<C> {
// number is the pin-count
/// Task to set a high level
pub fn set<'d, PIN>(self, pin: impl Peripheral<P = PIN> + 'd) -> GpioEtmTaskSet<'d, PIN, C>
pub fn set<'d, PIN>(
self,
pin: impl Peripheral<P = PIN> + '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<P = PIN> + 'd) -> GpioEtmTaskClear<'d, PIN, C>
pub fn clear<'d, PIN>(
self,
pin: impl Peripheral<P = PIN> + '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<const C: u8> GpioEtmTaskChannel<C> {
pub fn toggle<'d, PIN>(
self,
pin: impl Peripheral<P = PIN> + '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

View File

@ -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<MODE, const PIN: u8> {
pub(crate) private: PhantomData<MODE>,
/// A GPIO output pin configured for low power operation
pub struct LowPowerOutput<'d, const PIN: u8> {
phantom: PhantomData<&'d ()>,
}
impl<MODE, const PIN: u8> LowPowerPin<MODE, PIN> {
#[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<P>(_pin: impl crate::peripheral::Peripheral<P = P> + '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<P>(_pin: impl crate::peripheral::Peripheral<P = P> + '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<P>(_pin: impl crate::peripheral::Peripheral<P = P> + '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<MODE, const PIN: u8> LowPowerPin<MODE, PIN> {
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<Input<PullUp>, 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<Input<PullDown>, 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<Input<Floating>, 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<Output<PushPull>, 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<OpenDrain, PIN> {
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<const PIN: u8> {
/// Converts the pin into a low power pin
fn into_low_power(self) -> LowPowerPin<Unknown, { PIN }>;
}
#[doc(hidden)]
#[macro_export]
macro_rules! lp_gpio {
@ -171,16 +187,7 @@ macro_rules! lp_gpio {
) => {
paste::paste!{
$(
impl<MODE> $crate::gpio::lp_io::IntoLowPowerPin<$gpionum> for GpioPin<MODE, $gpionum> {
fn into_low_power(self) -> $crate::gpio::lp_io::LowPowerPin<Unknown, $gpionum> {
$crate::gpio::lp_io::init_low_power_pin($gpionum);
$crate::gpio::lp_io::LowPowerPin {
private: core::marker::PhantomData,
}
}
}
impl<MODE> $crate::gpio::RtcPin for GpioPin<MODE, $gpionum> {
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<MODE> $crate::gpio::RtcPinWithResistors for GpioPin<MODE, $gpionum> {
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;

File diff suppressed because it is too large Load Diff

View File

@ -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<MODE, const PIN: u8> {
pub(crate) private: PhantomData<MODE>,
/// 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<const PIN: u8> {
/// Convert into low power pin
fn into_low_power(self) -> LowPowerPin<Unknown, { PIN }>;
impl<'d, const PIN: u8> LowPowerOutput<'d, PIN> {
/// Create a new output pin for use by the low-power core
pub fn new<P>(pin: impl crate::peripheral::Peripheral<P = P> + '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<MODE, const PIN: u8> LowPowerPin<MODE, PIN> {
#[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<P>(pin: impl crate::peripheral::Peripheral<P = P> + '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<P>(pin: impl crate::peripheral::Peripheral<P = P> + '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<MODE, const PIN: u8> LowPowerPin<MODE, PIN> {
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<Input<PullUp>, 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<Input<PullDown>, 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<Input<Floating>, 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<Output<PushPull>, 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<OpenDrain, PIN> {
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));
}
}

View File

@ -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<OpenDrain, 6>,
_scl: LowPowerPin<OpenDrain, 7>,
_sda: LowPowerOutputOpenDrain<6>,
_scl: LowPowerOutputOpenDrain<7>,
frequency: HertzU32,
) -> Self {
let me = Self { i2c };

View File

@ -578,8 +578,8 @@ where
pub fn with_mclk<P: OutputPin>(self, pin: impl Peripheral<P = P> + '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
}
}

View File

@ -221,8 +221,8 @@ impl<'d, RX: Rx> Camera<'d, RX> {
pub fn with_master_clock<MCLK: OutputPin>(self, mclk: impl Peripheral<P = MCLK> + '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: () }
}

View File

@ -254,8 +254,8 @@ where
pub fn with_cs<CS: OutputPin>(self, cs: impl Peripheral<P = CS> + '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);
}
}

View File

@ -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);
}

View File

@ -220,6 +220,8 @@ impl crate::private::Sealed for Async {}
pub(crate) mod private {
pub trait Sealed {}
pub struct Internal;
}
/// Available CPU cores

View File

@ -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();

View File

@ -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::<OP, IS_A>();
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
}

View File

@ -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 >]);

View File

@ -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<P = P> + 'a) -> Self {
pub fn from_pin<'a, P: InputPin>(
pin: impl Peripheral<P = P> + '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 {

View File

@ -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,

View File

@ -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,

View File

@ -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,
};

View File

@ -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,
})
});
}
}

View File

@ -52,7 +52,6 @@ use crate::{
InterruptStatusRegisterAccess,
InterruptStatusRegisterAccessBank0,
InterruptStatusRegisterAccessBank1,
Unknown,
},
peripherals::GPIO,
Cpu,

View File

@ -45,7 +45,6 @@ use crate::{
GpioPin,
InterruptStatusRegisterAccess,
InterruptStatusRegisterAccessBank0,
Unknown,
},
peripherals::GPIO,
};

View File

@ -46,7 +46,6 @@ use crate::{
GpioPin,
InterruptStatusRegisterAccess,
InterruptStatusRegisterAccessBank0,
Unknown,
},
peripherals::GPIO,
};

View File

@ -46,7 +46,6 @@ use crate::{
GpioPin,
InterruptStatusRegisterAccess,
InterruptStatusRegisterAccessBank0,
Unknown,
},
peripherals::GPIO,
};

View File

@ -46,7 +46,6 @@ use crate::{
GpioPin,
InterruptStatusRegisterAccess,
InterruptStatusRegisterAccessBank0,
Unknown,
},
peripherals::GPIO,
};

View File

@ -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<T> crate::otg_fs::UsbDp for Gpio19<T> {}
impl<T> crate::otg_fs::UsbDm for Gpio20<T> {}
impl crate::otg_fs::UsbDp for Gpio19 {}
impl crate::otg_fs::UsbDm for Gpio20 {}

View File

@ -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<T> crate::otg_fs::UsbDp for Gpio19<T> {}
impl<T> crate::otg_fs::UsbDm for Gpio20<T> {}
impl crate::otg_fs::UsbDp for Gpio19 {}
impl crate::otg_fs::UsbDm for Gpio20 {}

View File

@ -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<SCK: OutputPin>(self, sck: impl Peripheral<P = SCK> + '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<MOSI: OutputPin>(self, mosi: impl Peripheral<P = MOSI> + '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<MISO: InputPin>(self, miso: impl Peripheral<P = MISO> + '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<CS: OutputPin>(self, cs: impl Peripheral<P = CS> + '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<SCK: OutputPin>(self, sck: impl Peripheral<P = SCK> + '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<P = MOSI> + '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<P = MISO> + '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<P = SIO2> + '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<P = SIO3> + '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<CS: OutputPin>(self, cs: impl Peripheral<P = CS> + '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;

View File

@ -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;

View File

@ -42,7 +42,7 @@ pub struct SystemTimer<'d, DM: crate::Mode> {
pub alarm0: Alarm<Target, DM, 0>,
pub alarm1: Alarm<Target, DM, 1>,
pub alarm2: Alarm<Target, DM, 2>,
_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,
}
}
}

View File

@ -646,14 +646,18 @@ where
clocks: &Clocks,
baud_rate: BaudRate,
interrupt: Option<InterruptHandler>,
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<TX: OutputPin, RX: InputPin>(
peripheral: impl Peripheral<P = T> + 'd,
tx_pin: impl Peripheral<P = TX> + 'd,
@ -783,7 +790,27 @@ where
baud_rate: BaudRate,
interrupt: Option<InterruptHandler>,
) -> 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<TX: OutputPin, RX: InputPin>(
peripheral: impl Peripheral<P = T> + 'd,
tx_pin: impl Peripheral<P = TX> + 'd,
rx_pin: impl Peripheral<P = RX> + 'd,
clocks: &Clocks,
baud_rate: BaudRate,
interrupt: Option<InterruptHandler>,
) -> 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<TX: OutputPin, RX: InputPin>(
peripheral: impl Peripheral<P = T> + 'd,
tx_pin: impl Peripheral<P = TX> + '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<TX: OutputPin, RX: InputPin>(
peripheral: impl Peripheral<P = T> + 'd,
tx_pin: impl Peripheral<P = TX> + 'd,
rx_pin: impl Peripheral<P = RX> + '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,
)
}
}

View File

@ -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<TX: OutputPin, RX: InputPin, CTS: InputPin, RTS: OutputPin> 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<TX: OutputPin, RX: InputPin> 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<Output<PushPull>, 5>,
_rx: LowPowerPin<Input<Floating>, 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 };

View File

@ -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",
]

View File

@ -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

View File

@ -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<Output<PushPull>, 1>) -> ! {
fn main(mut gpio1: Output<1>) -> ! {
let mut i: u32 = 0;
let ptr = ADDRESS as *mut u32;

View File

@ -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<const PIN: u8> {}
pub struct Input<MODE> {
_mode: PhantomData<MODE>,
}
pub struct Floating;
pub struct PullDown;
pub struct PullUp;
pub struct Output<MODE> {
_mode: PhantomData<MODE>,
}
pub struct PushPull;
pub struct GpioPin<MODE, const PIN: u8> {
phantom: PhantomData<MODE>,
}
impl<MODE, const PIN: u8> GpioPin<Input<MODE>, PIN> {
impl<const PIN: u8> Input<PIN> {
pub fn input_state(&self) -> bool {
unsafe { &*LpIo::PTR }.in_().read().bits() >> PIN & 0x1 != 0
}
}
impl<MODE, const PIN: u8> GpioPin<Output<MODE>, PIN> {
#[non_exhaustive]
pub struct Output<const PIN: u8> {}
impl<const PIN: u8> Output<PIN> {
pub fn output_state(&self) -> bool {
unsafe { &*LpIo::PTR }.out().read().bits() >> PIN & 0x1 != 0
}
@ -57,18 +39,26 @@ impl<MODE, const PIN: u8> GpioPin<Output<MODE>, PIN> {
// Used by the `entry` procmacro:
#[doc(hidden)]
pub unsafe fn conjure<MODE, const PIN: u8>() -> Option<GpioPin<MODE, PIN>> {
pub unsafe fn conjure_output<const PIN: u8>() -> Option<Output<PIN>> {
if PIN > 7 {
None
} else {
Some(GpioPin {
phantom: PhantomData,
})
Some(Output {})
}
}
// Used by the `entry` procmacro:
#[doc(hidden)]
pub unsafe fn conjure_input<const PIN: u8>() -> Option<Input<PIN>> {
if PIN > 7 {
None
} else {
Some(Input {})
}
}
#[cfg(feature = "embedded-hal-02")]
impl<MODE, const PIN: u8> embedded_hal_02::digital::v2::InputPin for GpioPin<Input<MODE>, PIN> {
impl<const PIN: u8> embedded_hal_02::digital::v2::InputPin for Input<PIN> {
type Error = core::convert::Infallible;
fn is_high(&self) -> Result<bool, Self::Error> {
@ -81,7 +71,7 @@ impl<MODE, const PIN: u8> embedded_hal_02::digital::v2::InputPin for GpioPin<Inp
}
#[cfg(feature = "embedded-hal-02")]
impl<MODE, const PIN: u8> embedded_hal_02::digital::v2::OutputPin for GpioPin<Output<MODE>, PIN> {
impl<const PIN: u8> embedded_hal_02::digital::v2::OutputPin for Output<PIN> {
type Error = core::convert::Infallible;
fn set_low(&mut self) -> Result<(), Self::Error> {
@ -96,9 +86,7 @@ impl<MODE, const PIN: u8> embedded_hal_02::digital::v2::OutputPin for GpioPin<Ou
}
#[cfg(feature = "embedded-hal-02")]
impl<MODE, const PIN: u8> embedded_hal_02::digital::v2::StatefulOutputPin
for GpioPin<Output<MODE>, PIN>
{
impl<const PIN: u8> embedded_hal_02::digital::v2::StatefulOutputPin for Output<PIN> {
fn is_set_high(&self) -> Result<bool, Self::Error> {
Ok(self.output_state())
}
@ -109,18 +97,20 @@ impl<MODE, const PIN: u8> embedded_hal_02::digital::v2::StatefulOutputPin
}
#[cfg(feature = "embedded-hal-02")]
impl<MODE, const PIN: u8> embedded_hal_02::digital::v2::toggleable::Default
for GpioPin<Output<MODE>, PIN>
{
}
impl<const PIN: u8> embedded_hal_02::digital::v2::toggleable::Default for Output<PIN> {}
#[cfg(feature = "embedded-hal-1")]
impl<MODE, const PIN: u8> embedded_hal_1::digital::ErrorType for GpioPin<MODE, PIN> {
impl<const PIN: u8> embedded_hal_1::digital::ErrorType for Input<PIN> {
type Error = core::convert::Infallible;
}
#[cfg(feature = "embedded-hal-1")]
impl<MODE, const PIN: u8> embedded_hal_1::digital::InputPin for GpioPin<Input<MODE>, PIN> {
impl<const PIN: u8> embedded_hal_1::digital::ErrorType for Output<PIN> {
type Error = core::convert::Infallible;
}
#[cfg(feature = "embedded-hal-1")]
impl<const PIN: u8> embedded_hal_1::digital::InputPin for Input<PIN> {
fn is_high(&mut self) -> Result<bool, Self::Error> {
Ok(self.input_state())
}
@ -131,7 +121,7 @@ impl<MODE, const PIN: u8> embedded_hal_1::digital::InputPin for GpioPin<Input<MO
}
#[cfg(feature = "embedded-hal-1")]
impl<MODE, const PIN: u8> embedded_hal_1::digital::OutputPin for GpioPin<Output<MODE>, PIN> {
impl<const PIN: u8> embedded_hal_1::digital::OutputPin for Output<PIN> {
fn set_low(&mut self) -> Result<(), Self::Error> {
self.set_output(false);
Ok(())
@ -144,9 +134,7 @@ impl<MODE, const PIN: u8> embedded_hal_1::digital::OutputPin for GpioPin<Output<
}
#[cfg(feature = "embedded-hal-1")]
impl<MODE, const PIN: u8> embedded_hal_1::digital::StatefulOutputPin
for GpioPin<Output<MODE>, PIN>
{
impl<const PIN: u8> embedded_hal_1::digital::StatefulOutputPin for Output<PIN> {
fn is_set_high(&mut self) -> Result<bool, Self::Error> {
Ok(self.output_state())
}

View File

@ -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;
}
}

View File

@ -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<ADC1>;
//type AdcCal = ();
type AdcCal = esp_hal::analog::adc::AdcCalBasic<esp_hal::peripherals::ADC1>;
// type AdcCal = esp_hal::analog::adc::AdcCalLine<ADC1>;
// type AdcCal = esp_hal::analog::adc::AdcCalCurve<ADC1>;

View File

@ -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,

View File

@ -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.

View File

@ -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<Output<PushPull>>], button: &AnyPin<Input<PullDown>>) {
fn toggle_pins(leds: &mut [AnyOutput], button: &AnyInput) {
for pin in leds.iter_mut() {
pin.toggle();
}

View File

@ -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;
}
}

View File

@ -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<Output<PushPull>, 0>,
mut led: AnyOutput<'static>,
control: &'static Signal<CriticalSectionRawMutex, bool>,
) {
println!("Starting control_led() on core {}", get_core() as usize);
@ -66,7 +66,7 @@ async fn main(_spawner: Spawner) {
static LED_CTRL: StaticCell<Signal<CriticalSectionRawMutex, bool>> = 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 || {

View File

@ -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<Output<PushPull>, 0>,
mut led: AnyOutput<'static>,
control: &'static Signal<CriticalSectionRawMutex, bool>,
) {
println!("Starting control_led() on core {}", get_core() as usize);
@ -85,7 +85,7 @@ fn main() -> ! {
static LED_CTRL: StaticCell<Signal<CriticalSectionRawMutex, bool>> = 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<InterruptExecutor<1>> = StaticCell::new();
let executor_core1 =

View File

@ -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<Output<PushPull>>) {
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 {

View File

@ -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()

View File

@ -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,

View File

@ -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...");

View File

@ -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);

View File

@ -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;

View File

@ -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<RefCell<Option<gpio::Gpio0<Input<PullDown>>>>> =
Mutex::new(RefCell::new(None));
static BUTTON: Mutex<RefCell<Option<Input<gpio::Gpio0>>>> = Mutex::new(RefCell::new(None));
#[cfg(not(any(feature = "esp32", feature = "esp32s2", feature = "esp32s3")))]
static BUTTON: Mutex<RefCell<Option<gpio::Gpio9<Input<PullDown>>>>> =
Mutex::new(RefCell::new(None));
static BUTTON: Mutex<RefCell<Option<Input<gpio::Gpio9>>>> = 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);

View File

@ -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,

View File

@ -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);

View File

@ -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();

View File

@ -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());

View File

@ -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);

View File

@ -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,

View File

@ -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")] {

View File

@ -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,

View File

@ -14,7 +14,6 @@ use esp_hal::{
entry,
gpio::Io,
peripherals::Peripherals,
prelude::*,
rtc_cntl::{
get_reset_reason,
get_wakeup_cause,

View File

@ -14,7 +14,6 @@ use esp_hal::{
entry,
gpio::{Io, RtcPin},
peripherals::Peripherals,
prelude::*,
rtc_cntl::{
get_reset_reason,
get_wakeup_cause,

View File

@ -14,7 +14,6 @@ use esp_hal::{
entry,
gpio::{Io, RtcPinWithResistors},
peripherals::Peripherals,
prelude::*,
rtc_cntl::{
get_reset_reason,
get_wakeup_cause,

View File

@ -16,7 +16,6 @@ use esp_hal::{
gpio,
gpio::Io,
peripherals::Peripherals,
prelude::*,
rtc_cntl::{
get_reset_reason,
get_wakeup_cause,

View File

@ -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));
}
}

View File

@ -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),

View File

@ -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();

View File

@ -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,

View File

@ -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);

View File

@ -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<RefCell<u32>> = Mutex::new(RefCell::new(0));
static INPUT_PIN: Mutex<RefCell<Option<esp_hal::gpio::Gpio2<Input<PullDown>>>>> =
Mutex::new(RefCell::new(None));
static INPUT_PIN: Mutex<RefCell<Option<Input<'static, Gpio2>>>> = Mutex::new(RefCell::new(None));
struct Context {
io2: GpioPin<Input<PullDown>, 2>,
io4: GpioPin<Output<PushPull>, 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::<Unknown, 0>::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);
}
}

View File

@ -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,

View File

@ -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);