Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion examples/rt685s-evk/src/bin/clocks-blinky.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

use defmt::{error, info};
use embassy_executor::Spawner;
use embassy_imxrt::iopctl::IopctlPin;
use embassy_imxrt::iopctl::{IopctlFunctionPin, IopctlPin};
use embassy_imxrt::{clocks, gpio};
use embassy_time::Timer;
use {defmt_rtt as _, embassy_imxrt as _, embassy_imxrt_examples as _, panic_probe as _};
Expand Down
78 changes: 50 additions & 28 deletions src/adc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,18 @@

use core::future::poll_fn;
use core::marker::PhantomData;
use core::ops::Deref;
use core::task::Poll;

use embassy_hal_internal::interrupt::InterruptExt;
use embassy_hal_internal::{impl_peripheral, Peri, PeripheralType};
use embassy_hal_internal::{Peri, PeripheralType};
use embassy_sync::waitqueue::AtomicWaker;

use crate::clocks::enable_and_reset;
use crate::interrupt::typelevel::Binding;
use crate::iopctl::{DriveMode, DriveStrength, Function, Inverter, IopctlPin, Pull, SlewRate};
use crate::iopctl::{
AnyPin, DriveMode, DriveStrength, Function, Inverter, IopctlFunctionPin, IopctlPin, Pull, SlewRate,
};
use crate::pac::adc0;
use crate::peripherals::ADC0;
use crate::{interrupt, peripherals};
Expand Down Expand Up @@ -45,16 +48,16 @@ impl Default for Config {
/// ADC channel config
pub struct ChannelConfig<'d> {
/// Positive channel to sample
p_channel: Peri<'d, AnyInput>,
p_channel: GuardedAnyInput<'d>,
/// An optional negative channel to sample
n_channel: Option<Peri<'d, AnyInput>>,
n_channel: Option<GuardedAnyInput<'d>>,
}

impl<'d> ChannelConfig<'d> {
/// Default configuration for single ended channel sampling.
pub fn single_ended(input: Peri<'d, impl Input>) -> Self {
pub fn single_ended(p_input: Peri<'d, impl Input>) -> Self {
Self {
p_channel: input.into(),
p_channel: GuardedAnyInput::from(p_input),
n_channel: None,
}
}
Expand All @@ -68,8 +71,8 @@ impl<'d> ChannelConfig<'d> {
}

Ok(Self {
p_channel: p_input.into(),
n_channel: Some(n_input.into()),
p_channel: GuardedAnyInput::from(p_input),
n_channel: Some(GuardedAnyInput::from(n_input)),
})
}
}
Expand All @@ -92,6 +95,7 @@ impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandl
/// ADC driver
pub struct Adc<'p, const N: usize> {
info: Info,
channels: [ChannelConfig<'p>; N],
_lifetime: PhantomData<&'p ()>,
}

Expand Down Expand Up @@ -163,13 +167,13 @@ impl<const N: usize> Adc<'_, N> {
self.info.regs.ctrl().modify(|_, w| w.rstfifo().rstfifo_1());
}

