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

Add SpiBus, SpiDevice implementations #181

Draft
wants to merge 9 commits into
base: lpspi-refactor
Choose a base branch
from
Draft
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
18 changes: 18 additions & 0 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,24 @@ jobs:
- name: Run unit, integration tests
run: cargo test --features=${{ matrix.chips }} --tests --package=imxrt-hal --package=imxrt-log

# Make sure our unit tests can pass (some recent version of) miri.
miri:
needs: tests
strategy:
matrix:
chips:
- imxrt-ral/imxrt1011,imxrt1010
- imxrt-ral/imxrt1021,imxrt1020
- imxrt-ral/imxrt1062,imxrt1060
- imxrt-ral/imxrt1176_cm7,imxrt1170
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install a nightly toolchain with miri
run: rustup toolchain install nightly --no-self-update --profile minimal --component miri
- name: Run unit, integration tests with miri
run: cargo +nightly miri test --features=${{ matrix.chips }} --tests --package=imxrt-hal --package=imxrt-log --config "profile.dev.opt-level = 0"

# Ensures that documentation builds, and that links are valid
docs:
needs: format
Expand Down
8 changes: 7 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,13 @@
- `timer::*PitChan`
- `lpspi::Disabled::{set_mode, set_watermark}`

**BREAKING** `LpspiError::{Busy, NoData}` are removed as possible LPSPI errors.
**BREAKING** Change the LPSPI driver:

- `LpspiError::{Busy, NoData}` are removed as possible LPSPI errors.
- There is no more `PCS0` type state associated with the LPSPI bus.

Introduce a hardware chip select and SPI mode into each LPSPI transaction.
Add an LPSPI configuration for hardware chip selects.

## [0.5.9] 2024-11-24

Expand Down
4 changes: 4 additions & 0 deletions board/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ publish = false
[dependencies.defmt]
version = "0.3"

[dependencies.eh1]
package = "embedded-hal"
version = "1.0"

[dependencies.imxrt-hal]
workspace = true

Expand Down
9 changes: 7 additions & 2 deletions board/src/imxrt1010evk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,11 @@ 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
>;

/// SPI PCS0 (J57_6).
pub type SpiPcs0 = iomuxc::gpio_ad::GPIO_AD_05;

#[cfg(feature = "spi")]
pub type Spi = hal::lpspi::Lpspi<SpiPins, 1>;

