Skip to content

Commit d5575fd

Browse files
committed
Changed I2C, UART and ADC to own GPIO pins for dropping
1 parent 3de660d commit d5575fd

File tree

10 files changed

+277
-178
lines changed

10 files changed

+277
-178
lines changed

examples/rt685s-evk/src/bin/clocks-blinky.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
use defmt::{error, info};
55
use embassy_executor::Spawner;
6-
use embassy_imxrt::iopctl::IopctlPin;
6+
use embassy_imxrt::iopctl::{IopctlFunctionPin, IopctlPin};
77
use embassy_imxrt::{clocks, gpio};
88
use embassy_time::Timer;
99
use {defmt_rtt as _, embassy_imxrt as _, embassy_imxrt_examples as _, panic_probe as _};

src/adc.rs

Lines changed: 50 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,18 @@
44

55
use core::future::poll_fn;
66
use core::marker::PhantomData;
7+
use core::ops::Deref;
78
use core::task::Poll;
89

910
use embassy_hal_internal::interrupt::InterruptExt;
10-
use embassy_hal_internal::{impl_peripheral, Peri, PeripheralType};
11+
use embassy_hal_internal::{Peri, PeripheralType};
1112
use embassy_sync::waitqueue::AtomicWaker;
1213

1314
use crate::clocks::enable_and_reset;
1415
use crate::interrupt::typelevel::Binding;
15-
use crate::iopctl::{DriveMode, DriveStrength, Function, Inverter, IopctlPin, Pull, SlewRate};
16+
use crate::iopctl::{
17+
AnyPin, DriveMode, DriveStrength, Function, Inverter, IopctlFunctionPin, IopctlPin, Pull, SlewRate,
18+
};
1619
use crate::pac::adc0;
1720
use crate::peripherals::ADC0;
1821
use crate::{interrupt, peripherals};
@@ -45,16 +48,16 @@ impl Default for Config {
4548
/// ADC channel config
4649
pub struct ChannelConfig<'d> {
4750
/// Positive channel to sample
48-
p_channel: Peri<'d, AnyInput>,
51+
p_channel: GuardedAnyInput<'d>,
4952
/// An optional negative channel to sample
50-
n_channel: Option<Peri<'d, AnyInput>>,
53+
n_channel: Option<GuardedAnyInput<'d>>,
5154
}
5255

5356
impl<'d> ChannelConfig<'d> {
5457
/// Default configuration for single ended channel sampling.
55-
pub fn single_ended(input: Peri<'d, impl Input>) -> Self {
58+
pub fn single_ended(p_input: Peri<'d, impl Input>) -> Self {
5659
Self {
57-
p_channel: input.into(),
60+
p_channel: GuardedAnyInput::from(p_input),
5861
n_channel: None,
5962
}
6063
}
@@ -68,8 +71,8 @@ impl<'d> ChannelConfig<'d> {
6871
}
6972

7073
Ok(Self {
71-
p_channel: p_input.into(),
72-
n_channel: Some(n_input.into()),
74+
p_channel: GuardedAnyInput::from(p_input),
75+
n_channel: Some(GuardedAnyInput::from(n_input)),
7376
})
7477
}
7578
}
@@ -92,6 +95,7 @@ impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandl
9295
/// ADC driver
9396
pub struct Adc<'p, const N: usize> {
9497
info: Info,
98+
channels: [ChannelConfig<'p>; N],
9599
_lifetime: PhantomData<&'p ()>,
96100
}
97101

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

