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

LPSPI: embedded-hal 1.0 rework #145

Draft
wants to merge 74 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 31 commits
Commits
Show all changes
74 commits
Select commit Hold shift + click to select a range
7724d42
Initial ideas
Finomnis Nov 17, 2023
42422ef
More ideas
Finomnis Nov 18, 2023
854f727
More work
Finomnis Nov 18, 2023
9a65d36
Dummy implement SPI traits
Finomnis Nov 18, 2023
d7bc1b5
Minor comment
Finomnis Nov 18, 2023
47ff70a
More work; remove device, as it seems to be best practices to leave t…
Finomnis Nov 24, 2023
c4d938d
Add some comments
Finomnis Nov 24, 2023
07a8343
Bla
Finomnis Nov 24, 2023
b2619de
Make DMA compile time configurable
Finomnis Nov 24, 2023
bfc7619
Small fixes
Finomnis Nov 24, 2023
9fa738b
Refactor dma stuff int lpspi/dma.rs
Finomnis Nov 24, 2023
95109a9
More work
Finomnis Nov 24, 2023
a74fc69
Add word_types
Finomnis Nov 25, 2023
e6ae197
Bla.
Finomnis Nov 25, 2023
c91cfb3
Add error handling to SPI bus
Finomnis Nov 25, 2023
b27d56e
Add data buffer tests
Finomnis Nov 25, 2023
8711814
Implement blocking transfer
Finomnis Nov 25, 2023
ddef8d8
Refactoring to enable in-place transfer
Finomnis Nov 25, 2023
210e86f
Remove unused variable
Finomnis Nov 25, 2023
af51c0a
First time compiling! Not working yet, though.
Finomnis Nov 25, 2023
5275bdc
More rework; split data into dma and non-dma parts. To be determined …
Finomnis Nov 25, 2023
6f54cc9
Make dma config a member again
Finomnis Nov 25, 2023
26482d4
Fix example and board
Finomnis Nov 25, 2023
ae6ee7d
Remove rtic-sync dependency
Finomnis Nov 25, 2023
ef4d4bc
Fix lpspi clock config
Finomnis Dec 4, 2023
fd90b71
Add comment to set_clock_hz
Finomnis Dec 4, 2023
844d1c4
Partial rewrite
Finomnis Dec 7, 2023
c426668
Remove obsolete bat script
Finomnis Dec 7, 2023
e828ca2
Remove obsolete use statements
Finomnis Dec 7, 2023
5fdd6b2
Fix warning
Finomnis Dec 7, 2023
595b154
More work
Finomnis Dec 7, 2023
11bb131
Rework error handling
Finomnis Dec 8, 2023
4b3e391
Add start_frame, add write iter
Finomnis Dec 8, 2023
2aca984
Update cargo.toml
Finomnis Dec 8, 2023
6d5c823
Merge branch 'main' into embedded_hal_1
Finomnis Dec 8, 2023
be75933
Update cargo.toml
Finomnis Dec 8, 2023
857076a
Update cargo
Finomnis Dec 8, 2023
343d555
Attempt to fix CI
Finomnis Dec 8, 2023
5686f83
Another attempt to fix CI
Finomnis Dec 8, 2023
5b4ecc6
Another attempt to fix CI
Finomnis Dec 8, 2023
b068ef6
Add actions_write_test
Finomnis Dec 8, 2023
7fb65a5
More write impls
Finomnis Dec 9, 2023
a3c3838
Fix tests
Finomnis Dec 9, 2023
3eae4e9
Fix rust-toolchain.toml
Finomnis Dec 9, 2023
69fc170
First bus activity!
Finomnis Dec 9, 2023
fe98166
Fix order of single word transfer
Finomnis Dec 9, 2023
e2c357c
Prepare status_watcher for interrupt enable/disable
Finomnis Dec 10, 2023
9242413
Minor fix
Finomnis Dec 10, 2023
7f58e7e
Add wait-for-watermark
Finomnis Dec 10, 2023
2a32c57
First working larger transmission!
Finomnis Dec 13, 2023
43ddf45
Remove comment
Finomnis Dec 13, 2023
95ecfcf
Add TODO
Finomnis Dec 13, 2023
ea86c45
More optimization on write
Finomnis Dec 15, 2023
01995ff
Make ownership non-exclusive for most internal bus functions
Finomnis Dec 15, 2023
fea46a2
Split LPSPI into read and write part, for async ownership problems
Finomnis Dec 15, 2023
fd8a533
Add explanatory comment
Finomnis Dec 15, 2023
84a502b
Refactoring; add ReadActionIter
Finomnis Dec 15, 2023
7c40563
Update cargo.toml
Finomnis Dec 15, 2023
fe44f27
Fix tests
Finomnis Dec 15, 2023
88a5d60
Refactor transfer_actions
Finomnis Dec 15, 2023
64ff0c9
Attempt to add read_single_word
Finomnis Dec 15, 2023
3027e05
Fix read
Finomnis Dec 15, 2023
9e5a427
Add u32 stream; finish read part
Finomnis Dec 15, 2023
1a2caab
Redistribute unsafe tags
Finomnis Dec 15, 2023
2ffab65
Fix cleanup procedure
Finomnis Dec 15, 2023
86ef4ed
Remove finished TODO
Finomnis Dec 15, 2023
8bf18b3
Remove lpspi_old driver
Finomnis Dec 15, 2023
7492ba2
Remove unnecessary pubs
Finomnis Dec 15, 2023
b75ede3
Add TODO comments
Finomnis Dec 15, 2023
9cbd05e
Simplify read part
Finomnis Dec 17, 2023
c70ea1a
Prepare write DMA
Finomnis Dec 17, 2023
0c5dcae
Add TODO
Finomnis Dec 17, 2023
0cfe3a7
Adjust visibility of DMA mappings
Finomnis Dec 17, 2023
649748d
Check in latest example version, does not work yet.
Finomnis Dec 21, 2023
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
54 changes: 39 additions & 15 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
[package]
name = "imxrt-hal"
authors = ["Tom Burdick <[email protected]>", "Ian McIntyre <[email protected]>"]
authors = [
"Tom Burdick <[email protected]>",
"Ian McIntyre <[email protected]>",
]
description = """
Hardware abstraction layer for NXP i.MX RT microcontrollers.
"""
readme = "README.md"
repository = { workspace = true }
keywords = { workspace = true }
categories = { workspace = true }
license = { workspace = true }
repository = { workspace = true }
keywords = { workspace = true }
categories = { workspace = true }
license = { workspace = true }
edition = { workspace = true }
version = "0.5.3"