fn configure_channels(&mut self, channel_config: &[ChannelConfig; N]) {
let mut cmd = channel_config.len();
fn configure_channels(&mut self) {
let mut cmd = self.channels.len();

// Configure conversion CMD configuration
// Set up a cmd chain, one cmd per channel
// one points to the next, last one points to 0
for ch in channel_config {
for ch in &self.channels {
// Mapping cmd [1-15] into reg array index [0-14]
// Reg array index is one less than cmd
let cmd_index = cmd - 1;
Expand Down Expand Up @@ -218,7 +222,7 @@ impl<const N: usize> Adc<'_, N> {
.tdly()
.bits(0)
.tcmd()
.bits(channel_config.len() as u8)
.bits(self.channels.len() as u8)
});
}
}
Expand All @@ -229,16 +233,17 @@ impl<'p, const N: usize> Adc<'p, N> {
_adc: Peri<'p, T>,
_irq: impl Binding<T::Interrupt, InterruptHandler<T>> + 'p,
config: Config,
channel_config: [ChannelConfig; N],
channels: [ChannelConfig<'p>; N],
) -> Self {
let mut inst = Self {
info: T::info(),
channels,
_lifetime: PhantomData,
};

Self::init();
inst.configure_adc(config);
inst.configure_channels(&channel_config);
inst.configure_channels();

// Enable interrupt
interrupt::ADC0.unpend();
Expand Down Expand Up @@ -367,27 +372,17 @@ pub(crate) trait SealedInput {

/// A dual purpose (digital/analog) input that can be used as analog input to ADC peripheral.
#[allow(private_bounds)]
pub trait Input: SealedInput + Into<AnyInput> + PeripheralType + Sized + 'static {
/// Convert this ADC input pin to a type-erased `AnyInput`.
///
/// This allows using several inputs in situations that might require
/// them to be the same type, like putting them in an array.
fn degrade_adc(self) -> AnyInput {
AnyInput {
channel: self.channel(),
}
}
}
pub trait Input: SealedInput + Into<AnyInput> + PeripheralType + Sized + 'static {}

/// A type-erased ADC input.
///
/// This allows using several inputs in situations that might require
/// them to be the same type, like putting them in an array.
pub struct AnyInput {
channel: AdcChannel,
pin: AnyPin,
}

impl_peripheral!(AnyInput);
embassy_hal_internal::impl_peripheral!(AnyInput);

impl SealedInput for AnyInput {
fn channel(&self) -> AdcChannel {
Expand All @@ -397,6 +392,30 @@ impl SealedInput for AnyInput {

impl Input for AnyInput {}

struct GuardedAnyInput<'a> {
inner: Peri<'a, AnyInput>,
}

impl<'a, T: Into<AnyInput> + PeripheralType> From<Peri<'a, T>> for GuardedAnyInput<'a> {
fn from(val: Peri<'a, T>) -> Self {
GuardedAnyInput { inner: val.into() }
}
}

impl<'a> Deref for GuardedAnyInput<'a> {
type Target = Peri<'a, AnyInput>;

fn deref(&self) -> &Self::Target {
&self.inner
}
}

impl Drop for GuardedAnyInput<'_> {
fn drop(&mut self) {
self.inner.pin.reset();
}
}

/// Macro to implement required types for dual purpose pins
macro_rules! impl_pin {
($pin:ident, $ch:ident, $side:ident) => {
Expand Down Expand Up @@ -425,7 +444,10 @@ macro_rules! impl_pin {

impl From<$pin> for crate::adc::AnyInput {
fn from(val: $pin) -> Self {
crate::adc::Input::degrade_adc(val)
crate::adc::AnyInput {
channel: val.channel(),
pin: val.into(),
}
}
}
};
Expand Down
2 changes: 1 addition & 1 deletion src/flexspi/nor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use storage_bus::nor::{
use crate::clocks::enable_and_reset;
#[cfg(feature = "time")]
use crate::flexspi::is_expired;
use crate::iopctl::IopctlPin as Pin;
use crate::iopctl::{IopctlFunctionPin, IopctlPin as Pin};
use crate::pac::flexspi::ahbcr::*;
use crate::pac::flexspi::flshcr1::*;
use crate::pac::flexspi::flshcr2::*;
Expand Down
28 changes: 10 additions & 18 deletions src/gpio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ use embassy_sync::waitqueue::AtomicWaker;
use sealed::Sealed;

use crate::clocks::enable_and_reset;
use crate::iopctl::IopctlPin;
pub use crate::iopctl::{AnyPin, DriveMode, DriveStrength, Function, Inverter, Pull, SlewRate};
pub use crate::iopctl::{AnyGpioPin, DriveMode, DriveStrength, Function, Inverter, Pull, SlewRate};
use crate::iopctl::{IopctlFunctionPin, IopctlPin};
use crate::{interrupt, peripherals, Peri, PeripheralType};

// This should be unique per IMXRT package
Expand Down Expand Up @@ -160,7 +160,7 @@ impl Sense for SenseDisabled {}
/// remain set while not in output mode, so the pin's level will be 'remembered' when it is not in
/// output mode.
pub struct Flex<'d, S: Sense> {
pin: Peri<'d, AnyPin>,
pin: Peri<'d, AnyGpioPin>,
_sense_mode: PhantomData<S>,
}

Expand Down Expand Up @@ -421,7 +421,7 @@ impl<'d> Input<'d> {

#[must_use = "futures do nothing unless you `.await` or poll them"]
struct InputFuture<'d> {
pin: Peri<'d, AnyPin>,
pin: Peri<'d, AnyGpioPin>,
}

impl<'d> InputFuture<'d> {
Expand Down Expand Up @@ -541,7 +541,7 @@ impl<'d> Output<'d> {
}
}

trait SealedPin: IopctlPin {
trait SealedPin: IopctlPin + IopctlFunctionPin {
fn pin_port(&self) -> usize;

fn port(&self) -> usize {
Expand All @@ -562,22 +562,14 @@ trait SealedPin: IopctlPin {

/// GPIO pin trait.
#[allow(private_bounds)]
pub trait GpioPin: SealedPin + Sized + PeripheralType + Into<AnyPin> + 'static {
/// Type-erase the pin.
fn degrade(self) -> AnyPin {
// SAFETY: This is only called within the GpioPin trait, which is only
// implemented within this module on valid pin peripherals and thus
// has been verified to be correct.
unsafe { AnyPin::new(self.port() as u8, self.pin() as u8) }
}
}
pub trait GpioPin: SealedPin + Sized + PeripheralType + Into<AnyGpioPin> + 'static {}

impl SealedPin for AnyPin {
impl SealedPin for AnyGpioPin {
fn pin_port(&self) -> usize {
self.pin_port()
}
}
impl GpioPin for AnyPin {}
impl GpioPin for AnyGpioPin {}

macro_rules! impl_pin {
($pin_periph:ident, $pin_port:expr, $pin_no:expr) => {
Expand All @@ -587,9 +579,9 @@ macro_rules! impl_pin {
}
}
impl GpioPin for crate::peripherals::$pin_periph {}
impl From<crate::peripherals::$pin_periph> for AnyPin {
impl From<crate::peripherals::$pin_periph> for AnyGpioPin {
fn from(value: crate::peripherals::$pin_periph) -> Self {
value.degrade()
unsafe { AnyGpioPin::new(value.port() as u8, value.pin() as u8) }
}
}
};
Expand Down
11 changes: 8 additions & 3 deletions src/i2c/master.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use super::{
};
use crate::flexcomm::FlexcommRef;
use crate::interrupt::typelevel::Interrupt;
use crate::iopctl::GuardedAnyPin;
use crate::pac::i2c0::msttime::{Mstsclhigh, Mstscllow};
use crate::{dma, interrupt, Peri};

Expand Down Expand Up @@ -153,6 +154,8 @@ pub struct I2cMaster<'a, M: Mode> {
_flexcomm: FlexcommRef,
_phantom: PhantomData<M>,
dma_ch: Option<dma::channel::Channel<'a>>,
_sda: GuardedAnyPin<'a>,
_scl: GuardedAnyPin<'a>,
}

/// Represents a duty cycle (percentage of time to hold the SCL line high per bit). Fitting is best-effort / not exact.
Expand Down Expand Up @@ -234,8 +237,8 @@ impl<'a, M: Mode> I2cMaster<'a, M> {
let flexcomm = T::enable(clock);
T::into_i2c();

sda.as_sda();
scl.as_scl();
let sda = SdaPin::as_sda(sda);
let scl = SclPin::as_scl(scl);

let info = T::info();
let regs = info.regs;
Expand Down Expand Up @@ -263,6 +266,8 @@ impl<'a, M: Mode> I2cMaster<'a, M> {
_flexcomm: flexcomm,
_phantom: PhantomData,
dma_ch,
_scl: scl,
_sda: sda,
})
}

Expand All @@ -289,7 +294,7 @@ impl<'a> I2cMaster<'a, Blocking> {
config: Config,
) -> Result<Self> {
force_clear_remediation(&T::info());
Ok(Self::new_inner::<T>(fc, scl, sda, config, None)?)
Self::new_inner::<T>(fc, scl, sda, config, None)
}

fn start(&mut self, address: u16, is_read: bool) -> Result<()> {
Expand Down
Loading