166-
fn configure_channels(&mut self, channel_config: &[ChannelConfig; N]) {
167-
let mut cmd = channel_config.len();
170+
fn configure_channels(&mut self) {
171+
let mut cmd = self.channels.len();
168172

169173
// Configure conversion CMD configuration
170174
// Set up a cmd chain, one cmd per channel
171175
// one points to the next, last one points to 0
172-
for ch in channel_config {
176+
for ch in &self.channels {
173177
// Mapping cmd [1-15] into reg array index [0-14]
174178
// Reg array index is one less than cmd
175179
let cmd_index = cmd - 1;
@@ -218,7 +222,7 @@ impl<const N: usize> Adc<'_, N> {
218222
.tdly()
219223
.bits(0)
220224
.tcmd()
221-
.bits(channel_config.len() as u8)
225+
.bits(self.channels.len() as u8)
222226
});
223227
}
224228
}
@@ -229,16 +233,17 @@ impl<'p, const N: usize> Adc<'p, N> {
229233
_adc: Peri<'p, T>,
230234
_irq: impl Binding<T::Interrupt, InterruptHandler<T>> + 'p,
231235
config: Config,
232-
channel_config: [ChannelConfig; N],
236+
channels: [ChannelConfig<'p>; N],
233237
) -> Self {
234238
let mut inst = Self {
235239
info: T::info(),
240+
channels,
236241
_lifetime: PhantomData,
237242
};
238243

239244
Self::init();
240245
inst.configure_adc(config);
241-
inst.configure_channels(&channel_config);
246+
inst.configure_channels();
242247

243248
// Enable interrupt
244249
interrupt::ADC0.unpend();
@@ -367,27 +372,17 @@ pub(crate) trait SealedInput {
367372

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

382377
/// A type-erased ADC input.
383378
///
384379
/// This allows using several inputs in situations that might require
385380
/// them to be the same type, like putting them in an array.
386381
pub struct AnyInput {
387382
channel: AdcChannel,
383+
pin: AnyPin,
388384
}
389-
390-
impl_peripheral!(AnyInput);
385+
embassy_hal_internal::impl_peripheral!(AnyInput);
391386

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

398393
impl Input for AnyInput {}
399394

395+
struct GuardedAnyInput<'a> {
396+
inner: Peri<'a, AnyInput>,
397+
}
398+
399+
impl<'a, T: Into<AnyInput> + PeripheralType> From<Peri<'a, T>> for GuardedAnyInput<'a> {
400+
fn from(val: Peri<'a, T>) -> Self {
401+
GuardedAnyInput { inner: val.into() }
402+
}
403+
}
404+
405+
impl<'a> Deref for GuardedAnyInput<'a> {
406+
type Target = Peri<'a, AnyInput>;
407+
408+
fn deref(&self) -> &Self::Target {
409+
&self.inner
410+
}
411+
}
412+
413+
impl Drop for GuardedAnyInput<'_> {
414+
fn drop(&mut self) {
415+
self.inner.pin.reset();
416+
}
417+
}
418+
400419
/// Macro to implement required types for dual purpose pins
401420
macro_rules! impl_pin {
402421
($pin:ident, $ch:ident, $side:ident) => {
@@ -425,7 +444,10 @@ macro_rules! impl_pin {
425444

426445
impl From<$pin> for crate::adc::AnyInput {
427446
fn from(val: $pin) -> Self {
428-
crate::adc::Input::degrade_adc(val)
447+
crate::adc::AnyInput {
448+
channel: val.channel(),
449+
pin: val.into(),
450+
}
429451
}
430452
}
431453
};

src/flexspi/nor.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use storage_bus::nor::{
1616
use crate::clocks::enable_and_reset;
1717
#[cfg(feature = "time")]
1818
use crate::flexspi::is_expired;
19-
use crate::iopctl::IopctlPin as Pin;
19+
use crate::iopctl::{IopctlFunctionPin, IopctlPin as Pin};
2020
use crate::pac::flexspi::ahbcr::*;
2121
use crate::pac::flexspi::flshcr1::*;
2222
use crate::pac::flexspi::flshcr2::*;

src/gpio.rs

Lines changed: 10 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ use embassy_sync::waitqueue::AtomicWaker;
1111
use sealed::Sealed;
1212

1313
use crate::clocks::enable_and_reset;
14-
use crate::iopctl::IopctlPin;
15-
pub use crate::iopctl::{AnyPin, DriveMode, DriveStrength, Function, Inverter, Pull, SlewRate};
14+
pub use crate::iopctl::{AnyGpioPin, DriveMode, DriveStrength, Function, Inverter, Pull, SlewRate};
15+
use crate::iopctl::{IopctlFunctionPin, IopctlPin};
1616
use crate::{interrupt, peripherals, Peri, PeripheralType};
1717

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

@@ -421,7 +421,7 @@ impl<'d> Input<'d> {
421421

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

427427
impl<'d> InputFuture<'d> {
@@ -541,7 +541,7 @@ impl<'d> Output<'d> {
541541
}
542542
}
543543

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

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

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

575-
impl SealedPin for AnyPin {
567+
impl SealedPin for AnyGpioPin {
576568
fn pin_port(&self) -> usize {
577569
self.pin_port()
578570
}
579571
}
580-
impl GpioPin for AnyPin {}
572+
impl GpioPin for AnyGpioPin {}
581573

582574
macro_rules! impl_pin {
583575
($pin_periph:ident, $pin_port:expr, $pin_no:expr) => {
@@ -587,9 +579,9 @@ macro_rules! impl_pin {
587579
}
588580
}
589581
impl GpioPin for crate::peripherals::$pin_periph {}
590-
impl From<crate::peripherals::$pin_periph> for AnyPin {
582+
impl From<crate::peripherals::$pin_periph> for AnyGpioPin {
591583
fn from(value: crate::peripherals::$pin_periph) -> Self {
592-
value.degrade()
584+
unsafe { AnyGpioPin::new(value.port() as u8, value.pin() as u8) }
593585
}
594586
}
595587
};

src/i2c/master.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ use super::{
1515
};
1616
use crate::flexcomm::FlexcommRef;
1717
use crate::interrupt::typelevel::Interrupt;
18+
use crate::iopctl::GuardedAnyPin;
1819
use crate::pac::i2c0::msttime::{Mstsclhigh, Mstscllow};
1920
use crate::{dma, interrupt, Peri};
2021

@@ -153,6 +154,8 @@ pub struct I2cMaster<'a, M: Mode> {
153154
_flexcomm: FlexcommRef,
154155
_phantom: PhantomData<M>,
155156
dma_ch: Option<dma::channel::Channel<'a>>,
157+
_sda: GuardedAnyPin<'a>,
158+
_scl: GuardedAnyPin<'a>,
156159
}
157160

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

237-
sda.as_sda();
238-
scl.as_scl();
240+
let sda = SdaPin::as_sda(sda);
241+
let scl = SclPin::as_scl(scl);
239242

240243
let info = T::info();
241244
let regs = info.regs;
@@ -263,6 +266,8 @@ impl<'a, M: Mode> I2cMaster<'a, M> {
263266
_flexcomm: flexcomm,
264267
_phantom: PhantomData,
265268
dma_ch,
269+
_scl: scl,
270+
_sda: sda,
266271
})
267272
}
268273

@@ -289,7 +294,7 @@ impl<'a> I2cMaster<'a, Blocking> {
289294
config: Config,
290295
) -> Result<Self> {
291296
force_clear_remediation(&T::info());
292-
Ok(Self::new_inner::<T>(fc, scl, sda, config, None)?)
297+
Self::new_inner::<T>(fc, scl, sda, config, None)
293298
}
294299

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

0 commit comments

Comments
 (0)