Expand All @@ -33,11 +36,26 @@ version = "1"
package = "embedded-hal"
version = "0.2"

[dependencies.eh1]
package = "embedded-hal"
version = "1.0.0-rc.1"

[dependencies.eh1-async]
package = "embedded-hal-async"
version = "1.0.0-rc.1"
optional = true

[dependencies.rand_core]
version = "0.5"
version = "0.6"
default-features = false
optional = true

[dependencies.cortex-m]
version = "0.7"

[dependencies.cassette]
version = "0.2.3"

#######################
# imxrt-rs dependencies
#######################
Expand Down Expand Up @@ -70,6 +88,7 @@ imxrt1020 = ["imxrt-iomuxc/imxrt1020"]
imxrt1060 = ["imxrt-iomuxc/imxrt1060"]
imxrt1064 = ["imxrt-iomuxc/imxrt1060"]
imxrt1170 = ["imxrt-iomuxc/imxrt1170"]
async = ["dep:eh1-async"]

################
# Extra features
Expand All @@ -80,16 +99,17 @@ imxrt1170 = ["imxrt-iomuxc/imxrt1170"]
eh02-unproven = []

[workspace]
members = [
"board",
"logging",
]
members = ["board", "logging"]

[workspace.dependencies]
imxrt-dma = "0.1"
imxrt-iomuxc = "0.2.1"
imxrt-hal = { version = "0.5", path = "." }
imxrt-log = { path = "logging", default-features = false, features = ["log", "lpuart", "usbd"] }
imxrt-log = { path = "logging", default-features = false, features = [
"log",
"lpuart",
"usbd",
] }
imxrt-ral = "0.5"
imxrt-rt = "0.1"
imxrt-usbd = "0.2"
Expand Down Expand Up @@ -124,16 +144,20 @@ codegen-units = 256
######################################

