-
Notifications
You must be signed in to change notification settings - Fork 33
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Demonstrate basic LPSPI device support
Use `set_device_enable` to transition the LPSPI peripheral from a controller into a device. You can then use the lower-level LPSPI interface to coordinate I/O. The commit includes two examples that you can run on physically-connected boards. See the example documentation for more info. I tested the LPSPI device behavior by running the `_device` example on a 1010EVK and the `_controller` example on a 1170EVK. I'm eagerly updating the pin configurations for other boards.
- Loading branch information
Showing
10 changed files
with
268 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
//! A SPI controller for testing SPI devices. | ||
//! | ||
//! Run this on one of your two development boards. Connect each board's | ||
//! SPI peripherals, and establish a common ground. Run rtic_spi_device.rs | ||
//! on the other development board. | ||
//! | ||
//! The controller sends two operands to the device. The device is expected | ||
//! to add those two operands (with wrapping). The controller expects this | ||
//! response from the device. The controllers transacts I/O as fast as | ||
//! possible. It periodically logs errors. | ||
//! | ||
//! You can monitor this device's defmt output to track the number of | ||
//! protocol errors. | ||
#![no_std] | ||
#![no_main] | ||
|
||
#[rtic::app(device = board, peripherals = false)] | ||
mod app { | ||
|
||
use core::sync::atomic::{AtomicU32, Ordering}; | ||
|
||
use hal::lpspi::BitOrder; | ||
use imxrt_hal as hal; | ||
|
||
const BIT_ORDER: BitOrder = BitOrder::Msb; | ||
|
||
#[local] | ||
struct Local { | ||
spi: board::Spi, | ||
pit: hal::pit::Pit<2>, | ||
} | ||
|
||
#[shared] | ||
struct Shared { | ||
errors: AtomicU32, | ||
} | ||
|
||
#[init] | ||
fn init(_: init::Context) -> (Shared, Local, init::Monotonics) { | ||
let ( | ||
board::Common { | ||
pit: (_, _, mut pit, _), | ||
.. | ||
}, | ||
board::Specifics { mut spi, .. }, | ||
) = board::new(); | ||
|
||
pit.set_interrupt_enable(true); | ||
pit.set_load_timer_value(board::PIT_FREQUENCY); | ||
pit.enable(); | ||
|
||
spi.set_bit_order(BIT_ORDER); | ||
|
||
( | ||
Shared { | ||
errors: AtomicU32::new(0), | ||
}, | ||
Local { spi, pit }, | ||
init::Monotonics(), | ||
) | ||
} | ||
|
||
#[idle(shared = [&errors], local = [spi])] | ||
fn idle(cx: idle::Context) -> ! { | ||
use eh02::blocking::spi::*; | ||
let idle::SharedResources { errors, .. } = cx.shared; | ||
let idle::LocalResources { spi, .. } = cx.local; | ||
|
||
for fst in (0u8..!0).cycle() { | ||
let snd = fst.wrapping_mul(7).wrapping_sub(13); | ||
spi.write(&[fst]).unwrap(); | ||
spi.write(&[snd]).unwrap(); | ||
|
||
let mut sum = [0xFFu8; 1]; | ||
spi.transfer(&mut sum).unwrap(); | ||
|
||
errors.fetch_add( | ||
u32::from(sum[0] != fst.wrapping_add(snd)), | ||
Ordering::Relaxed, | ||
); | ||
} | ||
|
||
unreachable!(); | ||
} | ||
|
||
#[task(binds = BOARD_PIT, shared = [&errors], local = [pit, count: usize = 0])] | ||
fn report_errors(cx: report_errors::Context) { | ||
let report_errors::LocalResources { pit, count, .. } = cx.local; | ||
|
||
while pit.is_elapsed() { | ||
pit.clear_elapsed(); | ||
} | ||
|
||
*count = count.wrapping_add(1); | ||
defmt::warn!( | ||
"({=usize}) Total errors: {=u32}", | ||
*count, | ||
cx.shared.errors.load(Ordering::Relaxed) | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
//! A SPI device demonstration. | ||
//! | ||
//! Run this on one of your two development boards. Connect each board's | ||
//! SPI peripherals, and establish a common ground. Run | ||
//! rtic_spi_controller.rs on the other development board. | ||
//! | ||
//! To understand the protocol, see the rtic_spi_controller.rs documentation. | ||
#![no_std] | ||
#![no_main] | ||
|
||
#[rtic::app(device = board, peripherals = false)] | ||
mod app { | ||
|
||
use hal::lpspi::{BitOrder, Direction, Interrupts, Transaction}; | ||
use imxrt_hal as hal; | ||
|
||
#[local] | ||
struct Local { | ||
spi: board::Spi, | ||
} | ||
|
||
#[shared] | ||
struct Shared {} | ||
|
||
type Elem = u8; | ||
const FRAME_SIZE: u16 = (core::mem::size_of::<Elem>() * 8) as u16; | ||
|
||
const BIT_ORDER: BitOrder = BitOrder::Msb; | ||
|
||
#[init] | ||
fn init(_: init::Context) -> (Shared, Local, init::Monotonics) { | ||
let (_, board::Specifics { mut spi, .. }) = board::new(); | ||
|
||
spi.disabled(|spi| spi.set_device_enable(true)); | ||
|
||
// Expect Elem bits per transaction. | ||
// | ||
// Don't transmit anything during this transaction! | ||
// Our protocol uses two separate transactions to | ||
// convey data. | ||
let mut transaction = Transaction::new(FRAME_SIZE).unwrap(); | ||
transaction.transmit_data_mask = true; | ||
transaction.bit_order = BIT_ORDER; | ||
spi.enqueue_transaction(&transaction); | ||
|
||
// React once we have both operands in the FIFO. | ||
spi.set_watermark(Direction::Rx, 1); | ||
spi.set_interrupts(Interrupts::RECEIVE_DATA); | ||
|
||
(Shared {}, Local { spi }, init::Monotonics()) | ||
} | ||
|
||
#[task(binds=BOARD_SPI, local = [spi])] | ||
fn spi_interrupt(cx: spi_interrupt::Context) { | ||
let spi_interrupt::LocalResources { spi, .. } = cx.local; | ||
|
||
let status = spi.status(); | ||
spi.clear_status(status); | ||
|
||
// There must be something, or we wouldn't have activated. | ||
let fst: Elem = spi.read_data().unwrap().try_into().unwrap(); | ||
let snd: Elem = spi.read_data().unwrap().try_into().unwrap(); | ||
|
||
// Prepare a new transaction that only sends data (ignores any received | ||
// data). | ||
let mut transaction = Transaction::new(FRAME_SIZE).unwrap(); | ||
transaction.receive_data_mask = true; | ||
transaction.bit_order = BIT_ORDER; | ||
spi.enqueue_transaction(&transaction); | ||
|
||
// Send the result. | ||
let sum: u8 = fst.wrapping_add(snd); | ||
spi.enqueue_data(sum.into()); | ||
|
||
// Prepare to receive the next elements from the controller. | ||
let mut transaction = Transaction::new(FRAME_SIZE).unwrap(); | ||
transaction.transmit_data_mask = true; | ||
transaction.bit_order = BIT_ORDER; | ||
spi.enqueue_transaction(&transaction); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters