Skip to content

Commit

Permalink
Make dma config a member again
Browse files Browse the repository at this point in the history
  • Loading branch information
Finomnis committed Nov 25, 2023
1 parent 5275bdc commit 6f54cc9
Show file tree
Hide file tree
Showing 6 changed files with 50 additions and 100 deletions.
6 changes: 4 additions & 2 deletions examples/rtic_spi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ mod app {
// Create SPI device
let spi_device = ExclusiveDevice::new(spi_bus, spi_cs_pin, Systick);

demo::spawn().unwrap();

(
Shared {},
Local {
Expand All @@ -78,8 +80,8 @@ mod app {
}

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

loop {
Systick::delay(1000.millis()).await;
Expand Down
23 changes: 17 additions & 6 deletions src/common/lpspi.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,30 @@
//! TODO
pub use eh1::spi::Mode;
use imxrt_dma::channel::Channel;

use crate::ral;

mod bus;
mod data_buffer;
mod disabled;
mod dma;
mod error;
mod status_watcher;

pub use dma::{FullDma, NoDma, PartialDma};
use status_watcher::StatusWatcher;

/// TODO
pub enum LpspiDma {
/// Everything is CPU driven
Disabled,
/// Read and Write are DMA based,
/// but Transfers are only partially
/// DMA based
Partial(Channel),
/// Everything is DMA based
Full(Channel, Channel),
}

/// Possible errors when interfacing the LPSPI.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum LpspiError {
Expand Down Expand Up @@ -45,16 +56,16 @@ pub struct LpspiData<const N: u8> {
}

/// TODO
pub struct Lpspi<'a, const N: u8, DMA> {
dma: DMA,
pub struct Lpspi<'a, const N: u8> {
dma: LpspiDma,
source_clock_hz: u32,
data: &'a LpspiData<N>,
tx_fifo_size: u32,
}

/// An LPSPI peripheral which is temporarily disabled.
pub struct Disabled<'a, 'b, const N: u8, DMA> {
bus: &'a mut Lpspi<'b, N, DMA>,
pub struct Disabled<'a, 'b, const N: u8> {
bus: &'a mut Lpspi<'b, N>,
men: bool,
}

Expand Down
50 changes: 14 additions & 36 deletions src/common/lpspi/bus.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,64 +2,33 @@ use eh1::spi::MODE_0;

use super::{
data_buffer::{LpspiDataBuffer, TransferBuffer},
dma::{FullDma, LpspiDma, NoDma},
Disabled, Lpspi, LpspiData, LpspiError, LpspiInterruptHandler, Pins, StatusWatcher,
};
use crate::{
iomuxc::{consts, lpspi},
lpspi::LpspiDma,
ral,
};

mod eh1_impl;

const MAX_FRAME_SIZE_BITS: u32 = 1 << 12;

impl<'a, const N: u8> Lpspi<'a, N, NoDma> {
/// Create a new LPSPI peripheral without DMA support.
///
/// `source_clock_hz` is the LPSPI peripheral clock speed. To specify the
/// peripheral clock, see the [`ccm::lpspi_clk`](crate::ccm::lpspi_clk) documentation.
pub fn new<SDO, SDI, SCK>(
lpspi: ral::lpspi::Instance<N>,
pins: Pins<SDO, SDI, SCK>,
data_storage: &'a mut Option<LpspiData<N>>,
source_clock_hz: u32,
) -> Self
where
SDO: lpspi::Pin<Module = consts::Const<N>, Signal = lpspi::Sdo>,
SDI: lpspi::Pin<Module = consts::Const<N>, Signal = lpspi::Sdi>,
SCK: lpspi::Pin<Module = consts::Const<N>, Signal = lpspi::Sck>,
{
Self::create(lpspi, pins, data_storage, source_clock_hz, NoDma)
}
}

impl<'a, const N: u8, DMA> Lpspi<'a, N, DMA> {
impl<'a, const N: u8> Lpspi<'a, N> {
/// The peripheral instance.
pub const N: u8 = N;

/// Attaches DMA channels to the device.
pub fn with_dma<D: LpspiDma>(self, dma: D) -> Lpspi<'a, N, D> {
Lpspi {
dma,
source_clock_hz: self.source_clock_hz,
data: self.data,
tx_fifo_size: self.tx_fifo_size,
}
}

/// Create a new LPSPI peripheral.
///
/// `source_clock_hz` is the LPSPI peripheral clock speed. To specify the
/// peripheral clock, see the [`ccm::lpspi_clk`](crate::ccm::lpspi_clk) documentation.
fn create<SDO, SDI, SCK>(
pub fn new<SDO, SDI, SCK>(
lpspi: ral::lpspi::Instance<N>,
// TODO: Open question: How to make those pins optional? (For example, WS2812 driver only uses SDO pin)
// Or should we simply do a `new_without_pins` again?
mut pins: Pins<SDO, SDI, SCK>,
data_storage: &'a mut Option<LpspiData<N>>,
source_clock_hz: u32,
dma: DMA,
) -> Self
where
SDO: lpspi::Pin<Module = consts::Const<N>, Signal = lpspi::Sdo>,
Expand All @@ -75,7 +44,7 @@ impl<'a, const N: u8, DMA> Lpspi<'a, N, DMA> {

let mut this = Self {
source_clock_hz,
dma,
dma: LpspiDma::Disabled,
data: data_storage.insert(data),
tx_fifo_size,
};
Expand Down Expand Up @@ -119,7 +88,7 @@ impl<'a, const N: u8, DMA> Lpspi<'a, N, DMA> {
///
/// The handle to a [`Disabled`](crate::lpspi::Disabled) driver lets you modify
/// LPSPI settings that require a fully disabled peripheral.
pub fn disabled<R>(&mut self, func: impl FnOnce(&mut Disabled<N, DMA>) -> R) -> R {
pub fn disabled<R>(&mut self, func: impl FnOnce(&mut Disabled<N>) -> R) -> R {
// Disable DMA and clear fifos
ral::modify_reg!(ral::lpspi, self.lpspi(), DER, RDDE: RDDE_0, TDDE: TDDE_0);
self.clear_fifos();
Expand All @@ -141,6 +110,15 @@ impl<'a, const N: u8, DMA> Lpspi<'a, N, DMA> {
}
}

/// Provides the SPI bus with one or two DMA channels.
///
/// This drastically increases the efficiency of reads/writes.
///
/// For simultaneous read/write, two DMA channels are required.
pub fn set_dma(&mut self, dma: LpspiDma) -> LpspiDma {
core::mem::replace(&mut self.dma, dma)
}

// ////////////////// PRIVATE DRIVER STUFF ///////////////////////

/// Get LPSPI Register Instance
Expand Down
20 changes: 12 additions & 8 deletions src/common/lpspi/bus/eh1_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@ use cassette::Cassette;

use crate::lpspi::data_buffer::{LpspiDataBuffer, TransferBuffer};

use super::{FullDma, Lpspi, LpspiError};
use super::{Lpspi, LpspiError};

impl<const N: u8, DMA> eh1::spi::ErrorType for Lpspi<'_, N, DMA> {
impl<const N: u8> eh1::spi::ErrorType for Lpspi<'_, N> {
type Error = LpspiError;
}

impl<const N: u8, DMA, T> eh1::spi::SpiBus<T> for Lpspi<'_, N, DMA>
impl<const N: u8, T> eh1::spi::SpiBus<T> for Lpspi<'_, N>
where
T: 'static + Copy,
[T]: LpspiDataBuffer,
Expand Down Expand Up @@ -46,20 +46,24 @@ where

// Async only makes sense for DMA; DMA only supports u32.
#[cfg(feature = "async")]
impl<const N: u8> eh1_async::spi::SpiBus<u32> for Lpspi<'_, N, FullDma> {
async fn read(&mut self, words: &mut [u32]) -> Result<(), Self::Error> {
impl<const N: u8, T> eh1_async::spi::SpiBus<T> for Lpspi<'_, N>
where
T: 'static + Copy,
[T]: LpspiDataBuffer,
{
async fn read(&mut self, words: &mut [T]) -> Result<(), Self::Error> {
self.transfer(TransferBuffer::Dual(words, &[])).await
}

async fn write(&mut self, words: &[u32]) -> Result<(), Self::Error> {
async fn write(&mut self, words: &[T]) -> Result<(), Self::Error> {
self.transfer(TransferBuffer::Dual(&mut [], words)).await
}

async fn transfer(&mut self, read: &mut [u32], write: &[u32]) -> Result<(), Self::Error> {
async fn transfer(&mut self, read: &mut [T], write: &[T]) -> Result<(), Self::Error> {
self.transfer(TransferBuffer::Dual(read, write)).await
}

async fn transfer_in_place(&mut self, words: &mut [u32]) -> Result<(), Self::Error> {
async fn transfer_in_place(&mut self, words: &mut [T]) -> Result<(), Self::Error> {
self.transfer(TransferBuffer::Single(words)).await
}

Expand Down
6 changes: 3 additions & 3 deletions src/common/lpspi/disabled.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ use eh1::spi::{Phase, Polarity};

use super::{ral, Disabled, Lpspi, Mode};

impl<'a, 'b, const N: u8, DMA> Disabled<'a, 'b, N, DMA> {
pub(crate) fn new(bus: &'a mut Lpspi<'b, N, DMA>) -> Self {
impl<'a, 'b, const N: u8> Disabled<'a, 'b, N> {
pub(crate) fn new(bus: &'a mut Lpspi<'b, N>) -> Self {
let men = ral::read_reg!(ral::lpspi, bus.data.lpspi.instance(), CR, MEN == MEN_1);
ral::modify_reg!(ral::lpspi, bus.data.lpspi.instance(), CR, MEN: MEN_0);
Self { bus, men }
Expand Down Expand Up @@ -48,7 +48,7 @@ impl<'a, 'b, const N: u8, DMA> Disabled<'a, 'b, N, DMA> {
}
}

impl<const N: u8, DMA> Drop for Disabled<'_, '_, N, DMA> {
impl<const N: u8> Drop for Disabled<'_, '_, N> {
fn drop(&mut self) {
ral::modify_reg!(ral::lpspi, self.bus.data.lpspi.instance(), CR, MEN: self.men as u32);
}
Expand Down
45 changes: 0 additions & 45 deletions src/common/lpspi/dma.rs

This file was deleted.

0 comments on commit 6f54cc9

Please sign in to comment.