Expand Down Expand Up @@ -192,8 +194,11 @@ impl Specifics {
sdo: iomuxc.gpio_ad.p04,
sdi: iomuxc.gpio_ad.p03,
sck: iomuxc.gpio_ad.p06,
pcs0: iomuxc.gpio_ad.p05,
};
crate::iomuxc::lpspi::prepare({
let pcs0: &mut SpiPcs0 = &mut iomuxc.gpio_ad.p05;
pcs0
});
let mut spi = Spi::new(lpspi1, pins);
spi.disabled(|spi| {
spi.set_clock_hz(super::LPSPI_CLK_FREQUENCY, super::SPI_BAUD_RATE_FREQUENCY);
Expand Down
8 changes: 6 additions & 2 deletions board/src/imxrt1060evk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,9 @@ pub type SpiPins = hal::lpspi::Pins<
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
>;
/// SPI PCS0 (J24_3).
pub type SpiPcs0 = iomuxc::gpio_sd_b0::GPIO_SD_B0_01;

#[cfg(not(feature = "spi"))]
/// Activate the `"spi"` feature to configure the SPI peripheral.
Expand Down Expand Up @@ -180,8 +181,11 @@ impl Specifics {
sdo: iomuxc.gpio_sd_b0.p02,
sdi: iomuxc.gpio_sd_b0.p03,
sck: iomuxc.gpio_sd_b0.p00,
pcs0: iomuxc.gpio_sd_b0.p01,
};
crate::iomuxc::lpspi::prepare({
let pcs0: &mut SpiPcs0 = &mut iomuxc.gpio_sd_b0.p01;
pcs0
});
let mut spi = Spi::new(lpspi1, pins);
spi.disabled(|spi| {
spi.set_clock_hz(super::LPSPI_CLK_FREQUENCY, super::SPI_BAUD_RATE_FREQUENCY);
Expand Down
15 changes: 10 additions & 5 deletions board/src/imxrt1170evk-cm7.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,12 +92,14 @@ 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
>;
/// SPI PCS0 (J10_6).
pub type SpiPcs0 = iomuxc::gpio_ad::GPIO_AD_29;
const SPI_INSTANCE: u8 = 1;

#[cfg(feature = "spi")]
pub type Spi = hal::lpspi::Lpspi<SpiPins, { SPI_INSTANCE }>;
pub type Spi =
hal::lpspi::ExclusiveDevice<SpiPins, SpiPcs0, crate::PanickingDelay, { SPI_INSTANCE }>;
#[cfg(not(feature = "spi"))]
pub type Spi = ();

Expand Down Expand Up @@ -207,13 +209,16 @@ impl Specifics {
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);
let mut spi = hal::lpspi::Lpspi::new(lpspi1, pins);
spi.disabled(|spi| {
spi.set_clock_hz(LPSPI_CLK_FREQUENCY, super::SPI_BAUD_RATE_FREQUENCY);
});
spi
hal::lpspi::ExclusiveDevice::with_pcs0(
spi,
iomuxc.gpio_ad.p29,
crate::PanickingDelay::new(),
)
};
#[cfg(not(feature = "spi"))]
#[allow(clippy::let_unit_value)]
Expand Down
14 changes: 14 additions & 0 deletions board/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,20 @@ pub mod blocking {
}
}

pub struct PanickingDelay(());

impl PanickingDelay {
pub fn new() -> Self {
Self(())
}
}

impl eh1::delay::DelayNs for PanickingDelay {
fn delay_ns(&mut self, _: u32) {
unimplemented!()
}
}

/// Configurations for the logger.
///
/// If your board is ready to support the logging infrastructure,
Expand Down
9 changes: 7 additions & 2 deletions board/src/teensy4.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,11 @@ 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
>;

/// SPI PCS0 (P10).
pub type SpiPcs0 = iomuxc::gpio_b0::GPIO_B0_00;

#[cfg(not(feature = "spi"))]
/// Activate the `"spi"` feature to configure the SPI peripheral.
pub type Spi = ();
Expand Down Expand Up @@ -152,8 +154,11 @@ impl Specifics {
sdo: iomuxc.gpio_b0.p02,
sdi: iomuxc.gpio_b0.p01,
sck: iomuxc.gpio_b0.p03,
pcs0: iomuxc.gpio_b0.p00,
};
crate::iomuxc::lpspi::prepare({
let pcs0: &mut SpiPcs0 = &mut iomuxc.gpio_b0.p00;
pcs0
});
let mut spi = Spi::new(lpspi4, pins);
spi.disabled(|spi| {
spi.set_clock_hz(super::LPSPI_CLK_FREQUENCY, super::SPI_BAUD_RATE_FREQUENCY);
Expand Down
53 changes: 38 additions & 15 deletions examples/rtic_spi_blocking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,26 +60,26 @@ mod app {
// size and bit order, use this sequence to evaluate how
// the driver packs your transfer elements.
{
use eh02::blocking::spi::Write;
use eh1::spi::SpiDevice;
use hal::lpspi::BitOrder::{self, *};

const BIT_ORDERS: [BitOrder; 2] = [Msb, Lsb];

const U32_WORDS: [u32; 2] = [0xDEADBEEFu32, 0xAD1CAC1D];
for bit_order in BIT_ORDERS {
spi.set_bit_order(bit_order);
spi.bus_mut().set_bit_order(bit_order);
spi.write(&U32_WORDS).unwrap();
}

const U8_WORDS: [u8; 7] = [0xDEu8, 0xAD, 0xBE, 0xEF, 0x12, 0x34, 0x56];
for bit_order in BIT_ORDERS {
spi.set_bit_order(bit_order);
spi.bus_mut().set_bit_order(bit_order);
spi.write(&U8_WORDS).unwrap();
}

const U16_WORDS: [u16; 3] = [0xDEADu16, 0xBEEF, 0x1234];
for bit_order in BIT_ORDERS {
spi.set_bit_order(bit_order);
spi.bus_mut().set_bit_order(bit_order);
spi.write(&U16_WORDS).unwrap();
}

Expand All @@ -88,12 +88,12 @@ mod app {

// Change me to explore bit order behavors in the
// remaining write / loopback transfer tests.
spi.set_bit_order(hal::lpspi::BitOrder::Msb);
spi.bus_mut().set_bit_order(hal::lpspi::BitOrder::Msb);

// Make sure concatenated elements look correct on the wire.
// Make sure we can read those elements.
{
use eh02::blocking::spi::Transfer;
use eh1::spi::SpiDevice;
use hal::lpspi::BitOrder;

macro_rules! transfer_test {
Expand All @@ -103,9 +103,9 @@ mod app {
BitOrder::Lsb => "LSB",
};

spi.set_bit_order($bit_order);
spi.bus_mut().set_bit_order($bit_order);
let mut buffer = $arr;
spi.transfer(&mut buffer).unwrap();
spi.transfer_in_place(&mut buffer).unwrap();
defmt::assert_eq!(buffer, $arr, "Bit Order {}", bit_order_name);
};
}
Expand Down Expand Up @@ -137,12 +137,12 @@ mod app {
transfer_test!([0x01020304u32, 0x05060708, 0x090A0B0C], BitOrder::Msb);
transfer_test!([0x01020304u32, 0x05060708, 0x090A0B0C], BitOrder::Lsb);

spi.set_bit_order(BitOrder::Msb);
spi.bus_mut().set_bit_order(BitOrder::Msb);
delay();
}

{
use eh02::blocking::spi::{Transfer, Write};
use eh1::spi::SpiDevice;

// Change me to test different Elem sizes, buffer sizes,
// bit patterns.
Expand All @@ -153,10 +153,8 @@ mod app {
// Simple loopback transfer. Easy to find with your
// scope.
let mut buffer = BUFFER;
spi.transfer(&mut buffer).unwrap();
if buffer != BUFFER {
defmt::error!("Simple transfer buffer mismatch!");
}
spi.transfer_in_place(&mut buffer).unwrap();
defmt::assert_eq!(buffer, BUFFER);

delay();

Expand All @@ -167,7 +165,7 @@ mod app {
for idx in 0u32..16 {
buffer.fill(SENTINEL.rotate_right(idx));
let expected = buffer;
spi.transfer(&mut buffer).unwrap();
spi.transfer_in_place(&mut buffer).unwrap();
error |= buffer != expected;
}
if error {
Expand All @@ -194,6 +192,31 @@ mod app {

delay();
}

{
use eh1::spi::{
Operation::{Read, TransferInPlace, Write},
SpiDevice,
};

let mut read = [0u8; 7];
let mut xfer = [0u8; 10];
for idx in 0..xfer.len() {
xfer[idx] = idx as u8;
}

spi.transaction(&mut [
TransferInPlace(&mut xfer),
Read(&mut read),
Write(&[0xA5; 13][..]),
])
.unwrap();

assert_eq!(read, [0xff; 7]);
assert_eq!(xfer, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);

delay();
}
}
}
}
13 changes: 5 additions & 8 deletions src/chip/dma.rs
Original file line number Diff line number Diff line change
Expand Up @@ -196,10 +196,9 @@ impl<P, const N: u8> lpspi::Lpspi<P, N> {
channel: &'a mut Channel,
buffer: &'a [u32],
) -> Result<peripheral::Write<'a, Self, u32>, lpspi::LpspiError> {
let mut transaction = lpspi::Transaction::new_u32s(buffer)?;
transaction.bit_order = self.bit_order();

let mut transaction = self.bus_transaction(buffer)?;
transaction.receive_data_mask = true;

self.wait_for_transmit_fifo_space()?;
self.enqueue_transaction(&transaction);
Ok(peripheral::write(channel, buffer, self))
Expand All @@ -216,10 +215,9 @@ impl<P, const N: u8> lpspi::Lpspi<P, N> {
channel: &'a mut Channel,
buffer: &'a mut [u32],
) -> Result<peripheral::Read<'a, Self, u32>, lpspi::LpspiError> {
let mut transaction = lpspi::Transaction::new_u32s(buffer)?;
transaction.bit_order = self.bit_order();

let mut transaction = self.bus_transaction(buffer)?;
transaction.transmit_data_mask = true;

self.wait_for_transmit_fifo_space()?;
self.enqueue_transaction(&transaction);
Ok(peripheral::read(channel, self, buffer))
Expand All @@ -238,8 +236,7 @@ impl<P, const N: u8> lpspi::Lpspi<P, N> {
tx: &'a mut Channel,
buffer: &'a mut [u32],
) -> Result<peripheral::FullDuplex<'a, Self, u32>, lpspi::LpspiError> {
let mut transaction = lpspi::Transaction::new_u32s(buffer)?;
transaction.bit_order = self.bit_order();
let transaction = self.bus_transaction(buffer)?;

self.wait_for_transmit_fifo_space()?;
self.enqueue_transaction(&transaction);
Expand Down
Loading
Loading