[dev-dependencies]
cortex-m = "0.7"
imxrt-rt = { workspace = true }
menu = "0.3.2"
cortex-m-rtic = "1.0"
menu = "0.4.0"
rtic = { version = "2.0.1", features = ["thumbv7-backend"] }
rtic-monotonics = { version = "1.2.0", features = [
"cortex-m-systick",
"embedded-hal-async",
] }
log = "0.4"
defmt = "0.3"
pin-utils = "0.1"
usb-device = { version = "0.2", features = ["test-class-high-speed"] }
usbd-serial = "0.1"
usbd-hid = "0.6"
embedded-hal-bus = { version = "0.1.0-rc.1", features = ["async"] }

[target.'cfg(all(target_arch = "arm", target_os = "none"))'.dev-dependencies]
board = { path = "board" }
Expand All @@ -148,7 +172,7 @@ required-features = ["board/spi"]

[[example]]
name = "rtic_spi"
required-features = ["board/spi"]
#required-features = ["board/spi"]

[[example]]
name = "hal_logging"
Expand Down
41 changes: 30 additions & 11 deletions board/src/teensy4.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,16 +49,27 @@ 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 = ();
mod lpspi_types {
pub type SpiBus = ();
pub type SpiCsPin = ();
pub type SpiInterruptHandler = ();
}

#[cfg(feature = "spi")]
/// SPI peripheral.
pub type Spi = hal::lpspi::Lpspi<SpiPins, 4>;
mod lpspi_types {

use super::*;
pub type SpiBus = hal::lpspi::Lpspi<'static, 4>;
pub type SpiCsPin = hal::gpio::Output<iomuxc::gpio_b0::GPIO_B0_00>;
pub type SpiInterruptHandler = hal::lpspi::LpspiInterruptHandler<'static, 4>;
}

pub use lpspi_types::*;

pub type I2cPins = hal::lpi2c::Pins<
iomuxc::gpio_ad_b1::GPIO_AD_B1_07, // SCL, P16
Expand Down Expand Up @@ -110,7 +121,7 @@ pub struct Specifics {
pub button: Button,
pub ports: GpioPorts,
pub console: Console,
pub spi: Spi,
pub spi: (SpiBus, SpiCsPin),
pub i2c: I2c,
pub pwm: Pwm,
pub trng: hal::trng::Trng,
Expand Down Expand Up @@ -153,17 +164,25 @@ impl Specifics {
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);
let cs_pin = gpio2.output(iomuxc.gpio_b0.p00);

static mut SPI_DATA: Option<super::hal::lpspi::LpspiData<4>> = None;
let mut spi = SpiBus::new(
lpspi4,
pins,
unsafe { &mut SPI_DATA },
super::LPSPI_CLK_FREQUENCY,
);
spi.disabled(|bus| {
bus.set_clock_hz(super::SPI_BAUD_RATE_FREQUENCY);
});
spi

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

let lpi2c3 = unsafe { ral::lpi2c::LPI2C3::instance() };
let i2c = I2c::new(
Expand Down Expand Up @@ -218,7 +237,7 @@ pub(crate) const CLOCK_GATES: &[clock_gate::Locator] = &[
clock_gate::gpio::<2>(),
clock_gate::lpuart::<{ Console::N }>(),
#[cfg(feature = "spi")]
clock_gate::lpspi::<{ Spi::N }>(),
clock_gate::lpspi::<{ SpiBus::N }>(),
clock_gate::lpi2c::<{ I2c::N }>(),
clock_gate::flexpwm::<{ pwm::Peripheral::N }>(),
];
Expand Down
116 changes: 80 additions & 36 deletions examples/rtic_spi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,64 +4,108 @@
//! schedule transfers, and to receive data. You can observe the
//! I/O with a scope / logic analyzer. The SPI CLK runs at 1MHz,
//! and the frame size is 64 bits.
//!
//! TODO: update description

#![no_std]
#![no_main]
// Required for RTIC 2 (for now)
#![feature(type_alias_impl_trait)]

#[rtic::app(device = board, peripherals = false)]
#[rtic::app(device = board, peripherals = false, dispatchers = [BOARD_SWTASK0])]
mod app {

use hal::lpspi::{Direction, Interrupts, Status, Transaction};
use embedded_hal_bus::spi::ExclusiveDevice;
use imxrt_hal as hal;

use eh1::spi::Operation;
use eh1::spi::SpiDevice;
use hal::lpspi::LpspiDma;
use rtic_monotonics::systick::*;

use board::{SpiBus, SpiCsPin, SpiInterruptHandler};

#[local]
struct Local {
spi: board::Spi,
spi_device: ExclusiveDevice<SpiBus, SpiCsPin, Systick>,
spi_interrupt_handler: SpiInterruptHandler,
}

#[shared]
struct Shared {}

#[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);
});
// Starts the I/O as soon as we're done initializing, since
// the TX FIFO is empty.
spi.set_interrupts(Interrupts::TRANSMIT_DATA);
(Shared {}, Local { spi }, init::Monotonics())
}
#[init(local = [
spi_systick: Option<Systick> = None,
])]
fn init(cx: init::Context) -> (Shared, Local) {
let (
board::Common { mut dma, .. },
board::Specifics {
spi: (mut spi_bus, spi_cs_pin),
..
},
) = board::new();

#[task(binds = BOARD_SPI, local = [spi])]
fn spi_interrupt(cx: spi_interrupt::Context) {
let spi_interrupt::LocalResources { spi } = cx.local;
// Init monotonic
let systick_token = rtic_monotonics::create_systick_token!();
Systick::start(
cx.core.SYST,
600_000_000, /* TODO: fix */
systick_token,
);

// Init DMA
let mut chan_a = dma[board::BOARD_DMA_A_INDEX].take().unwrap();
chan_a.set_disable_on_completion(true);

let status = spi.status();
spi.clear_status(Status::TRANSMIT_DATA | Status::RECEIVE_DATA);
let mut chan_b = dma[board::BOARD_DMA_B_INDEX].take().unwrap();
chan_b.set_disable_on_completion(true);

if status.intersects(Status::TRANSMIT_DATA) {
// This write clears TRANSMIT_DATA.
spi.set_interrupts(Interrupts::RECEIVE_DATA);
// Configure SPI
spi_bus.set_dma(LpspiDma::Full(chan_a, chan_b));
let spi_interrupt_handler = spi_bus.enable_interrupts();

// Sending two u32s. Frame size is represented by bits.
let transaction = Transaction::new(2 * 8 * core::mem::size_of::<u32>() as u16)
.expect("Transaction frame size is within bounds");
spi.enqueue_transaction(&transaction);
// Create SPI device
let spi_device = ExclusiveDevice::new(spi_bus, spi_cs_pin, Systick);

spi.enqueue_data(0xDEADBEEF);
spi.enqueue_data(!0xDEADBEEF);
} else if status.intersects(Status::RECEIVE_DATA) {
// This write clears RECEIVE_DATA.
spi.set_interrupts(Interrupts::TRANSMIT_DATA);
demo::spawn().unwrap();

assert!(spi.fifo_status().rxcount == 2);
(
Shared {},
Local {
spi_device,
spi_interrupt_handler,
},
)
}

while let Some(_) = spi.read_data() {}
#[task(priority = 1, local = [spi_device])]
async fn demo(cx: demo::Context) {
let demo::LocalResources { spi_device, .. } = cx.local;

loop {
Systick::delay(1000.millis()).await;

// To demonstrate normal operation
spi_device
.transaction(&mut [
Operation::DelayUs(100),
Operation::Write(&[12345u16]),
Operation::DelayUs(10),
Operation::Write(&[420, 69, 42]),
Operation::Write(&[0xFFFF]),
Operation::DelayUs(50),
])
.unwrap();

// To demonstrate larger, DMA based transfers
let mut buf = [0xf5u32; 512];
spi_device.transfer_in_place(&mut buf).unwrap();
mciantyre marked this conversation as resolved.
Show resolved Hide resolved
}
}

#[task(priority = 2, binds = BOARD_SPI, local = [spi_interrupt_handler])]
fn spi_interrupt(cx: spi_interrupt::Context) {
cx.local.spi_interrupt_handler.on_interrupt();
}
}
4 changes: 4 additions & 0 deletions rust-toolchain.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[toolchain]
channel = "nightly"
# components = ["rustfmt", "llvm-tools"]
targets = ["thumbv7em-none-eabihf"]
Loading
Loading