imxrt-hal 0.5.14

Hardware abstraction layer for NXP i.MX RT microcontrollers.
Documentation
//! 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_peripheral.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) {
        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 },
        )
    }

    #[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)
        );
    }
}