Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prepare LPSPI driver for embedded-hal 1.0 rework #149

Open
wants to merge 15 commits into
base: main
Choose a base branch
from
17 changes: 11 additions & 6 deletions board/src/imxrt1010evk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,14 +61,17 @@ pub type SpiPins = hal::lpspi::Pins<
iomuxc::gpio_ad::GPIO_AD_04, // SDO, J57_8
iomuxc::gpio_ad::GPIO_AD_03, // SDI, J57_10
iomuxc::gpio_ad::GPIO_AD_06, // SCK, J57_12
iomuxc::gpio_ad::GPIO_AD_05, // PCS0, J57_6
>;

#[cfg(feature = "spi")]
pub type Spi = hal::lpspi::Lpspi<SpiPins, 1>;
#[cfg(feature = "spi")]
pub type SpiCsPin = hal::gpio::Output<iomuxc::gpio_ad::GPIO_AD_05>; // PCS0, J57_6

#[cfg(not(feature = "spi"))]
pub type Spi = ();
#[cfg(not(feature = "spi"))]
pub type SpiCsPin = ();

pub type I2cPins = hal::lpi2c::Pins<
iomuxc::gpio::GPIO_02, // SCL, J57_20
Expand Down Expand Up @@ -145,6 +148,7 @@ pub struct Specifics {
pub ports: GpioPorts,
pub console: Console,
pub spi: Spi,
pub spi_cs: SpiCsPin,
pub i2c: I2c,
pub pwm: Pwm,
pub tp34: Tp34,
Expand All @@ -164,7 +168,7 @@ impl Specifics {
let gpio2 = unsafe { ral::gpio::GPIO2::instance() };
let mut gpio2 = hal::gpio::Port::new(gpio2);

let led = gpio1.output(iomuxc.gpio.p11);
let led = gpio1.output(iomuxc.gpio.p11, false);
let button = gpio2.input(iomuxc.gpio_sd.p05);

let lpuart1 = unsafe { ral::lpuart::LPUART1::instance() };
Expand All @@ -181,24 +185,24 @@ impl Specifics {
});

#[cfg(feature = "spi")]
let spi = {
let (spi, spi_cs) = {
let lpspi1 = unsafe { ral::lpspi::LPSPI1::instance() };
let pins = SpiPins {
sdo: iomuxc.gpio_ad.p04,
sdi: iomuxc.gpio_ad.p03,
sck: iomuxc.gpio_ad.p06,
pcs0: iomuxc.gpio_ad.p05,
};
let mut spi = Spi::new(lpspi1, pins);
spi.disabled(|spi| {
spi.set_clock_hz(super::LPSPI_CLK_FREQUENCY, super::SPI_BAUD_RATE_FREQUENCY);
});
spi
let spi_cs = gpio1.output(iomuxc.gpio_ad.p05, true);
(spi, spi_cs)
};

#[cfg(not(feature = "spi"))]
#[allow(clippy::let_unit_value)]
let spi = ();
let (spi, spi_cs) = ((), ());

let lpi2c1 = unsafe { ral::lpi2c::LPI2C1::instance() };
let i2c = I2c::new(
Expand Down Expand Up @@ -247,6 +251,7 @@ impl Specifics {
ports: GpioPorts { gpio2 },
console,
spi,
spi_cs,
i2c,
pwm,
tp34: iomuxc.gpio_sd.p02,
Expand Down
20 changes: 14 additions & 6 deletions board/src/imxrt1060evk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,16 +60,19 @@
iomuxc::gpio_sd_b0::GPIO_SD_B0_02, // SDO, J24_4
iomuxc::gpio_sd_b0::GPIO_SD_B0_03, // SDI, J24_5
iomuxc::gpio_sd_b0::GPIO_SD_B0_00, // SCK, J24_6
iomuxc::gpio_sd_b0::GPIO_SD_B0_01, // PCS0, J24_3
>;

#[cfg(not(feature = "spi"))]
/// Activate the `"spi"` feature to configure the SPI peripheral.
pub type Spi = ();
#[cfg(not(feature = "spi"))]
pub type SpiCsPin = ();

#[cfg(feature = "spi")]
/// SPI peripheral.
pub type Spi = hal::lpspi::Lpspi<SpiPins, 1>;
#[cfg(feature = "spi")]
pub type SpiCsPin = hal::gpio::Output<iomuxc::gpio_sd_b0::GPIO_SD_B0_01>; // PCS0, J24_3

type I2cScl = iomuxc::gpio_ad_b1::GPIO_AD_B1_00; // J24_10
type I2cSda = iomuxc::gpio_ad_b1::GPIO_AD_B1_01; // J24_9
Expand Down Expand Up @@ -130,6 +133,7 @@
pub ports: GpioPorts,
pub console: Console,
pub spi: Spi,
pub spi_cs: SpiCsPin,
pub i2c: I2c,
pub pwm: Pwm,
pub trng: hal::trng::Trng,
Expand All @@ -152,12 +156,15 @@

let gpio1 = unsafe { ral::gpio::GPIO1::instance() };
let mut gpio1 = hal::gpio::Port::new(gpio1);
let led = gpio1.output(iomuxc.gpio_ad_b0.p09);
let led = gpio1.output(iomuxc.gpio_ad_b0.p09, false);

let gpio5 = unsafe { ral::gpio::GPIO5::instance() };
let mut gpio5 = hal::gpio::Port::new(gpio5);
let button = hal::gpio::Input::without_pin(&mut gpio5, 0);

let gpio3 = unsafe { ral::gpio::GPIO3::instance() };
let mut gpio3 = hal::gpio::Port::new(gpio3);

Check warning on line 166 in board/src/imxrt1060evk.rs

View workflow job for this annotation

GitHub Actions / examples (--examples --features=board/imxrt1060evk,board/lcd1602)

unused variable: `gpio3`

Check warning on line 166 in board/src/imxrt1060evk.rs

View workflow job for this annotation

GitHub Actions / examples (--examples --features=board/imxrt1060evk,board/lcd1602)

variable does not need to be mutable

let lpuart1 = unsafe { ral::lpuart::LPUART1::instance() };
let mut console = hal::lpuart::Lpuart::new(
lpuart1,
Expand All @@ -172,23 +179,23 @@
});

#[cfg(feature = "spi")]
let spi = {
let (spi, spi_cs) = {
let lpspi1 = unsafe { ral::lpspi::LPSPI1::instance() };
let pins = SpiPins {
sdo: iomuxc.gpio_sd_b0.p02,
sdi: iomuxc.gpio_sd_b0.p03,
sck: iomuxc.gpio_sd_b0.p00,
pcs0: iomuxc.gpio_sd_b0.p01,
};
let mut spi = Spi::new(lpspi1, pins);
spi.disabled(|spi| {
spi.set_clock_hz(super::LPSPI_CLK_FREQUENCY, super::SPI_BAUD_RATE_FREQUENCY);
});
spi
let spi_cs = gpio3.output(iomuxc.gpio_sd_b0.p01, true);
(spi, spi_cs)
};
#[cfg(not(feature = "spi"))]
#[allow(clippy::let_unit_value)]
let spi = ();
let (spi, spi_cs) = ((), ());

let lpi2c1 = unsafe { ral::lpi2c::LPI2C1::instance() };
let i2c = I2c::new(
Expand Down Expand Up @@ -228,6 +235,7 @@
ports: GpioPorts { gpio5 },
console,
spi,
spi_cs,
i2c,
pwm,
trng,
Expand Down
18 changes: 12 additions & 6 deletions board/src/imxrt1170evk-cm7.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,14 +92,18 @@ pub type SpiPins = hal::lpspi::Pins<
iomuxc::gpio_ad::GPIO_AD_30, // SDO, J10_8
iomuxc::gpio_ad::GPIO_AD_31, // SDI, J10_10
iomuxc::gpio_ad::GPIO_AD_28, // SCK, J10_12
iomuxc::gpio_ad::GPIO_AD_29, // PCS0, J10_6
>;
const SPI_INSTANCE: u8 = 1;

#[cfg(feature = "spi")]
pub type Spi = hal::lpspi::Lpspi<SpiPins, { SPI_INSTANCE }>;
#[cfg(feature = "spi")]
pub type SpiCsPin = hal::gpio::Output<iomuxc::gpio_ad::GPIO_AD_29>; // PCS0, J10_6

#[cfg(not(feature = "spi"))]
pub type Spi = ();
#[cfg(not(feature = "spi"))]
pub type SpiCsPin = ();

pub type I2cPins = hal::lpi2c::Pins<
iomuxc::gpio_lpsr::GPIO_LPSR_05, // SCL, J10_20
Expand Down Expand Up @@ -160,6 +164,7 @@ pub struct Specifics {
pub tp1002: Tp1002,
pub tp1003: Tp1003,
pub spi: Spi,
pub spi_cs: SpiCsPin,
pub pwm: Pwm,
pub i2c: I2c,
}
Expand All @@ -184,7 +189,7 @@ impl Specifics {

let gpio9 = unsafe { ral::gpio::GPIO9::instance() };
let mut gpio9 = hal::gpio::Port::new(gpio9);
let led = gpio9.output(iomuxc.gpio_ad.p04);
let led = gpio9.output(iomuxc.gpio_ad.p04, false);

let console = unsafe { ral::lpuart::Instance::<{ CONSOLE_INSTANCE }>::instance() };
let mut console = hal::lpuart::Lpuart::new(
Expand All @@ -201,23 +206,23 @@ impl Specifics {
hal::usbphy::restart_pll(&mut common.usbphy1);

#[cfg(feature = "spi")]
let spi = {
let (spi, spi_cs) = {
let lpspi1 = unsafe { ral::lpspi::LPSPI1::instance() };
let pins = SpiPins {
sdo: iomuxc.gpio_ad.p30,
sdi: iomuxc.gpio_ad.p31,
sck: iomuxc.gpio_ad.p28,
pcs0: iomuxc.gpio_ad.p29,
};
let mut spi = Spi::new(lpspi1, pins);
spi.disabled(|spi| {
spi.set_clock_hz(LPSPI_CLK_FREQUENCY, super::SPI_BAUD_RATE_FREQUENCY);
});
spi
let spi_cs = gpio9.output(iomuxc.gpio_ad.p29, true);
(spi, spi_cs)
};
#[cfg(not(feature = "spi"))]
#[allow(clippy::let_unit_value)]
let spi = ();
let (spi, spi_cs) = ((), ());

#[cfg(not(feature = "spi"))]
let pwm = {
Expand Down Expand Up @@ -259,6 +264,7 @@ impl Specifics {
tp1002: iomuxc.gpio_emc_b1.p40,
tp1003: iomuxc.gpio_emc_b1.p41,
spi,
spi_cs,
pwm,
i2c,
}
Expand Down
17 changes: 11 additions & 6 deletions board/src/teensy4.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,16 +49,19 @@ pub type SpiPins = hal::lpspi::Pins<
iomuxc::gpio_b0::GPIO_B0_02, // SDO, P11
iomuxc::gpio_b0::GPIO_B0_01, // SDI, P12
iomuxc::gpio_b0::GPIO_B0_03, // SCK, P13
iomuxc::gpio_b0::GPIO_B0_00, // PCS0, P10
>;

#[cfg(not(feature = "spi"))]
/// Activate the `"spi"` feature to configure the SPI peripheral.
pub type Spi = ();
#[cfg(not(feature = "spi"))]
pub type SpiCsPin = ();

#[cfg(feature = "spi")]
/// SPI peripheral.
pub type Spi = hal::lpspi::Lpspi<SpiPins, 4>;
#[cfg(feature = "spi")]
pub type SpiCsPin = hal::gpio::Output<iomuxc::gpio_b0::GPIO_B0_00>; // PCS0, P10

pub type I2cPins = hal::lpi2c::Pins<
iomuxc::gpio_ad_b1::GPIO_AD_B1_07, // SCL, P16
Expand Down Expand Up @@ -111,6 +114,7 @@ pub struct Specifics {
pub ports: GpioPorts,
pub console: Console,
pub spi: Spi,
pub spi_cs: SpiCsPin,
pub i2c: I2c,
pub pwm: Pwm,
pub trng: hal::trng::Trng,
Expand All @@ -127,7 +131,7 @@ impl Specifics {
let mut gpio2 = hal::gpio::Port::new(gpio2);

#[cfg(not(feature = "spi"))]
let led = gpio2.output(iomuxc.gpio_b0.p03);
let led = gpio2.output(iomuxc.gpio_b0.p03, false);
#[cfg(feature = "spi")]
let led = ();

Expand All @@ -147,23 +151,23 @@ impl Specifics {
});

#[cfg(feature = "spi")]
let spi = {
let (spi, spi_cs) = {
let lpspi4 = unsafe { ral::lpspi::LPSPI4::instance() };
let pins = SpiPins {
sdo: iomuxc.gpio_b0.p02,
sdi: iomuxc.gpio_b0.p01,
sck: iomuxc.gpio_b0.p03,
pcs0: iomuxc.gpio_b0.p00,
};
let mut spi = Spi::new(lpspi4, pins);
spi.disabled(|spi| {
spi.set_clock_hz(super::LPSPI_CLK_FREQUENCY, super::SPI_BAUD_RATE_FREQUENCY);
});
spi
let spi_cs = gpio2.output(iomuxc.gpio_b0.p00, true);
(spi, spi_cs)
};
#[cfg(not(feature = "spi"))]
#[allow(clippy::let_unit_value)]
let spi = ();
let (spi, spi_cs) = ((), ());

let lpi2c3 = unsafe { ral::lpi2c::LPI2C3::instance() };
let i2c = I2c::new(
Expand Down Expand Up @@ -203,6 +207,7 @@ impl Specifics {
ports: GpioPorts { gpio2 },
console,
spi,
spi_cs,
i2c,
pwm,
trng,
Expand Down
12 changes: 6 additions & 6 deletions examples/rtic_spi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,12 @@ mod app {
#[init]
fn init(_: init::Context) -> (Shared, Local, init::Monotonics) {
let (_, board::Specifics { mut spi, .. }) = board::new();
spi.disabled(|spi| {
// Trigger when the TX FIFO is empty.
spi.set_watermark(Direction::Tx, 0);
// Wait to receive at least 2 u32s.
spi.set_watermark(Direction::Rx, 1);
});

// Wait to receive at least 2 u32s.
spi.set_watermark(Direction::Rx, 1);
// Trigger when the TX FIFO is empty.
spi.set_watermark(Direction::Tx, 0);

// Starts the I/O as soon as we're done initializing, since
// the TX FIFO is empty.
spi.set_interrupts(Interrupts::TRANSMIT_DATA);
Expand Down
23 changes: 16 additions & 7 deletions src/common/gpio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
//! let gpio_b0_04 = // Handle to GPIO_B0_04 IOMUXC pin, provided by BSP or higher-level HAL...
//! # unsafe { imxrt_iomuxc::imxrt1060::gpio_b0::GPIO_B0_04::new() };
//!
//! let output = gpio2.output(gpio_b0_04);
//! let output = gpio2.output(gpio_b0_04, false);
//! output.set();
//! output.clear();
//! output.toggle();
Expand Down Expand Up @@ -60,12 +60,14 @@ impl<const N: u8> Port<N> {
}

/// Allocate an output GPIO.
pub fn output<P>(&mut self, mut pin: P) -> Output<P>
///
/// `set` defines the initial state of the pin; `true` sets it high.
pub fn output<P>(&mut self, mut pin: P, set: bool) -> Output<P>
where
P: iomuxc::gpio::Pin<N>,
{
iomuxc::gpio::prepare(&mut pin);
Output::new(pin, self.register_block(), P::OFFSET)
Output::new(pin, self.register_block(), P::OFFSET, set)
}

/// Allocate an input GPIO.
Expand Down Expand Up @@ -134,8 +136,13 @@ pub struct Output<P> {
unsafe impl<P: Send> Send for Output<P> {}

impl<P> Output<P> {
fn new(pin: P, gpio: &'static ral::gpio::RegisterBlock, offset: u32) -> Self {
fn new(pin: P, gpio: &'static ral::gpio::RegisterBlock, offset: u32, set: bool) -> Self {
let output = Self { pin, gpio, offset };
if set {
output.set();
} else {
output.clear();
}
ral::modify_reg!(ral::gpio, gpio, GDIR, |gdir| gdir | output.mask());
output
}
Expand Down Expand Up @@ -189,7 +196,7 @@ impl<P> Output<P> {
impl Output<()> {
/// Allocate an output GPIO without a pin.
///
/// Prefer using [`Port::output`](Port::output) to create a GPIO ouptut with a
/// Prefer using [`Port::output`](Port::output) to create a GPIO output with a
/// pin resource. That method ensures that pin resources are managed throughout
/// your program, and that the pin is configured to operate as a GPIO output.
///
Expand All @@ -199,8 +206,10 @@ impl Output<()> {
///
/// If you use this constructor, you're responsible for configuring the IOMUX
/// multiplexer register.
pub fn without_pin<const N: u8>(port: &mut Port<N>, offset: u32) -> Self {
Self::new((), port.register_block(), offset)
///
/// `set` defines the initial state of the pin; `true` sets it high.
pub fn without_pin<const N: u8>(port: &mut Port<N>, offset: u32, set: bool) -> Self {
Self::new((), port.register_block(), offset, set)
}
}

Expand Down
Loading
Loading