From 25df5e9f195a3ec423e34c1b81c483d7edc8e413 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ad=C3=A4?= Date: Thu, 12 Dec 2019 00:28:04 +0100 Subject: [PATCH 001/103] Started implementation of DMA stream --- .idea/.gitignore | 2 + .idea/misc.xml | 6 + .idea/modules.xml | 8 + .idea/stm32h7xx-hal.iml | 14 + .idea/vcs.xml | 6 + examples/adc.rs | 22 +- src/dma.rs | 674 ++++++++++++++++++++++++++++++++++++++++ src/dma/channel.rs | 36 +++ src/dma/macros.rs | 167 ++++++++++ src/dma/stream.rs | 171 ++++++++++ src/dma/utils.rs | 3 + src/lib.rs | 2 + 12 files changed, 1101 insertions(+), 10 deletions(-) create mode 100644 .idea/.gitignore create mode 100644 .idea/misc.xml create mode 100644 .idea/modules.xml create mode 100644 .idea/stm32h7xx-hal.iml create mode 100644 .idea/vcs.xml create mode 100644 src/dma.rs create mode 100644 src/dma/channel.rs create mode 100644 src/dma/macros.rs create mode 100644 src/dma/stream.rs create mode 100644 src/dma/utils.rs diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 00000000..5c98b428 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,2 @@ +# Default ignored files +/workspace.xml \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 00000000..28a804d8 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 00000000..2ea6aa53 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/stm32h7xx-hal.iml b/.idea/stm32h7xx-hal.iml new file mode 100644 index 00000000..b7b42421 --- /dev/null +++ b/.idea/stm32h7xx-hal.iml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 00000000..94a25f7f --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/examples/adc.rs b/examples/adc.rs index 82163bfe..09db3b36 100644 --- a/examples/adc.rs +++ b/examples/adc.rs @@ -7,19 +7,13 @@ extern crate panic_itm; use cortex_m; use cortex_m_rt::entry; -use stm32h7xx_hal::{ - adc, - pac, - delay::Delay, - prelude::*, -}; +use stm32h7xx_hal::{adc, delay::Delay, pac, prelude::*}; use cortex_m_log::println; use cortex_m_log::{ destination::Itm, printer::itm::InterruptSync as InterruptSyncItm, }; - #[entry] fn main() -> ! { let cp = cortex_m::Peripherals::take().unwrap(); @@ -36,9 +30,12 @@ fn main() -> ! { let rcc = dp.RCC.constrain(); // setting this per_ck to 4 Mhz here (which is gonna choose the CSI that runs at exactly 4 Mhz) as the adc requires per_ck as its - // own kernel clock and wouldn't work at all if per_ck wouldnt be enabled or loose a few bits if it was too fast + // own kernel clock and wouldn't work at all if per_ck wouldnt be enabled or loose a few bits if it was too fast // (the maximum for this is 36 Mhz) - let mut ccdr = rcc.sys_ck(100.mhz()).per_ck(4.mhz()).freeze(vos, &dp.SYSCFG); + let mut ccdr = rcc + .sys_ck(100.mhz()) + .per_ck(4.mhz()) + .freeze(vos, &dp.SYSCFG); println!(log, ""); println!(log, "stm32h7xx-hal example - ADC"); @@ -59,6 +56,11 @@ fn main() -> ! { loop { let data: u32 = adc3.read(&mut channel).unwrap(); // voltage = reading * (vref/resolution) - println!(log, "ADC reading: {}, voltage for nucleo: {}", data, data as f32 * (3.3/adc3.max_sample() as f32)); + println!( + log, + "ADC reading: {}, voltage for nucleo: {}", + data, + data as f32 * (3.3 / adc3.max_sample() as f32) + ); } } diff --git a/src/dma.rs b/src/dma.rs new file mode 100644 index 00000000..508f6735 --- /dev/null +++ b/src/dma.rs @@ -0,0 +1,674 @@ +#[macro_use] +mod macros; +pub mod channel; +pub mod stream; +mod utils; + +use self::channel::ChannelId; +use self::stm32::dma1::ST; +use self::stm32::{DMA1, DMA2}; +use self::stream::{ + BufferMode, CircularMode, CurrentTarget, DirectModeErrorInterrupt, + Disabled, Disabling, Enabled, Error, Event, FifoErrorInterrupt, + FifoThreshold, FlowController, HalfTransferInterrupt, IsrCleared, + IsrState as IsrStateTrait, IsrUncleared, M0a, M1a, MBurst, MSize, Minc, + Ndt, NotDisabled, PBurst, PSize, Pa, Pinc, Pincos, PriorityLevel, + StreamIsr, TransferCompleteInterrupt, TransferDirection, + TransferErrorInterrupt, TransferMode, ED as EDTrait, +}; +use crate::nb::{self, Error as NbError}; +use core::convert::TryInto; +use core::marker::PhantomData; +use stm32h7::stm32h743 as stm32; + +pub unsafe trait DMATrait {} +unsafe impl DMATrait for DMA1 {} +unsafe impl DMATrait for DMA2 {} + +pub struct Stream +where + CXX: ChannelId, + DMA: DMATrait, + ED: EDTrait, + IsrState: IsrStateTrait, +{ + rb: &'static ST, + _phantom_data: PhantomData<(CXX, DMA, ED, IsrState)>, +} + +impl Stream +where + CXX: ChannelId, + DMA: DMATrait, +{ + fn new(rb: &'static ST) -> Self { + Stream { + rb, + _phantom_data: PhantomData, + } + } +} + +impl Stream +where + CXX: ChannelId, + DMA: DMATrait, + ED: EDTrait, + IsrState: IsrStateTrait, +{ + pub fn id(&self) -> usize { + CXX::STREAM_ID + } + + pub fn is_enabled(&self) -> bool { + self.rb.cr.read().en().bit_is_set() + } + + pub fn transfer_complete_interrupt(&self) -> TransferCompleteInterrupt { + self.rb.cr.read().tcie().bit().into() + } + + pub fn half_transfer_interrupt(&self) -> HalfTransferInterrupt { + self.rb.cr.read().htie().bit().into() + } + + pub fn transfer_error_interrupt(&self) -> TransferErrorInterrupt { + self.rb.cr.read().teie().bit().into() + } + + pub fn direct_mode_error_interrupt(&self) -> DirectModeErrorInterrupt { + self.rb.cr.read().dmeie().bit().into() + } + + pub fn fifo_error_interrupt(&self) -> FifoErrorInterrupt { + self.rb.fcr.read().feie().bit().into() + } + + pub fn flow_controller(&self) -> FlowController { + self.rb.cr.read().pfctrl().bit().into() + } + + pub fn transfer_direction(&self) -> TransferDirection { + self.rb.cr.read().dir().bits().try_into().unwrap() + } + + pub fn circular_mode(&self) -> CircularMode { + self.rb.cr.read().circ().bit().into() + } + + pub fn pinc(&self) -> Pinc { + self.rb.cr.read().pinc().bit().into() + } + + pub fn minc(&self) -> Minc { + self.rb.cr.read().minc().bit().into() + } + + pub fn p_size(&self) -> PSize { + self.rb.cr.read().psize().bits().try_into().unwrap() + } + + pub fn m_size(&self) -> MSize { + self.rb.cr.read().msize().bits().try_into().unwrap() + } + + pub fn pincos(&self) -> Pincos { + self.rb.cr.read().pincos().bit().into() + } + + pub fn priority_level(&self) -> PriorityLevel { + self.rb.cr.read().pl().bits().try_into().unwrap() + } + + pub fn buffer_mode(&self) -> BufferMode { + self.rb.cr.read().dbm().bit().into() + } + + pub fn current_target(&self) -> CurrentTarget { + self.rb.cr.read().ct().bit().into() + } + + pub fn p_burst(&self) -> PBurst { + self.rb.cr.read().pburst().bits().try_into().unwrap() + } + + pub fn m_burst(&self) -> MBurst { + self.rb.cr.read().mburst().bits().try_into().unwrap() + } + + pub fn ndt(&self) -> Ndt { + self.rb.ndtr.read().ndt().bits().into() + } + + pub fn pa(&self) -> Pa { + self.rb.par.read().pa().bits().into() + } + + pub fn m0a(&self) -> M0a { + self.rb.m0ar.read().m0a().bits().into() + } + + pub fn m1a(&self) -> M1a { + self.rb.m1ar.read().m1a().bits().into() + } + + pub fn fifo_threshold(&self) -> FifoThreshold { + self.rb.fcr.read().fth().bits().try_into().unwrap() + } + + pub fn transfer_mode(&self) -> TransferMode { + self.rb.fcr.read().dmdis().bit().into() + } + + fn impl_set_m0a(&mut self, m0a: M0a) { + unsafe { + self.rb.m0ar.modify(|_, w| w.m0a().bits(m0a.into())); + } + } + + fn impl_set_m1a(&mut self, m1a: M1a) { + unsafe { + self.rb.m0ar.modify(|_, w| w.m0a().bits(m1a.into())); + } + } + + fn transmute( + self, + ) -> Stream + where + NewED: EDTrait, + NewIsrState: IsrStateTrait, + { + Stream { + rb: self.rb, + _phantom_data: PhantomData, + } + } +} + +impl Stream +where + CXX: ChannelId, + DMA: DMATrait, + IsrState: IsrStateTrait, +{ + pub fn set_flow_controller(&mut self, flow_controller: FlowController) { + self.rb + .cr + .modify(|_, w| w.pfctrl().bit(flow_controller.into())); + } + + pub fn set_transfer_direction(&mut self, transfer_dir: TransferDirection) { + unsafe { + self.rb.cr.modify(|_, w| w.dir().bits(transfer_dir.into())); + } + } + + pub fn set_circular_mode(&mut self, circ_mode: CircularMode) { + self.rb.cr.modify(|_, w| w.circ().bit(circ_mode.into())); + } + + pub fn set_pinc(&mut self, pinc: Pinc) { + self.rb.cr.modify(|_, w| w.pinc().bit(pinc.into())); + } + + pub fn set_minc(&mut self, minc: Minc) { + self.rb.cr.modify(|_, w| w.minc().bit(minc.into())); + } + + pub fn set_p_size(&mut self, p_size: PSize) { + unsafe { + self.rb.cr.modify(|_, w| w.psize().bits(p_size.into())); + } + } + + pub fn set_m_size(&mut self, m_size: MSize) { + unsafe { + self.rb.cr.modify(|_, w| w.msize().bits(m_size.into())); + } + } + + pub fn set_pincos(&mut self, pincos: Pincos) { + self.rb.cr.modify(|_, w| w.pincos().bit(pincos.into())); + } + + pub fn set_priority_level(&mut self, priority_level: PriorityLevel) { + unsafe { + self.rb.cr.modify(|_, w| w.pl().bits(priority_level.into())); + } + } + + pub fn set_buffer_mode(&mut self, buffer_mode: BufferMode) { + self.rb.cr.modify(|_, w| w.dbm().bit(buffer_mode.into())); + } + + pub fn set_current_target(&mut self, current_target: CurrentTarget) { + self.rb.cr.modify(|_, w| w.ct().bit(current_target.into())); + } + + pub fn set_p_burst(&mut self, p_burst: PBurst) { + unsafe { + self.rb.cr.modify(|_, w| w.pburst().bits(p_burst.into())); + } + } + + pub fn set_m_burst(&mut self, m_burst: MBurst) { + unsafe { + self.rb.cr.modify(|_, w| w.mburst().bits(m_burst.into())); + } + } + + pub fn set_ndt(&mut self, ndt: Ndt) { + unsafe { + self.rb.ndtr.modify(|_, w| w.ndt().bits(ndt.into())); + } + } + + pub fn set_pa(&mut self, pa: Pa) { + unsafe { + self.rb.par.modify(|_, w| w.pa().bits(pa.into())); + } + } + + pub fn set_m0a(&mut self, m0a: M0a) { + self.impl_set_m0a(m0a); + } + + pub fn set_m1a(&mut self, m1a: M1a) { + self.impl_set_m1a(m1a); + } + + pub fn set_fifo_threshold(&mut self, fifo_threshold: FifoThreshold) { + unsafe { + self.rb + .fcr + .modify(|_, w| w.fth().bits(fifo_threshold.into())); + } + } + + pub fn set_transfer_mode(&mut self, transfer_mode: TransferMode) { + self.rb + .fcr + .modify(|_, w| w.dmdis().bit(transfer_mode.into())); + } +} + +impl Stream +where + CXX: ChannelId, + DMA: DMATrait, + ED: NotDisabled, + IsrState: IsrStateTrait, +{ + pub fn set_m0a(&mut self, m0a: M0a) -> nb::Result<(), ()> { + self.check_buffer_mode_addr_change(); + + if self.current_target() == CurrentTarget::M0a && self.is_enabled() { + return Err(NbError::WouldBlock); + } + + self.impl_set_m0a(m0a); + + Ok(()) + } + + pub fn set_m1a(&mut self, m1a: M1a) -> nb::Result<(), ()> { + self.check_buffer_mode_addr_change(); + + if self.current_target() == CurrentTarget::M1a && self.is_enabled() { + return Err(NbError::WouldBlock); + } + + self.impl_set_m1a(m1a); + + Ok(()) + } + + fn check_buffer_mode_addr_change(&self) { + if self.buffer_mode() == BufferMode::Regular { + panic!("The buffer must be in double buffer mode to be changed on the fly."); + } + } +} + +impl Stream +where + CXX: ChannelId, + DMA: DMATrait, +{ + /// # Safety + /// + /// Aliasing rules aren't enforced + pub unsafe fn enable(self) -> Stream { + self.rb.cr.modify(|_, w| w.en().set_bit()); + + self.transmute() + } +} + +impl Stream +where + CXX: ChannelId, + DMA: DMATrait, + IsrState: IsrStateTrait, +{ + pub fn disable(self) -> Stream { + self.rb.cr.modify(|_, w| w.en().clear_bit()); + + self.transmute() + } +} + +impl Stream +where + CXX: ChannelId, + DMA: DMATrait, + IsrState: IsrStateTrait, +{ + pub fn await_disabled(self) -> Stream { + while self.rb.cr.read().en().bit_is_set() {} + + self.transmute() + } +} + +impl Stream +where + CXX: ChannelId, + DMA: DMATrait, + ED: EDTrait, +{ + pub fn check_isr( + &self, + isr: &StreamIsr, + ) -> Result, Error> { + let transfer_error = self.is_transfer_error(isr); + let direct_mode_error = self.is_direct_mode_error(isr); + let fifo_error = self.is_fifo_error(isr); + + let event = if self.is_transfer_completed(isr) { + Some(Event::TransferComplete) + } else if self.is_half_transfer(isr) { + Some(Event::HalfTransfer) + } else { + None + }; + + let crashed = !self.is_enabled() && self.ndt().value() != 0; + + if transfer_error || direct_mode_error || fifo_error { + Err(Error { + transfer_error, + direct_mode_error, + fifo_error, + event, + crashed, + }) + } else { + Ok(event) + } + } + + pub fn is_transfer_completed(&self, isr: &StreamIsr) -> bool { + match self.id() { + 0 => isr.lisr.read().tcif0().bit_is_set(), + 1 => isr.lisr.read().tcif1().bit_is_set(), + 2 => isr.lisr.read().tcif2().bit_is_set(), + 3 => isr.lisr.read().tcif3().bit_is_set(), + 4 => isr.hisr.read().tcif4().bit_is_set(), + 5 => isr.hisr.read().tcif5().bit_is_set(), + 6 => isr.hisr.read().tcif6().bit_is_set(), + 7 => isr.hisr.read().tcif7().bit_is_set(), + _ => unreachable!(), + } + } + + pub fn is_half_transfer(&self, isr: &StreamIsr) -> bool { + match self.id() { + 0 => isr.lisr.read().htif0().bit_is_set(), + 1 => isr.lisr.read().htif1().bit_is_set(), + 2 => isr.lisr.read().htif2().bit_is_set(), + 3 => isr.lisr.read().htif3().bit_is_set(), + 4 => isr.hisr.read().htif4().bit_is_set(), + 5 => isr.hisr.read().htif5().bit_is_set(), + 6 => isr.hisr.read().htif6().bit_is_set(), + 7 => isr.hisr.read().htif7().bit_is_set(), + _ => unreachable!(), + } + } + + pub fn is_transfer_error(&self, isr: &StreamIsr) -> bool { + match self.id() { + 0 => isr.lisr.read().teif0().bit_is_set(), + 1 => isr.lisr.read().teif1().bit_is_set(), + 2 => isr.lisr.read().teif2().bit_is_set(), + 3 => isr.lisr.read().teif3().bit_is_set(), + 4 => isr.hisr.read().teif4().bit_is_set(), + 5 => isr.hisr.read().teif5().bit_is_set(), + 6 => isr.hisr.read().teif6().bit_is_set(), + 7 => isr.hisr.read().teif7().bit_is_set(), + _ => unreachable!(), + } + } + + pub fn is_direct_mode_error(&self, isr: &StreamIsr) -> bool { + match self.id() { + 0 => isr.lisr.read().dmeif0().bit_is_set(), + 1 => isr.lisr.read().dmeif1().bit_is_set(), + 2 => isr.lisr.read().dmeif2().bit_is_set(), + 3 => isr.lisr.read().dmeif3().bit_is_set(), + 4 => isr.hisr.read().dmeif4().bit_is_set(), + 5 => isr.hisr.read().dmeif5().bit_is_set(), + 6 => isr.hisr.read().dmeif6().bit_is_set(), + 7 => isr.hisr.read().dmeif7().bit_is_set(), + _ => unreachable!(), + } + } + + pub fn is_fifo_error(&self, isr: &StreamIsr) -> bool { + match self.id() { + 0 => isr.lisr.read().feif0().bit_is_set(), + 1 => isr.lisr.read().feif1().bit_is_set(), + 2 => isr.lisr.read().feif2().bit_is_set(), + 3 => isr.lisr.read().feif3().bit_is_set(), + 4 => isr.hisr.read().feif4().bit_is_set(), + 5 => isr.hisr.read().feif5().bit_is_set(), + 6 => isr.hisr.read().feif6().bit_is_set(), + 7 => isr.hisr.read().feif7().bit_is_set(), + _ => unreachable!(), + } + } + + fn clear_isr_impl(&self, isr: &mut StreamIsr) { + self.clear_transfer_complete(isr); + self.clear_half_transfer(isr); + self.clear_transfer_error(isr); + self.clear_direct_mode_error(isr); + self.clear_fifo_error(isr); + } + + pub fn clear_transfer_complete(&self, isr: &mut StreamIsr) { + match self.id() { + 0 => { + isr.lifcr.write(|w| w.ctcif0().set_bit()); + } + 1 => { + isr.lifcr.write(|w| w.ctcif1().set_bit()); + } + 2 => { + isr.lifcr.write(|w| w.ctcif2().set_bit()); + } + 3 => { + isr.lifcr.write(|w| w.ctcif3().set_bit()); + } + 4 => { + isr.hifcr.write(|w| w.ctcif4().set_bit()); + } + 5 => { + isr.hifcr.write(|w| w.ctcif5().set_bit()); + } + 6 => { + isr.hifcr.write(|w| w.ctcif6().set_bit()); + } + 7 => { + isr.hifcr.write(|w| w.ctcif7().set_bit()); + } + _ => unreachable!(), + } + } + + pub fn clear_half_transfer(&self, isr: &mut StreamIsr) { + match self.id() { + 0 => { + isr.lifcr.write(|w| w.chtif0().set_bit()); + } + 1 => { + isr.lifcr.write(|w| w.chtif1().set_bit()); + } + 2 => { + isr.lifcr.write(|w| w.chtif2().set_bit()); + } + 3 => { + isr.lifcr.write(|w| w.chtif3().set_bit()); + } + 4 => { + isr.hifcr.write(|w| w.chtif4().set_bit()); + } + 5 => { + isr.hifcr.write(|w| w.chtif5().set_bit()); + } + 6 => { + isr.hifcr.write(|w| w.chtif6().set_bit()); + } + 7 => { + isr.hifcr.write(|w| w.chtif7().set_bit()); + } + _ => unreachable!(), + } + } + + pub fn clear_transfer_error(&self, isr: &mut StreamIsr) { + match self.id() { + 0 => { + isr.lifcr.write(|w| w.cteif0().set_bit()); + } + 1 => { + isr.lifcr.write(|w| w.cteif1().set_bit()); + } + 2 => { + isr.lifcr.write(|w| w.cteif2().set_bit()); + } + 3 => { + isr.lifcr.write(|w| w.cteif3().set_bit()); + } + 4 => { + isr.hifcr.write(|w| w.cteif4().set_bit()); + } + 5 => { + isr.hifcr.write(|w| w.cteif5().set_bit()); + } + 6 => { + isr.hifcr.write(|w| w.cteif6().set_bit()); + } + 7 => { + isr.hifcr.write(|w| w.cteif7().set_bit()); + } + _ => unreachable!(), + } + } + + pub fn clear_direct_mode_error(&self, isr: &mut StreamIsr) { + match self.id() { + 0 => { + isr.lifcr.write(|w| w.cdmeif0().set_bit()); + } + 1 => { + isr.lifcr.write(|w| w.cdmeif1().set_bit()); + } + 2 => { + isr.lifcr.write(|w| w.cdmeif2().set_bit()); + } + 3 => { + isr.lifcr.write(|w| w.cdmeif3().set_bit()); + } + 4 => { + isr.hifcr.write(|w| w.cdmeif4().set_bit()); + } + 5 => { + isr.hifcr.write(|w| w.cdmeif5().set_bit()); + } + 6 => { + isr.hifcr.write(|w| w.cdmeif6().set_bit()); + } + 7 => { + isr.hifcr.write(|w| w.cdmeif7().set_bit()); + } + _ => unreachable!(), + } + } + + pub fn clear_fifo_error(&self, isr: &mut StreamIsr) { + match self.id() { + 0 => { + isr.lifcr.write(|w| w.cfeif0().set_bit()); + } + 1 => { + isr.lifcr.write(|w| w.cfeif1().set_bit()); + } + 2 => { + isr.lifcr.write(|w| w.cfeif2().set_bit()); + } + 3 => { + isr.lifcr.write(|w| w.cfeif3().set_bit()); + } + 4 => { + isr.hifcr.write(|w| w.cfeif4().set_bit()); + } + 5 => { + isr.hifcr.write(|w| w.cfeif5().set_bit()); + } + 6 => { + isr.hifcr.write(|w| w.cfeif6().set_bit()); + } + 7 => { + isr.hifcr.write(|w| w.cfeif7().set_bit()); + } + _ => unreachable!(), + } + } +} + +impl Stream +where + CXX: ChannelId, + DMA: DMATrait, +{ + pub fn clear_isr( + self, + isr: &mut StreamIsr, + ) -> Stream { + self.clear_isr_impl(isr); + + self.transmute() + } +} + +impl Stream +where + CXX: ChannelId, + DMA: DMATrait, + ED: NotDisabled, +{ + pub fn clear_isr(&self, isr: &mut StreamIsr) { + self.clear_isr_impl(isr); + } +} + +unsafe impl Sync for Stream +where + CXX: ChannelId, + DMA: DMATrait, + ED: EDTrait, + IsrState: IsrStateTrait, +{ +} diff --git a/src/dma/channel.rs b/src/dma/channel.rs new file mode 100644 index 00000000..6831ec3e --- /dev/null +++ b/src/dma/channel.rs @@ -0,0 +1,36 @@ +pub trait ChannelId { + const STREAM_ID: usize; + const MUX_ID: usize; +} + +macro_rules! channels { + ($($channel:ident => [$stream:tt, $mux:tt]),*) => { + $( + pub struct $channel; + + impl ChannelId for $channel { + const STREAM_ID: usize = $stream; + const MUX_ID: usize = $mux; + } + )* + }; +} + +channels! { + C0 => [0, 0], + C1 => [1, 1], + C2 => [2, 2], + C3 => [3, 3], + C4 => [4, 4], + C5 => [5, 5], + C6 => [6, 6], + C7 => [7, 7], + C8 => [0, 8], + C9 => [1, 9], + C10 => [2, 10], + C11 => [3, 11], + C12 => [4, 12], + C13 => [5, 13], + C14 => [6, 14], + C15 => [7, 15] +} diff --git a/src/dma/macros.rs b/src/dma/macros.rs new file mode 100644 index 00000000..1bcecfd7 --- /dev/null +++ b/src/dma/macros.rs @@ -0,0 +1,167 @@ +macro_rules! type_state { + ($trait:ident, $($type_state:ident),*) => { + pub unsafe trait $trait: crate::dma::utils::TypeState {} + + $( + #[derive(Debug, PartialEq, Eq, Clone, Copy)] + pub struct $type_state; + + impl crate::dma::utils::TypeState for $type_state {} + unsafe impl $trait for $type_state {} + )* + }; +} + +macro_rules! bool_enum { + ($name:ident, $doc:tt, $v_false:ident, $v_true:ident) => { + #[doc=$doc] + #[derive(Debug, PartialEq, Eq, Clone, Copy)] + pub enum $name { + $v_false, + $v_true, + } + + impl From<$name> for bool { + fn from(val: $name) -> bool { + val == $name::$v_true + } + } + + impl From for $name { + fn from(val: bool) -> Self { + if val { + $name::$v_true + } else { + $name::$v_false + } + } + } + }; +} + +macro_rules! int_enum { + ($name:ident <=> $ty:ty, $doc:tt, $($variant:ident <=> $num:tt),*) => { + #[doc=$doc] + #[derive(Debug, PartialEq, Eq, Clone, Copy)] + pub enum $name { + $( + $variant, + )* + } + + impl From<$name> for $ty { + fn from(val: $name) -> $ty { + match val { + $( + $name::$variant => $num, + )* + } + } + } + + impl core::convert::TryFrom<$ty> for $name { + type Error = &'static str; + + fn try_from(val: $ty) -> Result { + match val { + $( + $num => Ok($name::$variant), + )* + _ => Err("Conversion failed"), + } + } + } + }; +} + +/// Macro for generating structs closely related to integers. +/// +/// Attention: If you don't want to limit the length of the stored value, +/// set `$len = 0`. +macro_rules! int_struct { + ($name:ident, $int_type:ident, $len:tt, $doc:tt) => { + int_struct! { @INNER $name, $doc, $int_type, $len } + }; + (@INNER $name:ident, $doc:tt, $int_type:ident, 0) => { + #[doc=$doc] + #[derive(Debug, Clone, Copy, PartialEq, Eq)] + pub struct $name(pub $int_type); + + impl $name { + pub fn new(val: $int_type) -> Self { + $name(val) + } + + pub fn set_value(&mut self, val: $int_type) { + self.0 = val; + } + + pub fn value(self) -> $int_type { + self.0 + } + } + + impl From<$int_type> for $name { + fn from(val: $int_type) -> Self { + $name::new(val) + } + } + + impl From<$name> for $int_type { + fn from(val: $name) -> $int_type { + val.value() + } + } + }; + (@INNER $name:ident, $doc:tt, $int_type:ident, $len:tt) => { + #[doc=$doc] + #[derive(Debug, Clone, Copy, PartialEq, Eq)] + pub struct $name($int_type); + + impl $name { + pub fn new(val: $int_type) -> Self { + if !$name::is_val_valid(val) { + // Expression `(1 << $len) - 1` overflows if $len = len of $int_type + panic!("The given value is incompatible with this type (max_value={}, got={})", (1 << $len) - 1, val); + } + + $name(val) + } + + pub fn value(self) -> $int_type { + self.0 + } + + pub fn set_value(&mut self, val: $int_type) { + if !$name::is_val_valid(val) { + panic!("The given value is incompatible with this type (max_value={}, got={})", (1 << $len) - 1, val); + } + + self.0 = val; + } + + fn is_val_valid(val: $int_type) -> bool { + val >> ($len - 1) <= 0b1 + } + } + + impl From<$name> for $int_type { + fn from(val: $name) -> $int_type { + val.value() + } + } + + impl core::convert::TryFrom<$int_type> for $name { + // FIXME + type Error = &'static str; + + fn try_from(val: $int_type) -> Result { + if $name::is_val_valid(val) { + Ok($name::new(val)) + } else { + Err("Conversion failed.") + } + } + } + }; +} diff --git a/src/dma/stream.rs b/src/dma/stream.rs new file mode 100644 index 00000000..52c4340e --- /dev/null +++ b/src/dma/stream.rs @@ -0,0 +1,171 @@ +use super::stm32::dma1::{HIFCR, HISR, LIFCR, LISR}; +use super::DMATrait; +use core::marker::PhantomData; + +type_state! { + ED, Disabled, Disabling, Enabled +} + +pub unsafe trait NotDisabled: ED {} +unsafe impl NotDisabled for Disabling {} +unsafe impl NotDisabled for Enabled {} + +type_state! { + IsrState, IsrCleared, IsrUncleared +} + +bool_enum! { + TransferCompleteInterrupt, "Transfer Complete Interrupt", Disabled, Enabled +} + +bool_enum! { + HalfTransferInterrupt, "Half Transfer Interrupt", Disabled, Enabled +} + +bool_enum! { + TransferErrorInterrupt, "Transfer Error Interrupt", Disabled, Enabled +} + +bool_enum! { + DirectModeErrorInterrupt, "Direct Mode Error Interrupt", Disabled, Enabled +} + +bool_enum! { + FifoErrorInterrupt, "Fifo Error Interrupt", Disabled, Enabled +} + +bool_enum! { + FlowController, "Flow Controller", Dma, Peripheral +} + +int_enum! { + TransferDirection <=> u8, + "Transfer Direction", + P2M <=> 0b00, + M2P <=> 0b01, + M2M <=> 0b10 +} + +bool_enum! { + CircularMode, "Circular Mode", Disabled, Enabled +} + +bool_enum! { + Pinc, "Peripheral Increment Mode", Fixed, Incremented +} + +bool_enum! { + Minc, "Memory Increment Mode", Fixed, Incremented +} + +int_enum! { + PSize <=> u8, + "Peripheral Data Size", + Byte <=> 0b00, + HalfWord <=> 0b01, + Word <=> 0b10 +} + +int_enum! { + MSize <=> u8, + "Memory Data Size", + Byte <=> 0b00, + HalfWord <=> 0b01, + Word <=> 0b10 +} + +bool_enum! { + Pincos, "Peripheral Increment Offset Size", PSize, Word +} + +int_enum! { + PriorityLevel <=> u8, + "Priority Level", + Low <=> 0b00, + Medium <=> 0b01, + High <=> 0b10, + VeryHigh <=> 0b11 +} + +bool_enum! { + BufferMode, "Buffer Mode", Regular, DoubleBuffer +} + +bool_enum! { + CurrentTarget, "CurrentTarget", M0a, M1a +} + +int_enum! { + PBurst <=> u8, + "Peripheral Burst", + Single <=> 0b00, + Incr4 <=> 0b01, + Incr8 <=> 0b10, + Incr16 <=> 0b11 +} + +int_enum! { + MBurst <=> u8, + "Memory Burst", + Single <=> 0b00, + Incr4 <=> 0b01, + Incr8 <=> 0b10, + Incr16 <=> 0b11 +} + +int_struct! { + Ndt, u16, 0, "Number of Data Items to transfer" +} + +int_struct! { + Pa, u32, 0, "Peripheral Address" +} + +int_struct! { + M0a, u32, 0, "Memory 0 Address" +} + +int_struct! { + M1a, u32, 0, "Memory 1 Address" +} + +bool_enum! { + TransferMode, "Transfer Mode", Direct, Fifo +} + +int_enum! { + FifoThreshold <=> u8, + "Fifo Threshold", + F1_4 <=> 0b00, + F1_2 <=> 0b01, + F3_4 <=> 0b10, + Full <=> 0b11 +} + +pub struct StreamIsr +where + DMA: DMATrait, +{ + pub(super) lisr: &'static LISR, + pub(super) hisr: &'static HISR, + pub(super) lifcr: &'static LIFCR, + pub(super) hifcr: &'static HIFCR, + _phantom_data: PhantomData, +} + +unsafe impl Sync for StreamIsr where DMA: DMATrait {} + +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +pub enum Event { + HalfTransfer, + TransferComplete, +} + +#[derive(Debug, Clone, Copy)] +pub struct Error { + pub transfer_error: bool, + pub direct_mode_error: bool, + pub fifo_error: bool, + pub event: Option, + pub crashed: bool, +} diff --git a/src/dma/utils.rs b/src/dma/utils.rs new file mode 100644 index 00000000..7cfec657 --- /dev/null +++ b/src/dma/utils.rs @@ -0,0 +1,3 @@ +use core::fmt::Debug; + +pub trait TypeState: Debug + PartialEq + Eq + Clone + Copy {} diff --git a/src/lib.rs b/src/lib.rs index 3cce8249..314f8885 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -67,6 +67,8 @@ pub use crate::stm32::interrupt; pub mod adc; #[cfg(feature = "device-selected")] pub mod delay; +#[cfg(feature = "stm32h743")] +pub mod dma; #[cfg(feature = "device-selected")] pub mod flash; #[cfg(feature = "device-selected")] From 509ab48efba51bf63487f92120106cf6c6d9030a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ad=C3=A4?= Date: Thu, 12 Dec 2019 11:08:56 +0100 Subject: [PATCH 002/103] Implemented dma stream config checks --- src/dma.rs | 84 ++++++++++++++++++++++++++++++++++++++++++++++- src/dma/stream.rs | 58 ++++++++++++++++++++++++++++++++ 2 files changed, 141 insertions(+), 1 deletion(-) diff --git a/src/dma.rs b/src/dma.rs index 508f6735..e017ba87 100644 --- a/src/dma.rs +++ b/src/dma.rs @@ -10,7 +10,7 @@ use self::stm32::{DMA1, DMA2}; use self::stream::{ BufferMode, CircularMode, CurrentTarget, DirectModeErrorInterrupt, Disabled, Disabling, Enabled, Error, Event, FifoErrorInterrupt, - FifoThreshold, FlowController, HalfTransferInterrupt, IsrCleared, + FifoThreshold, FlowController, HalfTransferInterrupt, IntoNum, IsrCleared, IsrState as IsrStateTrait, IsrUncleared, M0a, M1a, MBurst, MSize, Minc, Ndt, NotDisabled, PBurst, PSize, Pa, Pinc, Pincos, PriorityLevel, StreamIsr, TransferCompleteInterrupt, TransferDirection, @@ -340,10 +340,92 @@ where /// /// Aliasing rules aren't enforced pub unsafe fn enable(self) -> Stream { + self.check_config(); + + self.enable_unchecked() + } + + /// # Safety + /// + /// - Aliasing rules aren't enforced + /// - Config is not checked for guaranteeing data integrity + pub unsafe fn enable_unchecked( + self, + ) -> Stream { self.rb.cr.modify(|_, w| w.en().set_bit()); self.transmute() } + + fn check_config(&self) { + if self.circular_mode() == CircularMode::Enabled { + self.check_config_circular(); + } + if self.transfer_mode() == TransferMode::Fifo { + self.check_config_fifo(); + } + } + + fn check_config_circular(&self) { + if self.transfer_mode() == TransferMode::Fifo { + let ndt = self.ndt().value(); + let m_burst = self.m_burst().into_num() as u16; + let p_burst = self.p_burst().into_num() as u16; + let m_size = self.m_size().into_num() as u16; + let p_size = self.p_size().into_num() as u16; + + if ndt % (m_burst * (m_size / p_size)) != 0 { + panic!("Data integrity not guaranteed, because `num_data_items != Multiple of (m_burst * (m_size / p_size))`"); + } + + if ndt % (p_burst * p_size) != 0 { + panic!("Data integrity not guaranteed, because `num_data_items != Multiple of (p_burst * p_size)`"); + } + } else { + let ndt = self.ndt().value(); + let p_size = self.p_size().into_num() as u16; + + if ndt % p_size != 0 { + panic!("Data integrity not guaranteed, because `num_data_items != Multiple of (p_size)`"); + } + } + } + + fn check_config_fifo(&self) { + let m_size = self.m_size().into_num(); + let m_burst = self.m_burst().into_num(); + // Fifo Size in bytes + let fifo_size = self.fifo_threshold().into_num() * 4; + + if m_size * m_burst > fifo_size { + panic!("FIFO configuration invalid, because `msize * mburst > fifo_size`"); + } + + if fifo_size % (m_size * m_burst) != 0 { + panic!("FIFO configuration invalid, because `fifo_size % (msize * mburst) != 0`"); + } + + if self.transfer_direction() == TransferDirection::M2P { + self.check_config_fifo_m2p(); + } + } + + fn check_config_fifo_m2p(&self) { + let p_burst = self.p_burst().into_num(); + let p_size = self.p_size().into_num(); + // 4 Words = 16 Bytes + const FULL_FIFO_BYTES: usize = 16; + + if p_burst * p_size == FULL_FIFO_BYTES { + if self.fifo_threshold() == FifoThreshold::F3_4 { + panic!( + "FIFO configuration invalid, because \ + `pburst * psize == FULL_FIFO_SIZE` and \ + `fifo_threshhold = 3/4`" + ); + } + } + } } impl Stream diff --git a/src/dma/stream.rs b/src/dma/stream.rs index 52c4340e..0aa05a15 100644 --- a/src/dma/stream.rs +++ b/src/dma/stream.rs @@ -14,6 +14,10 @@ type_state! { IsrState, IsrCleared, IsrUncleared } +pub trait IntoNum { + fn into_num(self) -> usize; +} + bool_enum! { TransferCompleteInterrupt, "Transfer Complete Interrupt", Disabled, Enabled } @@ -66,6 +70,16 @@ int_enum! { Word <=> 0b10 } +impl IntoNum for PSize { + fn into_num(self) -> usize { + match self { + PSize::Byte => 1, + PSize::HalfWord => 2, + PSize::Word => 4, + } + } +} + int_enum! { MSize <=> u8, "Memory Data Size", @@ -74,6 +88,16 @@ int_enum! { Word <=> 0b10 } +impl IntoNum for MSize { + fn into_num(self) -> usize { + match self { + MSize::Byte => 1, + MSize::HalfWord => 2, + MSize::Word => 4, + } + } +} + bool_enum! { Pincos, "Peripheral Increment Offset Size", PSize, Word } @@ -104,6 +128,17 @@ int_enum! { Incr16 <=> 0b11 } +impl IntoNum for PBurst { + fn into_num(self) -> usize { + match self { + PBurst::Single => 1, + PBurst::Incr4 => 4, + PBurst::Incr8 => 8, + PBurst::Incr16 => 16, + } + } +} + int_enum! { MBurst <=> u8, "Memory Burst", @@ -113,6 +148,17 @@ int_enum! { Incr16 <=> 0b11 } +impl IntoNum for MBurst { + fn into_num(self) -> usize { + match self { + MBurst::Single => 1, + MBurst::Incr4 => 4, + MBurst::Incr8 => 8, + MBurst::Incr16 => 16, + } + } +} + int_struct! { Ndt, u16, 0, "Number of Data Items to transfer" } @@ -142,6 +188,18 @@ int_enum! { Full <=> 0b11 } +impl IntoNum for FifoThreshold { + /// Fifo threshold in words + fn into_num(self) -> usize { + match self { + FifoThreshold::F1_4 => 1, + FifoThreshold::F1_2 => 2, + FifoThreshold::F3_4 => 3, + FifoThreshold::Full => 4, + } + } +} + pub struct StreamIsr where DMA: DMATrait, From 064cce949f2f1c0a6d47d67cace06156429f1f2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ad=C3=A4?= Date: Thu, 12 Dec 2019 11:27:30 +0100 Subject: [PATCH 003/103] Using type Infallible for Errors that wont occur. --- src/dma.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/dma.rs b/src/dma.rs index e017ba87..a5fcfcfd 100644 --- a/src/dma.rs +++ b/src/dma.rs @@ -17,7 +17,7 @@ use self::stream::{ TransferErrorInterrupt, TransferMode, ED as EDTrait, }; use crate::nb::{self, Error as NbError}; -use core::convert::TryInto; +use core::convert::{Infallible, TryInto}; use core::marker::PhantomData; use stm32h7::stm32h743 as stm32; @@ -300,7 +300,7 @@ where ED: NotDisabled, IsrState: IsrStateTrait, { - pub fn set_m0a(&mut self, m0a: M0a) -> nb::Result<(), ()> { + pub fn set_m0a(&mut self, m0a: M0a) -> nb::Result<(), Infallible> { self.check_buffer_mode_addr_change(); if self.current_target() == CurrentTarget::M0a && self.is_enabled() { @@ -312,7 +312,7 @@ where Ok(()) } - pub fn set_m1a(&mut self, m1a: M1a) -> nb::Result<(), ()> { + pub fn set_m1a(&mut self, m1a: M1a) -> nb::Result<(), Infallible> { self.check_buffer_mode_addr_change(); if self.current_target() == CurrentTarget::M1a && self.is_enabled() { From 71b3b5bebd65b5b7025bc80927528d977cfd9072 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ad=C3=A4?= Date: Thu, 12 Dec 2019 20:27:44 +0100 Subject: [PATCH 004/103] Fixed stream config check --- src/dma.rs | 53 ++++++++++++++++++++++++++++++++++++----------------- src/lib.rs | 1 + 2 files changed, 37 insertions(+), 17 deletions(-) diff --git a/src/dma.rs b/src/dma.rs index a5fcfcfd..35426b17 100644 --- a/src/dma.rs +++ b/src/dma.rs @@ -1,3 +1,5 @@ +#![warn(clippy::all)] + #[macro_use] mod macros; pub mod channel; @@ -374,24 +376,45 @@ where let m_size = self.m_size().into_num() as u16; let p_size = self.p_size().into_num() as u16; - if ndt % (m_burst * (m_size / p_size)) != 0 { - panic!("Data integrity not guaranteed, because `num_data_items != Multiple of (m_burst * (m_size / p_size))`"); + if self.m_burst() != MBurst::Single + && ndt % (m_burst * m_size / p_size) != 0 + { + panic!( + "Data integrity not guaranteed, because \ + `num_data_items != Multiple of (m_burst * (m_size / p_size))`" + ); } if ndt % (p_burst * p_size) != 0 { - panic!("Data integrity not guaranteed, because `num_data_items != Multiple of (p_burst * p_size)`"); + panic!( + "Data integrity not guaranteed, because \ + `num_data_items != Multiple of (p_burst * p_size)`" + ); } } else { let ndt = self.ndt().value(); let p_size = self.p_size().into_num() as u16; if ndt % p_size != 0 { - panic!("Data integrity not guaranteed, because `num_data_items != Multiple of (p_size)`"); + panic!( + "Data integrity not guaranteed, because \ + `num_data_items != Multiple of (p_size)`" + ); } } } fn check_config_fifo(&self) { + if self.m_burst() != MBurst::Single { + self.check_config_fifo_m_burst(); + } + + if self.p_burst() != PBurst::Single { + self.check_config_fifo_p_burst(); + } + } + + fn check_config_fifo_m_burst(&self) { let m_size = self.m_size().into_num(); let m_burst = self.m_burst().into_num(); // Fifo Size in bytes @@ -404,26 +427,22 @@ where if fifo_size % (m_size * m_burst) != 0 { panic!("FIFO configuration invalid, because `fifo_size % (msize * mburst) != 0`"); } - - if self.transfer_direction() == TransferDirection::M2P { - self.check_config_fifo_m2p(); - } } - fn check_config_fifo_m2p(&self) { + fn check_config_fifo_p_burst(&self) { let p_burst = self.p_burst().into_num(); let p_size = self.p_size().into_num(); // 4 Words = 16 Bytes const FULL_FIFO_BYTES: usize = 16; - if p_burst * p_size == FULL_FIFO_BYTES { - if self.fifo_threshold() == FifoThreshold::F3_4 { - panic!( - "FIFO configuration invalid, because \ - `pburst * psize == FULL_FIFO_SIZE` and \ - `fifo_threshhold = 3/4`" - ); - } + if p_burst * p_size == FULL_FIFO_BYTES + && self.fifo_threshold() == FifoThreshold::F3_4 + { + panic!( + "FIFO configuration invalid, because \ + `pburst * psize == FULL_FIFO_SIZE` and \ + `fifo_threshhold == 3/4`" + ); } } } diff --git a/src/lib.rs b/src/lib.rs index 314f8885..f7e6bb0c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,6 @@ #![no_std] #![allow(non_camel_case_types)] +#![allow(clippy::all)] #[derive(Debug)] pub enum Never {} From f85576f456050b989b9d4b3417684a0408f8881c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ad=C3=A4?= Date: Thu, 12 Dec 2019 22:21:09 +0100 Subject: [PATCH 005/103] Started implementation of DmaMux and implemented its config --- src/dma.rs | 228 +++++++++++++++++++++++++++++++++++++++++++++++ src/dma/mux.rs | 235 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 463 insertions(+) create mode 100644 src/dma/mux.rs diff --git a/src/dma.rs b/src/dma.rs index 35426b17..1eaa08d7 100644 --- a/src/dma.rs +++ b/src/dma.rs @@ -3,11 +3,21 @@ #[macro_use] mod macros; pub mod channel; +pub mod mux; pub mod stream; mod utils; use self::channel::ChannelId; +use self::mux::request_ids::{ + ReqNone, RequestId as RequestIdTrait, RequestIdSome, +}; +use self::mux::{ + EgDisabled, EgED as EgEDTrait, EgEnabled, NbReq, RequestId, SyncDisabled, + SyncED as SyncEDTrait, SyncEnabled, SyncId, SyncOverrunInterrupt, + SyncPolarity, +}; use self::stm32::dma1::ST; +use self::stm32::dmamux1::CCR; use self::stm32::{DMA1, DMA2}; use self::stream::{ BufferMode, CircularMode, CurrentTarget, DirectModeErrorInterrupt, @@ -773,3 +783,221 @@ where IsrState: IsrStateTrait, { } + +pub struct DmaMux +where + CXX: ChannelId, + ReqId: RequestIdTrait, + SyncED: SyncEDTrait, + EgED: EgEDTrait, +{ + rb: &'static CCR, + req_id: ReqId, + _phantom_data: PhantomData<(CXX, SyncED, EgED)>, +} + +impl DmaMux +where + CXX: ChannelId, + ReqId: RequestIdTrait, + SyncED: SyncEDTrait, + EgED: EgEDTrait, +{ + pub fn id(&self) -> usize { + CXX::MUX_ID + } + + pub fn request_id(&self) -> RequestId { + self.rb.read().dmareq_id().bits().try_into().unwrap() + } + + pub fn sync_overrun_interrupt(&self) -> SyncOverrunInterrupt { + self.rb.read().soie().bit().into() + } + + pub fn set_sync_overrun_interrupt( + &mut self, + sync_overrun_intrpt: SyncOverrunInterrupt, + ) { + self.rb + .modify(|_, w| w.soie().bit(sync_overrun_intrpt.into())); + } + + pub fn sync_polarity(&self) -> SyncPolarity { + self.rb.read().spol().bits().try_into().unwrap() + } + + pub fn set_sync_polarity(&mut self, sync_polarity: SyncPolarity) { + self.rb.modify(|_, w| w.spol().bits(sync_polarity.into())); + } + + pub fn nbreq(&self) -> NbReq { + self.rb.read().nbreq().bits().try_into().unwrap() + } + + pub fn sync_id(&self) -> SyncId { + self.rb.read().sync_id().bits().try_into().unwrap() + } + + pub fn set_sync_id(&mut self, sync_id: SyncId) { + unsafe { + self.rb.modify(|_, w| w.sync_id().bits(sync_id.into())); + } + } + + fn set_req_id_impl(&mut self, request_id: RequestId) { + unsafe { + self.rb.modify(|_, w| w.dmareq_id().bits(request_id.into())); + } + } + + fn transmute( + self, + ) -> DmaMux + where + NewSyncED: SyncEDTrait, + NewEgED: EgEDTrait, + { + DmaMux { + rb: self.rb, + req_id: self.req_id, + _phantom_data: PhantomData, + } + } +} + +impl DmaMux +where + CXX: ChannelId, + ReqId: RequestIdTrait, +{ + pub fn set_nbreq(&mut self, nbreq: NbReq) { + self.rb.modify(|_, w| w.nbreq().bits(nbreq.into())); + } +} + +impl DmaMux +where + CXX: ChannelId, + ReqId: RequestIdTrait, + EgED: EgEDTrait, +{ + pub fn enable_sync(self) -> DmaMux { + self.rb.modify(|_, w| w.se().set_bit()); + + self.transmute() + } +} + +impl DmaMux +where + CXX: ChannelId, + ReqId: RequestIdTrait, + EgED: EgEDTrait, +{ + pub fn disable_sync(self) -> DmaMux { + self.rb.modify(|_, w| w.se().clear_bit()); + + self.transmute() + } +} + +impl DmaMux +where + CXX: ChannelId, + ReqId: RequestIdTrait, + SyncED: SyncEDTrait, +{ + pub fn enable_event_gen(self) -> DmaMux { + self.rb.modify(|_, w| w.ege().set_bit()); + + self.transmute() + } +} + +impl DmaMux +where + CXX: ChannelId, + ReqId: RequestIdTrait, + SyncED: SyncEDTrait, +{ + pub fn disable_event_gen(self) -> DmaMux { + self.rb.modify(|_, w| w.ege().clear_bit()); + + self.transmute() + } +} + +impl DmaMux +where + CXX: ChannelId, + SyncED: SyncEDTrait, + EgED: EgEDTrait, +{ + pub fn set_req_id( + mut self, + req_id: NewReqId, + ) -> DmaMux + where + NewReqId: RequestIdSome, + { + self.set_req_id_impl(req_id.request_id()); + + DmaMux { + req_id, + rb: self.rb, + _phantom_data: PhantomData, + } + } +} + +impl DmaMux +where + CXX: ChannelId, + ReqId: RequestIdSome, + SyncED: SyncEDTrait, + EgED: EgEDTrait, +{ + pub fn unset_req_id( + mut self, + ) -> (DmaMux, ReqId) { + self.set_req_id_impl(ReqNone::REQUEST_ID); + + let old_req_id = self.req_id; + let new_dma_mux = DmaMux { + rb: self.rb, + req_id: ReqNone, + _phantom_data: PhantomData, + }; + + (new_dma_mux, old_req_id) + } + + pub fn replace_req_id( + mut self, + req_id: NewReqId, + ) -> (DmaMux, ReqId) + where + NewReqId: RequestIdSome, + { + self.set_req_id_impl(req_id.request_id()); + + let old_req_id = self.req_id; + let new_dma_mux = DmaMux { + req_id, + rb: self.rb, + _phantom_data: PhantomData, + }; + + (new_dma_mux, old_req_id) + } +} + +unsafe impl Sync for DmaMux +where + CXX: ChannelId, + ReqId: RequestIdTrait, + SyncED: SyncEDTrait, + EgED: EgEDTrait, +{ +} diff --git a/src/dma/mux.rs b/src/dma/mux.rs new file mode 100644 index 00000000..83305d93 --- /dev/null +++ b/src/dma/mux.rs @@ -0,0 +1,235 @@ +type_state! { + SyncED, SyncDisabled, SyncEnabled +} + +type_state! { + EgED, EgDisabled, EgEnabled +} + +bool_enum! { + SyncOverrunInterrupt, "Synchronization overrun interrupt", Disabled, Enabled +} + +int_enum! { + SyncPolarity <=> u8, + "Synchronization Polarity", + NoEvent <=> 0b00, + RisingEdge <=> 0b01, + FallingEdge <=> 0b10, + RisingFallingEdge <=> 0b11 +} + +int_struct! { + NbReq, u8, 5, "Number of Requests" +} + +int_enum! { + SyncId <=> u8, + "Synchronization Identification", + DmaMux1Evt0 <=> 0b000, + DmaMux1Evt1 <=> 0b001, + DmaMux1Evt2 <=> 0b010, + Lptim1Out <=> 0b011, + Lptim2Out <=> 0b100, + Lptim3Out <=> 0b101, + Extit0 <=> 0b110, + Tim12Trgo <=> 0b111 +} + +macro_rules! request_id { + ($($request_id:ident => ($name:ident, $id:tt)),*) => { + use request_ids::{ + ReqNone, + $( + $request_id, + )* + }; + + pub struct RequestIds { + pub none: ReqNone, + $( + pub $name: $request_id, + )* + } + + impl RequestIds { + const fn new() -> Self { + RequestIds { + none: ReqNone, + $( + $name: $request_id::new(), + )* + } + } + } + + int_enum! { + RequestId <=> u8, + "Request Id", + None <=> 0, + $( + $request_id <=> $id + ),* + } + + pub mod request_ids { + use super::RequestId as RequestIdEnum; + + pub unsafe trait RequestId { + const REQUEST_ID: RequestIdEnum; + + fn request_id(&self) -> RequestIdEnum { + Self::REQUEST_ID + } + } + + #[derive(Clone, Copy)] + pub struct ReqNone; + + unsafe impl RequestId for ReqNone { + const REQUEST_ID: RequestIdEnum = RequestIdEnum::None; + } + + pub unsafe trait RequestIdSome: RequestId {} + + $( + pub struct $request_id { + _priv: (), + } + + impl $request_id { + pub(super) const fn new() -> Self { + $request_id { + _priv: (), + } + } + } + + unsafe impl RequestId for $request_id { + const REQUEST_ID: RequestIdEnum = RequestIdEnum::$request_id; + } + + unsafe impl RequestIdSome for $request_id {} + )* + } + }; +} + +request_id! { + DmaMux1ReqGen0 => (dma_mux_1_req_gen_0, 1), + DmaMux1ReqGen1 => (dma_mux_1_req_gen_1, 2), + DmaMux1ReqGen2 => (dma_mux_1_req_gen_2, 3), + DmaMux1ReqGen3 => (dma_mux_1_req_gen_3, 4), + DmaMux1ReqGen4 => (dma_mux_1_req_gen_4, 5), + DmaMux1ReqGen5 => (dma_mux_1_req_gen_5, 6), + DmaMux1ReqGen6 => (dma_mux_1_req_gen_6, 7), + DmaMux1ReqGen7 => (dma_mux_1_req_gen_7, 8), + Adc1Dma => (adc_1_dma, 9), + Adc2Dma => (adc_2_dma, 10), + Tim1Ch1 => (tim_1_ch_1, 11), + Tim1Ch2 => (tim_1_ch_2, 12), + Tim1Ch3 => (tim_1_ch_3, 13), + Tim1Ch4 => (tim_1_ch_4, 14), + Tim1Up => (tim_1_up, 15), + Tim1Trig => (tim_1_trig, 16), + Tim1Com => (tim_1_com, 17), + Tim2Ch1 => (tim_2_ch_1, 18), + Tim2Ch2 => (tim_2_ch_2, 19), + Tim2Ch3 => (tim_2_ch_3, 20), + Tim2Ch4 => (tim_2_ch_4, 21), + Tim2Up => (tim_2_up, 22), + Tim3Ch1 => (tim_3_ch_1, 23), + Tim3Ch2 => (tim_3_ch_2, 24), + Tim3Ch3 => (tim_3_ch_3, 25), + Tim3Ch4 => (tim_3_ch_4, 26), + Tim3Up => (tim_3_up, 27), + Tim3Trig => (tim_3_trig, 28), + Tim4Ch1 => (tim_4_ch1, 29), + Tim4Ch2 => (tim_4_ch2, 30), + Tim4Ch3 => (tim_4_ch3, 31), + Tim4Up => (tim_4_up, 32), + I2c1RxDma => (i2c_1_rx_dma, 33), + I2c1TxDma => (i2c_1_tx_dma, 34), + I2c2RxDma => (i2c_2_rx_dma, 35), + I2c2TxDma => (i2c_2_tx_dma, 36), + Spi1RxDma => (spi_1_rx_dma, 37), + Spi1TxDma => (spi_1_tx_dma, 38), + Spi2RxDma => (spi_2_rx_dma, 39), + Spi2TxDma => (spi_2_tx_dma, 40), + Usart1RxDma => (usart_1_rx_dma, 41), + Usart1TxDma => (usart_1_tx_dma, 42), + Usart2RxDma => (usart_2_rx_dma, 43), + Usart2TxDma => (usart_2_tx_dma, 44), + Usart3RxDma => (usart_3_rx_dma, 45), + Usart3TxDma => (usart_3_tx_dma, 46), + Tim8Ch1 => (tim_8_ch_1, 47), + Tim8Ch2 => (tim_8_ch_2, 48), + Tim8Ch3 => (tim_8_ch_3, 49), + Tim8Ch4 => (tim_8_ch_4, 50), + Tim8Up => (tim_8_up, 51), + Tim8Trig => (tim_8_trig, 52), + Tim8Com => (tim_8_com, 53), + // 54 Reserved + Tim5Ch1 => (tim_5_ch_1, 55), + Tim5Ch2 => (tim_5_ch_2, 56), + Tim5Ch3 => (tim_5_ch_3, 57), + Tim5Ch4 => (tim_5_ch_4, 58), + Tim5Up => (tim_5_up, 59), + Tim5Trig => (tim_5_trig, 60), + Spi3RxDma => (spi_3_rx_dma, 61), + Spi3TxDma => (spi_3_tx_dma, 62), + Uart4RxDma => (uart_4_rx_dma, 63), + Uart4TxDma => (uart_4_tx_dma, 64), + Uart5RxDma => (uart_5_rx_dma, 65), + Uart5TxDma => (uart_5_tx_dma, 66), + DacCh1Dma => (dac_ch_1_dma, 67), + DacCh2Dma => (dac_ch_2_dma, 68), + Tim6Up => (tim_6_up, 69), + Tim7Up => (tim_7_up, 70), + Usart6RxDma => (usart_6_rx_dma, 71), + Usart6TxDma => (usart_6_tx_dma, 72), + I2c3RxDma => (i2c_3_rx_dma, 73), + I2c3TxDma => (i2c_3_tx_dma, 74), + DcmiDma => (dcmi_dma, 75), + CrypInDma => (cryp_in_dma, 76), + CrypOutDma => (cryp_out_dma, 77), + HashInDma => (hash_in_dma, 78), + Uart7RxDma => (uart_7_rx_dma, 79), + Uart7TxDma => (uart_7_tx_dma, 80), + Uart8RxDma => (uart_8_rx_dma, 81), + Uart8TxDma => (uart_8_tx_dma, 82), + Spi4RxDma => (spi_4_rx_dma, 83), + Spi4TxDma => (spi_4_tx_dma, 84), + Spi5RxDma => (spi_5_rx_dma, 85), + Spi5TxDma => (spi_5_tx_dma, 86), + Sai1aDma => (sai_1a_dma, 87), + Sai1bDma => (sai_1b_dma, 88), + Sai2aDma => (sai_2a_dma, 89), + Sai2bDma => (sai_2b_dma, 90), + SwpmiRxDma => (swpmi_rx_dma, 91), + SwpmiTxDma => (swpmi_tx_dma, 92), + SpdifrxDatDma => (spdifrx_dat_dma, 93), + SpdifrxCtrlDma => (spdifrx_ctrl_dma, 94), + HrReq1 => (hr_req_1, 95), + HrReq2 => (hr_req_2, 96), + HrReq3 => (hr_req_3, 97), + HrReq4 => (hr_req_4, 98), + HrReq5 => (hr_req_5, 99), + HrReq6 => (hr_req_6, 100), + Dfsdm1Dma0 => (dfsdm_1_dma_0, 101), + Dfsdm1Dma1 => (dfsdm_1_dma_1, 102), + Dfsdm1Dma2 => (dfsdm_1_dma_2, 103), + Dfsdm1Dma3 => (dfsdm_1_dma_3, 104), + Tim15Ch1 => (tim_15_ch_1, 105), + Tim15Up => (tim_15_up, 106), + Tim15Trig => (tim_15_trig, 107), + Tim15Com => (tim_15_com, 108), + Tim16Ch1 => (tim_16_ch_1, 109), + Tim16Up => (tim_16_up, 110), + Tim17Ch1 => (tim_17_ch_1, 111), + Tim17Up => (tim_17_up, 112), + Sai3aDma => (sai_3a_dma, 113), + Sai3bDma => (sai_3b_dma, 114), + Adc3Dma => (adc_3_dma, 115) + // [116; 127] reserved +} From c679d3f61603a3b0054e4ca00e715af0d890217b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ad=C3=A4?= Date: Thu, 12 Dec 2019 23:44:37 +0100 Subject: [PATCH 006/103] Implemented Isr for Dma mux --- src/dma.rs | 51 ++++++++++++++++++++++++++++++++++++++++--- src/dma/mux.rs | 10 +++++++++ src/dma/mux/shared.rs | 8 +++++++ 3 files changed, 66 insertions(+), 3 deletions(-) create mode 100644 src/dma/mux/shared.rs diff --git a/src/dma.rs b/src/dma.rs index 1eaa08d7..b7514c03 100644 --- a/src/dma.rs +++ b/src/dma.rs @@ -11,10 +11,11 @@ use self::channel::ChannelId; use self::mux::request_ids::{ ReqNone, RequestId as RequestIdTrait, RequestIdSome, }; +use self::mux::shared::MuxIsr; use self::mux::{ - EgDisabled, EgED as EgEDTrait, EgEnabled, NbReq, RequestId, SyncDisabled, - SyncED as SyncEDTrait, SyncEnabled, SyncId, SyncOverrunInterrupt, - SyncPolarity, + EgDisabled, EgED as EgEDTrait, EgEnabled, NbReq, OverrunError, RequestId, + SyncDisabled, SyncED as SyncEDTrait, SyncEnabled, SyncId, + SyncOverrunInterrupt, SyncPolarity, }; use self::stm32::dma1::ST; use self::stm32::dmamux1::CCR; @@ -993,6 +994,50 @@ where } } +impl DmaMux +where + CXX: ChannelId, + ReqId: RequestIdTrait, + SyncED: SyncEDTrait, + EgED: EgEDTrait, +{ + pub fn check_isr(&self, mux_isr: &MuxIsr) -> Result<(), OverrunError> { + if self.is_sync_overrun(mux_isr) { + Err(OverrunError) + } else { + Ok(()) + } + } + + pub fn is_sync_overrun(&self, mux_isr: &MuxIsr) -> bool { + let mask: u16 = 1 << self.id() as u16; + + mux_isr.csr.read().sof().bits() & mask != 0 + } + + pub fn clear_isr(&self, mux_isr: &mut MuxIsr) { + match self.id() { + 0 => mux_isr.cfr.write(|w| w.csof0().set_bit()), + 1 => mux_isr.cfr.write(|w| w.csof1().set_bit()), + 2 => mux_isr.cfr.write(|w| w.csof2().set_bit()), + 3 => mux_isr.cfr.write(|w| w.csof3().set_bit()), + 4 => mux_isr.cfr.write(|w| w.csof4().set_bit()), + 5 => mux_isr.cfr.write(|w| w.csof5().set_bit()), + 6 => mux_isr.cfr.write(|w| w.csof6().set_bit()), + 7 => mux_isr.cfr.write(|w| w.csof7().set_bit()), + 8 => mux_isr.cfr.write(|w| w.csof8().set_bit()), + 9 => mux_isr.cfr.write(|w| w.csof9().set_bit()), + 10 => mux_isr.cfr.write(|w| w.csof10().set_bit()), + 11 => mux_isr.cfr.write(|w| w.csof11().set_bit()), + 12 => mux_isr.cfr.write(|w| w.csof12().set_bit()), + 13 => mux_isr.cfr.write(|w| w.csof13().set_bit()), + 14 => mux_isr.cfr.write(|w| w.csof14().set_bit()), + 15 => mux_isr.cfr.write(|w| w.csof15().set_bit()), + _ => unreachable!(), + } + } +} + unsafe impl Sync for DmaMux where CXX: ChannelId, diff --git a/src/dma/mux.rs b/src/dma/mux.rs index 83305d93..1c158830 100644 --- a/src/dma/mux.rs +++ b/src/dma/mux.rs @@ -1,3 +1,7 @@ +pub mod shared; + +use self::shared::MuxIsr; + type_state! { SyncED, SyncDisabled, SyncEnabled } @@ -233,3 +237,9 @@ request_id! { Adc3Dma => (adc_3_dma, 115) // [116; 127] reserved } + +pub struct MuxShared { + pub mux_isr: MuxIsr, +} + +pub struct OverrunError; diff --git a/src/dma/mux/shared.rs b/src/dma/mux/shared.rs new file mode 100644 index 00000000..7e0995ff --- /dev/null +++ b/src/dma/mux/shared.rs @@ -0,0 +1,8 @@ +use super::super::stm32::dmamux1::{CFR, CSR}; + +pub struct MuxIsr { + pub(in super::super) csr: &'static CSR, + pub(in super::super) cfr: &'static CFR, +} + +unsafe impl Sync for MuxIsr {} From 7ccafaba4dbf68af17aeae2edea7cec024cf91de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ad=C3=A4?= Date: Sat, 14 Dec 2019 16:50:37 +0100 Subject: [PATCH 007/103] Fixed state machine of dma mux --- src/dma.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dma.rs b/src/dma.rs index b7514c03..e8dca05a 100644 --- a/src/dma.rs +++ b/src/dma.rs @@ -922,7 +922,7 @@ where ReqId: RequestIdTrait, SyncED: SyncEDTrait, { - pub fn disable_event_gen(self) -> DmaMux { + pub fn disable_event_gen(self) -> DmaMux { self.rb.modify(|_, w| w.ege().clear_bit()); self.transmute() From 647521175928be5c57a337c1083c9a0d858c4ed1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ad=C3=A4?= Date: Sat, 14 Dec 2019 16:56:21 +0100 Subject: [PATCH 008/103] Changed my email address in cargo.toml --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 42cc1006..766380f7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,7 +4,7 @@ version = "0.2.1" authors = ["Andrew Straw ", "Richard Meadows ", "Henrik Böving ", - "Jan Adä ", + "Jan Adä ", "Robert Jördens "] edition = "2018" categories = ["embedded", "hardware-support", "no-std"] From f58c273225efa80a062b0d439b4deb866de8c88d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ad=C3=A4?= Date: Sat, 14 Dec 2019 18:40:46 +0100 Subject: [PATCH 009/103] Minor improvements --- src/dma.rs | 17 +++++++++++++---- src/dma/mux.rs | 20 +++++++++++++------- src/dma/mux/request_gen.rs | 32 ++++++++++++++++++++++++++++++++ 3 files changed, 58 insertions(+), 11 deletions(-) create mode 100644 src/dma/mux/request_gen.rs diff --git a/src/dma.rs b/src/dma.rs index e8dca05a..8d273a8b 100644 --- a/src/dma.rs +++ b/src/dma.rs @@ -30,7 +30,7 @@ use self::stream::{ TransferErrorInterrupt, TransferMode, ED as EDTrait, }; use crate::nb::{self, Error as NbError}; -use core::convert::{Infallible, TryInto}; +use core::convert::{Infallible, TryInto, TryFrom}; use core::marker::PhantomData; use stm32h7::stm32h743 as stm32; @@ -809,7 +809,16 @@ where } pub fn request_id(&self) -> RequestId { - self.rb.read().dmareq_id().bits().try_into().unwrap() + debug_assert_eq!( + ReqId::REQUEST_ID, + RequestId::try_from(self.rb.read().dmareq_id().bits()).unwrap(), + "DmaMux is in invalid state, because \ + `ReqId::REQUEST_ID` ({:?}) != Volatile request id ({:?})", + ReqId::REQUEST_ID, + RequestId::try_from(self.rb.read().dmareq_id().bits()).unwrap(), + ); + + ReqId::REQUEST_ID } pub fn sync_overrun_interrupt(&self) -> SyncOverrunInterrupt { @@ -942,7 +951,7 @@ where where NewReqId: RequestIdSome, { - self.set_req_id_impl(req_id.request_id()); + self.set_req_id_impl(NewReqId::REQUEST_ID); DmaMux { req_id, @@ -981,7 +990,7 @@ where where NewReqId: RequestIdSome, { - self.set_req_id_impl(req_id.request_id()); + self.set_req_id_impl(NewReqId::REQUEST_ID); let old_req_id = self.req_id; let new_dma_mux = DmaMux { diff --git a/src/dma/mux.rs b/src/dma/mux.rs index 1c158830..038a4672 100644 --- a/src/dma/mux.rs +++ b/src/dma/mux.rs @@ -1,6 +1,10 @@ pub mod shared; +pub mod request_gen; use self::shared::MuxIsr; +use super::stm32::dmamux1::RGCR; +use core::marker::PhantomData; +use core::fmt::Display; type_state! { SyncED, SyncDisabled, SyncEnabled @@ -43,14 +47,12 @@ int_enum! { macro_rules! request_id { ($($request_id:ident => ($name:ident, $id:tt)),*) => { use request_ids::{ - ReqNone, $( $request_id, )* }; pub struct RequestIds { - pub none: ReqNone, $( pub $name: $request_id, )* @@ -59,7 +61,6 @@ macro_rules! request_id { impl RequestIds { const fn new() -> Self { RequestIds { - none: ReqNone, $( $name: $request_id::new(), )* @@ -81,10 +82,6 @@ macro_rules! request_id { pub unsafe trait RequestId { const REQUEST_ID: RequestIdEnum; - - fn request_id(&self) -> RequestIdEnum { - Self::REQUEST_ID - } } #[derive(Clone, Copy)] @@ -243,3 +240,12 @@ pub struct MuxShared { } pub struct OverrunError; + +pub struct RequestGenerator { + rb: &'static RGCR, + _phantom_data: PhantomData<(GXX, ED)>, +} + +impl RequestGenerator { + +} diff --git a/src/dma/mux/request_gen.rs b/src/dma/mux/request_gen.rs new file mode 100644 index 00000000..0d5ec214 --- /dev/null +++ b/src/dma/mux/request_gen.rs @@ -0,0 +1,32 @@ +use super::super::utils::TypeState; + +type_state! { + ED, Disabled, Enabled +} + +pub unsafe trait GenId { + const ID: usize; +} + +macro_rules! gen_ids { + ($($name:ident => $id:tt),*) => { + $( + pub struct $name; + + unsafe impl GenId for $name { + const ID:usize = $id; + } + )* + }; +} + +gen_ids! { + G0 => 0, + G1 => 1, + G2 => 2, + G3 => 3, + G4 => 4, + G5 => 5, + G6 => 6, + G7 => 7 +} From 7a2edd139f447d96542d9510acb980d95dcae8c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ad=C3=A4?= Date: Sat, 14 Dec 2019 19:00:51 +0100 Subject: [PATCH 010/103] Implemented config for dma request generator --- src/dma.rs | 2 +- src/dma/mux.rs | 90 ++++++++++++++++++++++++++++++++++++-- src/dma/mux/request_gen.rs | 30 +++++++++++++ 3 files changed, 117 insertions(+), 5 deletions(-) diff --git a/src/dma.rs b/src/dma.rs index 8d273a8b..aecd3268 100644 --- a/src/dma.rs +++ b/src/dma.rs @@ -30,7 +30,7 @@ use self::stream::{ TransferErrorInterrupt, TransferMode, ED as EDTrait, }; use crate::nb::{self, Error as NbError}; -use core::convert::{Infallible, TryInto, TryFrom}; +use core::convert::{Infallible, TryFrom, TryInto}; use core::marker::PhantomData; use stm32h7::stm32h743 as stm32; diff --git a/src/dma/mux.rs b/src/dma/mux.rs index 038a4672..01a28ed8 100644 --- a/src/dma/mux.rs +++ b/src/dma/mux.rs @@ -1,10 +1,14 @@ -pub mod shared; pub mod request_gen; +pub mod shared; +use self::request_gen::{ + Disabled as GenDisabled, GNbReq, GPol, GenId, + OverrunInterrupt as GenOverrunInterrupt, SigId, ED as GenED, +}; use self::shared::MuxIsr; use super::stm32::dmamux1::RGCR; +use core::convert::TryInto; use core::marker::PhantomData; -use core::fmt::Display; type_state! { SyncED, SyncDisabled, SyncEnabled @@ -241,11 +245,89 @@ pub struct MuxShared { pub struct OverrunError; -pub struct RequestGenerator { +pub struct RequestGenerator +where + GXX: GenId, + ED: GenED, +{ rb: &'static RGCR, _phantom_data: PhantomData<(GXX, ED)>, } -impl RequestGenerator { +impl RequestGenerator +where + GXX: GenId, +{ + pub(super) fn after_reset(rb: &'static RGCR) -> Self { + RequestGenerator { + rb, + _phantom_data: PhantomData, + } + } +} + +impl RequestGenerator +where + GXX: GenId, + ED: GenED, +{ + pub fn id(&self) -> usize { + GXX::ID + } + + pub fn sig_id(&self) -> SigId { + self.rb.read().sig_id().bits().try_into().unwrap() + } + + pub fn set_sig_id(&mut self, sig_id: SigId) { + unsafe { + self.rb.modify(|_, w| w.sig_id().bits(sig_id.into())); + } + } + + pub fn overrun_interrupt(&self) -> GenOverrunInterrupt { + self.rb.read().oie().bit().into() + } + pub fn set_overrun_interrupt( + &mut self, + overrun_intrpt: GenOverrunInterrupt, + ) { + self.rb.modify(|_, w| w.oie().bit(overrun_intrpt.into())); + } + + pub fn gpol(&self) -> GPol { + self.rb.read().gpol().bits().try_into().unwrap() + } + + pub fn set_gpol(&mut self, gpol: GPol) { + unsafe { + self.rb.modify(|_, w| w.gpol().bits(gpol.into())); + } + } + + pub fn gnbreq(&self) -> GNbReq { + self.rb.read().gnbreq().bits().try_into().unwrap() + } + + fn transmute(self) -> RequestGenerator + where + NewGenED: GenED, + { + RequestGenerator { + rb: self.rb, + _phantom_data: PhantomData, + } + } +} + +impl RequestGenerator +where + GXX: GenId, +{ + pub fn set_gnbreq(&mut self, gnbreq: GNbReq) { + unsafe { + self.rb.modify(|_, w| w.gnbreq().bits(gnbreq.into())); + } + } } diff --git a/src/dma/mux/request_gen.rs b/src/dma/mux/request_gen.rs index 0d5ec214..a9c0cd3c 100644 --- a/src/dma/mux/request_gen.rs +++ b/src/dma/mux/request_gen.rs @@ -30,3 +30,33 @@ gen_ids! { G6 => 6, G7 => 7 } + +int_enum! { + SigId <=> u8, + "Signal Identification", + DmaMux1Evt0 <=> 0b000, + DmaMux1Evt1 <=> 0b001, + DmaMux1Evt2 <=> 0b010, + Lptim1Out <=> 0b011, + Lptim2Out <=> 0b100, + Lptim3Out <=> 0b101, + Extit0 <=> 0b110, + Tim12Trgo <=> 0b111 +} + +bool_enum! { + OverrunInterrupt, "Overrun Interrupt", Disabled, Enabled +} + +int_enum! { + GPol <=> u8, + "Request Generator Trigger Polarity", + NoEvent <=> 0b00, + RisingEdge <=> 0b01, + FallingEdge <=> 0b10, + RisingFallingEdge <=> 0b11 +} + +int_struct! { + GNbReq, u8, 5, "Number of DMA Requests to be generated (minus 1)" +} From 0a4242f520cac7072a9e2ea26c07c9bdb62368e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ad=C3=A4?= Date: Sat, 14 Dec 2019 20:12:16 +0100 Subject: [PATCH 011/103] Implemented enable / disable method for DMA Request generator --- src/dma/channel.rs | 9 +++++++-- src/dma/macros.rs | 4 ++-- src/dma/mux.rs | 27 ++++++++++++++++++++------- src/dma/mux/request_gen.rs | 7 +++++-- src/dma/utils.rs | 3 ++- 5 files changed, 36 insertions(+), 14 deletions(-) diff --git a/src/dma/channel.rs b/src/dma/channel.rs index 6831ec3e..d3463bb2 100644 --- a/src/dma/channel.rs +++ b/src/dma/channel.rs @@ -1,4 +1,6 @@ -pub trait ChannelId { +use super::utils::PhantomType; + +pub unsafe trait ChannelId: PhantomType { const STREAM_ID: usize; const MUX_ID: usize; } @@ -6,9 +8,12 @@ pub trait ChannelId { macro_rules! channels { ($($channel:ident => [$stream:tt, $mux:tt]),*) => { $( + #[derive(Debug, PartialEq, Eq, Clone, Copy)] pub struct $channel; - impl ChannelId for $channel { + impl PhantomType for $channel {} + + unsafe impl ChannelId for $channel { const STREAM_ID: usize = $stream; const MUX_ID: usize = $mux; } diff --git a/src/dma/macros.rs b/src/dma/macros.rs index 1bcecfd7..e1e398f9 100644 --- a/src/dma/macros.rs +++ b/src/dma/macros.rs @@ -1,12 +1,12 @@ macro_rules! type_state { ($trait:ident, $($type_state:ident),*) => { - pub unsafe trait $trait: crate::dma::utils::TypeState {} + pub unsafe trait $trait: crate::dma::utils::PhantomType {} $( #[derive(Debug, PartialEq, Eq, Clone, Copy)] pub struct $type_state; - impl crate::dma::utils::TypeState for $type_state {} + impl crate::dma::utils::PhantomType for $type_state {} unsafe impl $trait for $type_state {} )* }; diff --git a/src/dma/mux.rs b/src/dma/mux.rs index 01a28ed8..f85fbb2d 100644 --- a/src/dma/mux.rs +++ b/src/dma/mux.rs @@ -2,7 +2,7 @@ pub mod request_gen; pub mod shared; use self::request_gen::{ - Disabled as GenDisabled, GNbReq, GPol, GenId, + Disabled as GenDisabled, Enabled as GenEnabled, GNbReq, GPol, GenId, OverrunInterrupt as GenOverrunInterrupt, SigId, ED as GenED, }; use self::shared::MuxIsr; @@ -301,9 +301,7 @@ where } pub fn set_gpol(&mut self, gpol: GPol) { - unsafe { - self.rb.modify(|_, w| w.gpol().bits(gpol.into())); - } + self.rb.modify(|_, w| w.gpol().bits(gpol.into())); } pub fn gnbreq(&self) -> GNbReq { @@ -326,8 +324,23 @@ where GXX: GenId, { pub fn set_gnbreq(&mut self, gnbreq: GNbReq) { - unsafe { - self.rb.modify(|_, w| w.gnbreq().bits(gnbreq.into())); - } + self.rb.modify(|_, w| w.gnbreq().bits(gnbreq.into())); + } + + pub fn enable(self) -> RequestGenerator { + self.rb.modify(|_, w| w.ge().set_bit()); + + self.transmute() + } +} + +impl RequestGenerator +where + GXX: GenId, +{ + pub fn disable(self) -> RequestGenerator { + self.rb.modify(|_, w| w.ge().clear_bit()); + + self.transmute() } } diff --git a/src/dma/mux/request_gen.rs b/src/dma/mux/request_gen.rs index a9c0cd3c..13e37c4d 100644 --- a/src/dma/mux/request_gen.rs +++ b/src/dma/mux/request_gen.rs @@ -1,18 +1,21 @@ -use super::super::utils::TypeState; +use super::super::utils::PhantomType; type_state! { ED, Disabled, Enabled } -pub unsafe trait GenId { +pub unsafe trait GenId: PhantomType { const ID: usize; } macro_rules! gen_ids { ($($name:ident => $id:tt),*) => { $( + #[derive(Debug, PartialEq, Eq, Clone, Copy)] pub struct $name; + impl PhantomType for $name {} + unsafe impl GenId for $name { const ID:usize = $id; } diff --git a/src/dma/utils.rs b/src/dma/utils.rs index 7cfec657..ba70c605 100644 --- a/src/dma/utils.rs +++ b/src/dma/utils.rs @@ -1,3 +1,4 @@ use core::fmt::Debug; -pub trait TypeState: Debug + PartialEq + Eq + Clone + Copy {} +/// Used to enable usage of derive macros for structs using Self as Phantom Type. +pub trait PhantomType: Debug + PartialEq + Eq + Clone + Copy {} From 1046e450f21de623a828e5e7db78a663cb861e55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ad=C3=A4?= Date: Sat, 14 Dec 2019 20:26:25 +0100 Subject: [PATCH 012/103] Replaced static with static mut references to justify unsafe sync implementations --- src/dma.rs | 6 +++--- src/dma/mux.rs | 3 ++- src/dma/mux/shared.rs | 13 ++++++++++--- src/dma/stream.rs | 8 ++++---- 4 files changed, 19 insertions(+), 11 deletions(-) diff --git a/src/dma.rs b/src/dma.rs index aecd3268..1de72ba4 100644 --- a/src/dma.rs +++ b/src/dma.rs @@ -45,7 +45,7 @@ where ED: EDTrait, IsrState: IsrStateTrait, { - rb: &'static ST, + rb: &'static mut ST, _phantom_data: PhantomData<(CXX, DMA, ED, IsrState)>, } @@ -54,7 +54,7 @@ where CXX: ChannelId, DMA: DMATrait, { - fn new(rb: &'static ST) -> Self { + fn new(rb: &'static mut ST) -> Self { Stream { rb, _phantom_data: PhantomData, @@ -792,7 +792,7 @@ where SyncED: SyncEDTrait, EgED: EgEDTrait, { - rb: &'static CCR, + rb: &'static mut CCR, req_id: ReqId, _phantom_data: PhantomData<(CXX, SyncED, EgED)>, } diff --git a/src/dma/mux.rs b/src/dma/mux.rs index f85fbb2d..fafa1404 100644 --- a/src/dma/mux.rs +++ b/src/dma/mux.rs @@ -5,7 +5,7 @@ use self::request_gen::{ Disabled as GenDisabled, Enabled as GenEnabled, GNbReq, GPol, GenId, OverrunInterrupt as GenOverrunInterrupt, SigId, ED as GenED, }; -use self::shared::MuxIsr; +use self::shared::{MuxIsr, RequestGenIsr}; use super::stm32::dmamux1::RGCR; use core::convert::TryInto; use core::marker::PhantomData; @@ -241,6 +241,7 @@ request_id! { pub struct MuxShared { pub mux_isr: MuxIsr, + pub req_gen_isr: RequestGenIsr, } pub struct OverrunError; diff --git a/src/dma/mux/shared.rs b/src/dma/mux/shared.rs index 7e0995ff..d8f6e6eb 100644 --- a/src/dma/mux/shared.rs +++ b/src/dma/mux/shared.rs @@ -1,8 +1,15 @@ -use super::super::stm32::dmamux1::{CFR, CSR}; +use super::super::stm32::dmamux1::{CFR, CSR, RGSR, RGCFR}; pub struct MuxIsr { - pub(in super::super) csr: &'static CSR, - pub(in super::super) cfr: &'static CFR, + pub(in super::super) csr: &'static mut CSR, + pub(in super::super) cfr: &'static mut CFR, } unsafe impl Sync for MuxIsr {} + +pub struct RequestGenIsr { + pub(in super::super) rgsr: &'static mut RGSR, + pub(in super::super) rgcfr: &'static mut RGCFR, +} + +unsafe impl Sync for RequestGenIsr {} diff --git a/src/dma/stream.rs b/src/dma/stream.rs index 0aa05a15..f7fd5f49 100644 --- a/src/dma/stream.rs +++ b/src/dma/stream.rs @@ -204,10 +204,10 @@ pub struct StreamIsr where DMA: DMATrait, { - pub(super) lisr: &'static LISR, - pub(super) hisr: &'static HISR, - pub(super) lifcr: &'static LIFCR, - pub(super) hifcr: &'static HIFCR, + pub(super) lisr: &'static mut LISR, + pub(super) hisr: &'static mut HISR, + pub(super) lifcr: &'static mut LIFCR, + pub(super) hifcr: &'static mut HIFCR, _phantom_data: PhantomData, } From 168a74a6b1f5c2c15a793f7bbad81f2ef47f444b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ad=C3=A4?= Date: Sun, 15 Dec 2019 00:19:13 +0100 Subject: [PATCH 013/103] Implemented isr of dma mux --- src/dma.rs | 28 +++++++++--------- src/dma/mux.rs | 58 +++++++++++++++++++++++++++++++++----- src/dma/mux/request_gen.rs | 5 +++- src/dma/mux/shared.rs | 8 ++++-- 4 files changed, 75 insertions(+), 24 deletions(-) diff --git a/src/dma.rs b/src/dma.rs index 1de72ba4..4cf273fe 100644 --- a/src/dma.rs +++ b/src/dma.rs @@ -45,6 +45,7 @@ where ED: EDTrait, IsrState: IsrStateTrait, { + /// This field *must not* be mutated by shared references rb: &'static mut ST, _phantom_data: PhantomData<(CXX, DMA, ED, IsrState)>, } @@ -314,7 +315,7 @@ where IsrState: IsrStateTrait, { pub fn set_m0a(&mut self, m0a: M0a) -> nb::Result<(), Infallible> { - self.check_buffer_mode_addr_change(); + self.check_double_buffer(); if self.current_target() == CurrentTarget::M0a && self.is_enabled() { return Err(NbError::WouldBlock); @@ -326,7 +327,7 @@ where } pub fn set_m1a(&mut self, m1a: M1a) -> nb::Result<(), Infallible> { - self.check_buffer_mode_addr_change(); + self.check_double_buffer(); if self.current_target() == CurrentTarget::M1a && self.is_enabled() { return Err(NbError::WouldBlock); @@ -337,7 +338,7 @@ where Ok(()) } - fn check_buffer_mode_addr_change(&self) { + fn check_double_buffer(&self) { if self.buffer_mode() == BufferMode::Regular { panic!("The buffer must be in double buffer mode to be changed on the fly."); } @@ -494,13 +495,13 @@ where &self, isr: &StreamIsr, ) -> Result, Error> { - let transfer_error = self.is_transfer_error(isr); - let direct_mode_error = self.is_direct_mode_error(isr); - let fifo_error = self.is_fifo_error(isr); + let transfer_error = self.transfer_error_flag(isr); + let direct_mode_error = self.direct_mode_error_flag(isr); + let fifo_error = self.fifo_error_flag(isr); - let event = if self.is_transfer_completed(isr) { + let event = if self.transfer_complete_flag(isr) { Some(Event::TransferComplete) - } else if self.is_half_transfer(isr) { + } else if self.half_transfer_flag(isr) { Some(Event::HalfTransfer) } else { None @@ -521,7 +522,7 @@ where } } - pub fn is_transfer_completed(&self, isr: &StreamIsr) -> bool { + pub fn transfer_complete_flag(&self, isr: &StreamIsr) -> bool { match self.id() { 0 => isr.lisr.read().tcif0().bit_is_set(), 1 => isr.lisr.read().tcif1().bit_is_set(), @@ -535,7 +536,7 @@ where } } - pub fn is_half_transfer(&self, isr: &StreamIsr) -> bool { + pub fn half_transfer_flag(&self, isr: &StreamIsr) -> bool { match self.id() { 0 => isr.lisr.read().htif0().bit_is_set(), 1 => isr.lisr.read().htif1().bit_is_set(), @@ -549,7 +550,7 @@ where } } - pub fn is_transfer_error(&self, isr: &StreamIsr) -> bool { + pub fn transfer_error_flag(&self, isr: &StreamIsr) -> bool { match self.id() { 0 => isr.lisr.read().teif0().bit_is_set(), 1 => isr.lisr.read().teif1().bit_is_set(), @@ -563,7 +564,7 @@ where } } - pub fn is_direct_mode_error(&self, isr: &StreamIsr) -> bool { + pub fn direct_mode_error_flag(&self, isr: &StreamIsr) -> bool { match self.id() { 0 => isr.lisr.read().dmeif0().bit_is_set(), 1 => isr.lisr.read().dmeif1().bit_is_set(), @@ -577,7 +578,7 @@ where } } - pub fn is_fifo_error(&self, isr: &StreamIsr) -> bool { + pub fn fifo_error_flag(&self, isr: &StreamIsr) -> bool { match self.id() { 0 => isr.lisr.read().feif0().bit_is_set(), 1 => isr.lisr.read().feif1().bit_is_set(), @@ -792,6 +793,7 @@ where SyncED: SyncEDTrait, EgED: EgEDTrait, { + /// This field *must not* be mutated by shared references rb: &'static mut CCR, req_id: ReqId, _phantom_data: PhantomData<(CXX, SyncED, EgED)>, diff --git a/src/dma/mux.rs b/src/dma/mux.rs index fafa1404..c15f3c46 100644 --- a/src/dma/mux.rs +++ b/src/dma/mux.rs @@ -2,8 +2,8 @@ pub mod request_gen; pub mod shared; use self::request_gen::{ - Disabled as GenDisabled, Enabled as GenEnabled, GNbReq, GPol, GenId, - OverrunInterrupt as GenOverrunInterrupt, SigId, ED as GenED, + Disabled as GenDisabled, Enabled as GenEnabled, GNbReq, GPol, GenId, SigId, + TriggerOverrunError, TriggerOverrunInterrupt, ED as GenED, }; use self::shared::{MuxIsr, RequestGenIsr}; use super::stm32::dmamux1::RGCR; @@ -286,13 +286,13 @@ where } } - pub fn overrun_interrupt(&self) -> GenOverrunInterrupt { + pub fn overrun_interrupt(&self) -> TriggerOverrunInterrupt { self.rb.read().oie().bit().into() } - pub fn set_overrun_interrupt( + pub fn set_trigger_overrun_interrupt( &mut self, - overrun_intrpt: GenOverrunInterrupt, + overrun_intrpt: TriggerOverrunInterrupt, ) { self.rb.modify(|_, w| w.oie().bit(overrun_intrpt.into())); } @@ -309,9 +309,9 @@ where self.rb.read().gnbreq().bits().try_into().unwrap() } - fn transmute(self) -> RequestGenerator + fn transmute(self) -> RequestGenerator where - NewGenED: GenED, + NewED: GenED, { RequestGenerator { rb: self.rb, @@ -345,3 +345,47 @@ where self.transmute() } } + +impl RequestGenerator +where + GXX: GenId, + ED: GenED, +{ + pub fn check_isr( + &self, + isr: &RequestGenIsr, + ) -> Result<(), TriggerOverrunError> { + if self.trigger_overrun_flag(isr) { + Err(TriggerOverrunError) + } else { + Ok(()) + } + } + pub fn trigger_overrun_flag(&self, isr: &RequestGenIsr) -> bool { + match self.id() { + 0 => isr.rgsr.read().of0().bit_is_set(), + 1 => isr.rgsr.read().of1().bit_is_set(), + 2 => isr.rgsr.read().of2().bit_is_set(), + 3 => isr.rgsr.read().of3().bit_is_set(), + 4 => isr.rgsr.read().of4().bit_is_set(), + 5 => isr.rgsr.read().of5().bit_is_set(), + 6 => isr.rgsr.read().of6().bit_is_set(), + 7 => isr.rgsr.read().of7().bit_is_set(), + _ => unreachable!(), + } + } + + pub fn clear_isr(&self, isr: &mut RequestGenIsr) { + match self.id() { + 0 => isr.rgcfr.write(|w| w.cof0().set_bit()), + 1 => isr.rgcfr.write(|w| w.cof1().set_bit()), + 2 => isr.rgcfr.write(|w| w.cof2().set_bit()), + 3 => isr.rgcfr.write(|w| w.cof3().set_bit()), + 4 => isr.rgcfr.write(|w| w.cof4().set_bit()), + 5 => isr.rgcfr.write(|w| w.cof5().set_bit()), + 6 => isr.rgcfr.write(|w| w.cof6().set_bit()), + 7 => isr.rgcfr.write(|w| w.cof7().set_bit()), + _ => unreachable!(), + } + } +} diff --git a/src/dma/mux/request_gen.rs b/src/dma/mux/request_gen.rs index 13e37c4d..1988b7e0 100644 --- a/src/dma/mux/request_gen.rs +++ b/src/dma/mux/request_gen.rs @@ -48,7 +48,7 @@ int_enum! { } bool_enum! { - OverrunInterrupt, "Overrun Interrupt", Disabled, Enabled + TriggerOverrunInterrupt, "Overrun Interrupt", Disabled, Enabled } int_enum! { @@ -63,3 +63,6 @@ int_enum! { int_struct! { GNbReq, u8, 5, "Number of DMA Requests to be generated (minus 1)" } + +#[derive(Debug, Clone, Copy)] +pub struct TriggerOverrunError; diff --git a/src/dma/mux/shared.rs b/src/dma/mux/shared.rs index d8f6e6eb..3cfcc908 100644 --- a/src/dma/mux/shared.rs +++ b/src/dma/mux/shared.rs @@ -1,15 +1,17 @@ -use super::super::stm32::dmamux1::{CFR, CSR, RGSR, RGCFR}; +use super::super::stm32::dmamux1::{CFR, CSR, RGCFR, RGSR}; pub struct MuxIsr { + /// This field *must not* be mutated through shared references pub(in super::super) csr: &'static mut CSR, + /// This field *must not* be mutated through shared references pub(in super::super) cfr: &'static mut CFR, } unsafe impl Sync for MuxIsr {} pub struct RequestGenIsr { - pub(in super::super) rgsr: &'static mut RGSR, - pub(in super::super) rgcfr: &'static mut RGCFR, + pub(super) rgsr: &'static mut RGSR, + pub(super) rgcfr: &'static mut RGCFR, } unsafe impl Sync for RequestGenIsr {} From 82ca7b793126beb5d631eb5ed815d5b4444848fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ad=C3=A4?= Date: Sun, 15 Dec 2019 15:15:48 +0100 Subject: [PATCH 014/103] Bit of reworkk --- src/dma.rs | 1 - src/dma/channel.rs | 8 +++----- src/dma/macros.rs | 3 +-- src/dma/mux/request_gen.rs | 8 +++----- src/dma/utils.rs | 4 ---- 5 files changed, 7 insertions(+), 17 deletions(-) delete mode 100644 src/dma/utils.rs diff --git a/src/dma.rs b/src/dma.rs index 4cf273fe..c5997576 100644 --- a/src/dma.rs +++ b/src/dma.rs @@ -5,7 +5,6 @@ mod macros; pub mod channel; pub mod mux; pub mod stream; -mod utils; use self::channel::ChannelId; use self::mux::request_ids::{ diff --git a/src/dma/channel.rs b/src/dma/channel.rs index d3463bb2..f8887064 100644 --- a/src/dma/channel.rs +++ b/src/dma/channel.rs @@ -1,6 +1,6 @@ -use super::utils::PhantomType; +use core::fmt::Debug; -pub unsafe trait ChannelId: PhantomType { +pub unsafe trait ChannelId: Debug { const STREAM_ID: usize; const MUX_ID: usize; } @@ -8,11 +8,9 @@ pub unsafe trait ChannelId: PhantomType { macro_rules! channels { ($($channel:ident => [$stream:tt, $mux:tt]),*) => { $( - #[derive(Debug, PartialEq, Eq, Clone, Copy)] + #[derive(Debug)] pub struct $channel; - impl PhantomType for $channel {} - unsafe impl ChannelId for $channel { const STREAM_ID: usize = $stream; const MUX_ID: usize = $mux; diff --git a/src/dma/macros.rs b/src/dma/macros.rs index e1e398f9..81a19ebc 100644 --- a/src/dma/macros.rs +++ b/src/dma/macros.rs @@ -1,12 +1,11 @@ macro_rules! type_state { ($trait:ident, $($type_state:ident),*) => { - pub unsafe trait $trait: crate::dma::utils::PhantomType {} + pub unsafe trait $trait: core::fmt::Debug + PartialEq + Eq + Clone + Copy {} $( #[derive(Debug, PartialEq, Eq, Clone, Copy)] pub struct $type_state; - impl crate::dma::utils::PhantomType for $type_state {} unsafe impl $trait for $type_state {} )* }; diff --git a/src/dma/mux/request_gen.rs b/src/dma/mux/request_gen.rs index 1988b7e0..50581481 100644 --- a/src/dma/mux/request_gen.rs +++ b/src/dma/mux/request_gen.rs @@ -1,21 +1,19 @@ -use super::super::utils::PhantomType; +use core::fmt::Debug; type_state! { ED, Disabled, Enabled } -pub unsafe trait GenId: PhantomType { +pub unsafe trait GenId: Debug { const ID: usize; } macro_rules! gen_ids { ($($name:ident => $id:tt),*) => { $( - #[derive(Debug, PartialEq, Eq, Clone, Copy)] + #[derive(Debug)] pub struct $name; - impl PhantomType for $name {} - unsafe impl GenId for $name { const ID:usize = $id; } diff --git a/src/dma/utils.rs b/src/dma/utils.rs deleted file mode 100644 index ba70c605..00000000 --- a/src/dma/utils.rs +++ /dev/null @@ -1,4 +0,0 @@ -use core::fmt::Debug; - -/// Used to enable usage of derive macros for structs using Self as Phantom Type. -pub trait PhantomType: Debug + PartialEq + Eq + Clone + Copy {} From fb3c958fca2c6f15d1d69d6ed00658b5ea6bf653 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ad=C3=A4?= Date: Sun, 15 Dec 2019 16:53:44 +0100 Subject: [PATCH 015/103] Implemented default values for config types --- src/dma.rs | 3 ++ src/dma/macros.rs | 72 ++++++++++++++++++++++++++++++++++---- src/dma/mux.rs | 10 +++--- src/dma/mux/request_gen.rs | 8 ++--- src/dma/stream.rs | 48 ++++++++++++------------- 5 files changed, 102 insertions(+), 39 deletions(-) diff --git a/src/dma.rs b/src/dma.rs index c5997576..8f43ab0a 100644 --- a/src/dma.rs +++ b/src/dma.rs @@ -46,6 +46,7 @@ where { /// This field *must not* be mutated by shared references rb: &'static mut ST, + ndt: Ndt, _phantom_data: PhantomData<(CXX, DMA, ED, IsrState)>, } @@ -57,6 +58,7 @@ where fn new(rb: &'static mut ST) -> Self { Stream { rb, + ndt: Ndt::default(), _phantom_data: PhantomData, } } @@ -194,6 +196,7 @@ where { Stream { rb: self.rb, + ndt: self.ndt, _phantom_data: PhantomData, } } diff --git a/src/dma/macros.rs b/src/dma/macros.rs index 81a19ebc..ca7c1f4f 100644 --- a/src/dma/macros.rs +++ b/src/dma/macros.rs @@ -11,8 +11,11 @@ macro_rules! type_state { }; } +/// Macro for generating enums that map one-to-one to bool values. +/// +/// To set the default variant, write `(D)` after it. macro_rules! bool_enum { - ($name:ident, $doc:tt, $v_false:ident, $v_true:ident) => { + ($name:ident, $doc:tt, $v_false:ident $((D $($_syntax_false:ident)?))?, $v_true:ident $((D $($_syntax_true:ident)?))?) => { #[doc=$doc] #[derive(Debug, PartialEq, Eq, Clone, Copy)] pub enum $name { @@ -35,11 +38,38 @@ macro_rules! bool_enum { } } } + + $( + impl Default for $name { + fn default() -> Self { + $name::$v_false + } + } + // Needed because otherwise the macro would lack a syntax variable being matched to + $( + type $_syntax_false = __INVALID__; + )? + )? + + $( + impl Default for $name { + fn default() -> Self { + $name::$v_true + } + } + // Needed because otherwise the macro would lack a syntax variable being matched to + $( + type $_syntax_true = __INVALID__; + )? + )? }; } +/// Macro for generating enums that map one-to-one to int values of type `$ty`. +/// +/// To set the default variant, write `(D)` after it. macro_rules! int_enum { - ($name:ident <=> $ty:ty, $doc:tt, $($variant:ident <=> $num:tt),*) => { + ($name:ident <=> $ty:ty, $doc:tt, $($variant:ident <=> $num:tt $((D $($_syntax:ident)?))?),*) => { #[doc=$doc] #[derive(Debug, PartialEq, Eq, Clone, Copy)] pub enum $name { @@ -70,6 +100,20 @@ macro_rules! int_enum { } } } + + $( + $( + impl Default for $name { + fn default() -> Self { + $name::$variant + } + } + // Needed because otherwise the macro would lack a syntax variable being matched to + $( + type $_syntax = __INVALID__; + )? + )? + )* }; } @@ -78,10 +122,10 @@ macro_rules! int_enum { /// Attention: If you don't want to limit the length of the stored value, /// set `$len = 0`. macro_rules! int_struct { - ($name:ident, $int_type:ident, $len:tt, $doc:tt) => { - int_struct! { @INNER $name, $doc, $int_type, $len } + ($name:ident, $int_type:ident, $len:tt, $doc:tt $(, $default:tt)?) => { + int_struct! { @INNER $name, $doc, $int_type, $len $(, $default)? } }; - (@INNER $name:ident, $doc:tt, $int_type:ident, 0) => { + (@INNER $name:ident, $doc:tt, $int_type:ident, 0 $(, $default:tt)?) => { #[doc=$doc] #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub struct $name(pub $int_type); @@ -111,8 +155,16 @@ macro_rules! int_struct { val.value() } } + + $( + impl Default for $name { + fn default() -> $name { + $name($default) + } + } + )? }; - (@INNER $name:ident, $doc:tt, $int_type:ident, $len:tt) => { + (@INNER $name:ident, $doc:tt, $int_type:ident, $len:tt $(, $default:tt)?) => { #[doc=$doc] #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub struct $name($int_type); @@ -162,5 +214,13 @@ macro_rules! int_struct { } } } + + $( + impl Default for $name { + fn default() -> $name { + $name($default) + } + } + )? }; } diff --git a/src/dma/mux.rs b/src/dma/mux.rs index c15f3c46..b0f552ae 100644 --- a/src/dma/mux.rs +++ b/src/dma/mux.rs @@ -19,26 +19,26 @@ type_state! { } bool_enum! { - SyncOverrunInterrupt, "Synchronization overrun interrupt", Disabled, Enabled + SyncOverrunInterrupt, "Synchronization overrun interrupt", Disabled (D), Enabled } int_enum! { SyncPolarity <=> u8, "Synchronization Polarity", - NoEvent <=> 0b00, + NoEvent <=> 0b00 (D), RisingEdge <=> 0b01, FallingEdge <=> 0b10, RisingFallingEdge <=> 0b11 } int_struct! { - NbReq, u8, 5, "Number of Requests" + NbReq, u8, 5, "Number of Requests", 0 } int_enum! { SyncId <=> u8, "Synchronization Identification", - DmaMux1Evt0 <=> 0b000, + DmaMux1Evt0 <=> 0b000 (D), DmaMux1Evt1 <=> 0b001, DmaMux1Evt2 <=> 0b010, Lptim1Out <=> 0b011, @@ -75,7 +75,7 @@ macro_rules! request_id { int_enum! { RequestId <=> u8, "Request Id", - None <=> 0, + None <=> 0 (D), $( $request_id <=> $id ),* diff --git a/src/dma/mux/request_gen.rs b/src/dma/mux/request_gen.rs index 50581481..e9894b58 100644 --- a/src/dma/mux/request_gen.rs +++ b/src/dma/mux/request_gen.rs @@ -35,7 +35,7 @@ gen_ids! { int_enum! { SigId <=> u8, "Signal Identification", - DmaMux1Evt0 <=> 0b000, + DmaMux1Evt0 <=> 0b000 (D), DmaMux1Evt1 <=> 0b001, DmaMux1Evt2 <=> 0b010, Lptim1Out <=> 0b011, @@ -46,20 +46,20 @@ int_enum! { } bool_enum! { - TriggerOverrunInterrupt, "Overrun Interrupt", Disabled, Enabled + TriggerOverrunInterrupt, "Overrun Interrupt", Disabled (D), Enabled } int_enum! { GPol <=> u8, "Request Generator Trigger Polarity", - NoEvent <=> 0b00, + NoEvent <=> 0b00 (D), RisingEdge <=> 0b01, FallingEdge <=> 0b10, RisingFallingEdge <=> 0b11 } int_struct! { - GNbReq, u8, 5, "Number of DMA Requests to be generated (minus 1)" + GNbReq, u8, 5, "Number of DMA Requests to be generated (minus 1)", 0 } #[derive(Debug, Clone, Copy)] diff --git a/src/dma/stream.rs b/src/dma/stream.rs index f7fd5f49..fa0659be 100644 --- a/src/dma/stream.rs +++ b/src/dma/stream.rs @@ -19,53 +19,53 @@ pub trait IntoNum { } bool_enum! { - TransferCompleteInterrupt, "Transfer Complete Interrupt", Disabled, Enabled + TransferCompleteInterrupt, "Transfer Complete Interrupt", Disabled (D), Enabled } bool_enum! { - HalfTransferInterrupt, "Half Transfer Interrupt", Disabled, Enabled + HalfTransferInterrupt, "Half Transfer Interrupt", Disabled (D), Enabled } bool_enum! { - TransferErrorInterrupt, "Transfer Error Interrupt", Disabled, Enabled + TransferErrorInterrupt, "Transfer Error Interrupt", Disabled (D), Enabled } bool_enum! { - DirectModeErrorInterrupt, "Direct Mode Error Interrupt", Disabled, Enabled + DirectModeErrorInterrupt, "Direct Mode Error Interrupt", Disabled (D), Enabled } bool_enum! { - FifoErrorInterrupt, "Fifo Error Interrupt", Disabled, Enabled + FifoErrorInterrupt, "Fifo Error Interrupt", Disabled (D), Enabled } bool_enum! { - FlowController, "Flow Controller", Dma, Peripheral + FlowController, "Flow Controller", Dma (D), Peripheral } int_enum! { TransferDirection <=> u8, "Transfer Direction", - P2M <=> 0b00, + P2M <=> 0b00 (D), M2P <=> 0b01, M2M <=> 0b10 } bool_enum! { - CircularMode, "Circular Mode", Disabled, Enabled + CircularMode, "Circular Mode", Disabled (D), Enabled } bool_enum! { - Pinc, "Peripheral Increment Mode", Fixed, Incremented + Pinc, "Peripheral Increment Mode", Fixed (D), Incremented } bool_enum! { - Minc, "Memory Increment Mode", Fixed, Incremented + Minc, "Memory Increment Mode", Fixed (D), Incremented } int_enum! { PSize <=> u8, "Peripheral Data Size", - Byte <=> 0b00, + Byte <=> 0b00 (D), HalfWord <=> 0b01, Word <=> 0b10 } @@ -83,7 +83,7 @@ impl IntoNum for PSize { int_enum! { MSize <=> u8, "Memory Data Size", - Byte <=> 0b00, + Byte <=> 0b00 (D), HalfWord <=> 0b01, Word <=> 0b10 } @@ -99,30 +99,30 @@ impl IntoNum for MSize { } bool_enum! { - Pincos, "Peripheral Increment Offset Size", PSize, Word + Pincos, "Peripheral Increment Offset Size", PSize (D), Word } int_enum! { PriorityLevel <=> u8, "Priority Level", - Low <=> 0b00, + Low <=> 0b00 (D), Medium <=> 0b01, High <=> 0b10, VeryHigh <=> 0b11 } bool_enum! { - BufferMode, "Buffer Mode", Regular, DoubleBuffer + BufferMode, "Buffer Mode", Regular (D), DoubleBuffer } bool_enum! { - CurrentTarget, "CurrentTarget", M0a, M1a + CurrentTarget, "CurrentTarget", M0a (D), M1a } int_enum! { PBurst <=> u8, "Peripheral Burst", - Single <=> 0b00, + Single <=> 0b00 (D), Incr4 <=> 0b01, Incr8 <=> 0b10, Incr16 <=> 0b11 @@ -142,7 +142,7 @@ impl IntoNum for PBurst { int_enum! { MBurst <=> u8, "Memory Burst", - Single <=> 0b00, + Single <=> 0b00 (D), Incr4 <=> 0b01, Incr8 <=> 0b10, Incr16 <=> 0b11 @@ -160,29 +160,29 @@ impl IntoNum for MBurst { } int_struct! { - Ndt, u16, 0, "Number of Data Items to transfer" + Ndt, u16, 0, "Number of Data Items to transfer", 0 } int_struct! { - Pa, u32, 0, "Peripheral Address" + Pa, u32, 0, "Peripheral Address", 0 } int_struct! { - M0a, u32, 0, "Memory 0 Address" + M0a, u32, 0, "Memory 0 Address", 0 } int_struct! { - M1a, u32, 0, "Memory 1 Address" + M1a, u32, 0, "Memory 1 Address", 0 } bool_enum! { - TransferMode, "Transfer Mode", Direct, Fifo + TransferMode, "Transfer Mode", Direct (D), Fifo } int_enum! { FifoThreshold <=> u8, "Fifo Threshold", - F1_4 <=> 0b00, + F1_4 <=> 0b00 (D), F1_2 <=> 0b01, F3_4 <=> 0b10, Full <=> 0b11 From fb178afc620f8b9b36885ebbb09174760f1aab4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ad=C3=A4?= Date: Sun, 15 Dec 2019 17:28:37 +0100 Subject: [PATCH 016/103] Implemented dma stream config check for ndt register --- src/dma.rs | 39 +++++++++++++++++++++++++++++---------- 1 file changed, 29 insertions(+), 10 deletions(-) diff --git a/src/dma.rs b/src/dma.rs index 8f43ab0a..464b5e69 100644 --- a/src/dma.rs +++ b/src/dma.rs @@ -46,7 +46,7 @@ where { /// This field *must not* be mutated by shared references rb: &'static mut ST, - ndt: Ndt, + config_ndt: Ndt, _phantom_data: PhantomData<(CXX, DMA, ED, IsrState)>, } @@ -58,7 +58,7 @@ where fn new(rb: &'static mut ST) -> Self { Stream { rb, - ndt: Ndt::default(), + config_ndt: Ndt::default(), _phantom_data: PhantomData, } } @@ -155,6 +155,10 @@ where self.rb.ndtr.read().ndt().bits().into() } + pub fn configured_ndt(&self) -> Ndt { + self.config_ndt + } + pub fn pa(&self) -> Pa { self.rb.par.read().pa().bits().into() } @@ -196,7 +200,7 @@ where { Stream { rb: self.rb, - ndt: self.ndt, + config_ndt: self.config_ndt, _phantom_data: PhantomData, } } @@ -275,6 +279,8 @@ where } pub fn set_ndt(&mut self, ndt: Ndt) { + self.config_ndt = ndt; + unsafe { self.rb.ndtr.modify(|_, w| w.ndt().bits(ndt.into())); } @@ -377,18 +383,21 @@ where if self.circular_mode() == CircularMode::Enabled { self.check_config_circular(); } + if self.transfer_mode() == TransferMode::Fifo { self.check_config_fifo(); } + + self.check_ndt(); } fn check_config_circular(&self) { if self.transfer_mode() == TransferMode::Fifo { - let ndt = self.ndt().value(); - let m_burst = self.m_burst().into_num() as u16; - let p_burst = self.p_burst().into_num() as u16; - let m_size = self.m_size().into_num() as u16; - let p_size = self.p_size().into_num() as u16; + let ndt = self.ndt().value() as usize; + let m_burst = self.m_burst().into_num(); + let p_burst = self.p_burst().into_num(); + let m_size = self.m_size().into_num(); + let p_size = self.p_size().into_num(); if self.m_burst() != MBurst::Single && ndt % (m_burst * m_size / p_size) != 0 @@ -406,8 +415,8 @@ where ); } } else { - let ndt = self.ndt().value(); - let p_size = self.p_size().into_num() as u16; + let ndt = self.ndt().value() as usize; + let p_size = self.p_size().into_num(); if ndt % p_size != 0 { panic!( @@ -459,6 +468,16 @@ where ); } } + + fn check_ndt(&self) { + let m_size = self.m_size().into_num(); + let p_size = self.p_size().into_num(); + let ndt = self.config_ndt.value() as usize; + + if m_size > p_size && ndt % (m_size / p_size) != 0 { + panic!("`NDT` must be a multiple of (`m_size / p_size`)."); + } + } } impl Stream From 0696ebec5a267917ff74110b56f29cc3ec20b385 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ad=C3=A4?= Date: Sun, 15 Dec 2019 17:57:35 +0100 Subject: [PATCH 017/103] Added DMA channel struct as a wrapper for the stream and it's mux channel --- src/dma.rs | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/src/dma.rs b/src/dma.rs index 464b5e69..5cce1469 100644 --- a/src/dma.rs +++ b/src/dma.rs @@ -37,6 +37,71 @@ pub unsafe trait DMATrait {} unsafe impl DMATrait for DMA1 {} unsafe impl DMATrait for DMA2 {} +pub struct Channel +where + CXX: ChannelId, + DMA: DMATrait, + StreamED: EDTrait, + IsrState: IsrStateTrait, + ReqId: RequestIdTrait, + SyncED: SyncEDTrait, + EgED: EgEDTrait, +{ + pub stream: Stream, + pub mux: DmaMux, +} + +impl + Channel +where + CXX: ChannelId, + DMA: DMATrait, + StreamED: EDTrait, + IsrState: IsrStateTrait, + ReqId: RequestIdTrait, + SyncED: SyncEDTrait, + EgED: EgEDTrait, +{ + pub fn stream_owned( + self, + op: F, + ) -> Channel + where + F: FnOnce( + Stream, + ) -> Stream, + NewStreamED: EDTrait, + NewIsrState: IsrStateTrait, + { + let new_stream = op(self.stream); + + Channel { + stream: new_stream, + mux: self.mux, + } + } + + pub fn mux_owned( + self, + op: F, + ) -> Channel + where + F: FnOnce( + DmaMux, + ) -> DmaMux, + NewReqId: RequestIdTrait, + NewSyncED: SyncEDTrait, + NewEgED: EgEDTrait, + { + let new_mux = op(self.mux); + + Channel { + stream: self.stream, + mux: new_mux, + } + } +} + pub struct Stream where CXX: ChannelId, From c269d652ea795b27025bc375ee5e6e48a6306d04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ad=C3=A4?= Date: Sun, 15 Dec 2019 18:07:52 +0100 Subject: [PATCH 018/103] minor changes --- src/dma.rs | 4 ++-- src/dma/mux.rs | 5 +++-- src/dma/mux/shared.rs | 8 ++++---- src/dma/stream.rs | 6 ++++-- 4 files changed, 13 insertions(+), 10 deletions(-) diff --git a/src/dma.rs b/src/dma.rs index 5cce1469..1914196e 100644 --- a/src/dma.rs +++ b/src/dma.rs @@ -109,7 +109,7 @@ where ED: EDTrait, IsrState: IsrStateTrait, { - /// This field *must not* be mutated by shared references + /// This field *must not* be mutated using shared references rb: &'static mut ST, config_ndt: Ndt, _phantom_data: PhantomData<(CXX, DMA, ED, IsrState)>, @@ -879,7 +879,7 @@ where SyncED: SyncEDTrait, EgED: EgEDTrait, { - /// This field *must not* be mutated by shared references + /// This field *must not* be mutated using shared references rb: &'static mut CCR, req_id: ReqId, _phantom_data: PhantomData<(CXX, SyncED, EgED)>, diff --git a/src/dma/mux.rs b/src/dma/mux.rs index b0f552ae..7bad0451 100644 --- a/src/dma/mux.rs +++ b/src/dma/mux.rs @@ -251,7 +251,8 @@ where GXX: GenId, ED: GenED, { - rb: &'static RGCR, + /// This field *must not* be mutated using shared references + rb: &'static mut RGCR, _phantom_data: PhantomData<(GXX, ED)>, } @@ -259,7 +260,7 @@ impl RequestGenerator where GXX: GenId, { - pub(super) fn after_reset(rb: &'static RGCR) -> Self { + pub(super) fn after_reset(rb: &'static mut RGCR) -> Self { RequestGenerator { rb, _phantom_data: PhantomData, diff --git a/src/dma/mux/shared.rs b/src/dma/mux/shared.rs index 3cfcc908..791012b5 100644 --- a/src/dma/mux/shared.rs +++ b/src/dma/mux/shared.rs @@ -1,16 +1,16 @@ use super::super::stm32::dmamux1::{CFR, CSR, RGCFR, RGSR}; pub struct MuxIsr { - /// This field *must not* be mutated through shared references - pub(in super::super) csr: &'static mut CSR, - /// This field *must not* be mutated through shared references + pub(in super::super) csr: &'static CSR, + /// This field *must not* be mutated using shared references pub(in super::super) cfr: &'static mut CFR, } unsafe impl Sync for MuxIsr {} pub struct RequestGenIsr { - pub(super) rgsr: &'static mut RGSR, + pub(super) rgsr: &'static RGSR, + /// This field *must not* be mutated using shared references pub(super) rgcfr: &'static mut RGCFR, } diff --git a/src/dma/stream.rs b/src/dma/stream.rs index fa0659be..7654d0ae 100644 --- a/src/dma/stream.rs +++ b/src/dma/stream.rs @@ -204,9 +204,11 @@ pub struct StreamIsr where DMA: DMATrait, { - pub(super) lisr: &'static mut LISR, - pub(super) hisr: &'static mut HISR, + pub(super) lisr: &'static LISR, + pub(super) hisr: &'static HISR, + /// This field *must not* be mutated using shared references pub(super) lifcr: &'static mut LIFCR, + /// This field *must not* be mutated using shared references pub(super) hifcr: &'static mut HIFCR, _phantom_data: PhantomData, } From 84181e94d397a96f1f48f638f236d0d8cea8b240 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ad=C3=A4?= Date: Mon, 16 Dec 2019 00:17:29 +0100 Subject: [PATCH 019/103] Started implementation of DMA safe transfer --- src/dma.rs | 3 + src/dma/safe_transfer.rs | 394 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 397 insertions(+) create mode 100644 src/dma/safe_transfer.rs diff --git a/src/dma.rs b/src/dma.rs index 1914196e..e253fe8f 100644 --- a/src/dma.rs +++ b/src/dma.rs @@ -4,6 +4,7 @@ mod macros; pub mod channel; pub mod mux; +pub mod safe_transfer; pub mod stream; use self::channel::ChannelId; @@ -1143,3 +1144,5 @@ where EgED: EgEDTrait, { } + +pub struct SafeTransfer {} diff --git a/src/dma/safe_transfer.rs b/src/dma/safe_transfer.rs new file mode 100644 index 00000000..d17c8d10 --- /dev/null +++ b/src/dma/safe_transfer.rs @@ -0,0 +1,394 @@ +use super::stream::{MSize, PSize}; +use core::convert::TryInto; +use core::fmt::Debug; +use core::mem; +use core::ops::{Deref, DerefMut}; + +/// # Safety +/// +/// * `Self` must be valid for any bit representation +pub unsafe trait BufferType: + Sized + Clone + Copy + Sync + 'static +{ +} + +// Maps BufferTypeSize to number of bytes +int_enum! { + BufferTypeSize <=> usize, + "Buffer Size", + Byte <=> 1, + HalfWord <=> 2, + Word <=> 4 +} + +impl From for MSize { + fn from(val: BufferTypeSize) -> Self { + match val { + BufferTypeSize::Byte => MSize::Byte, + BufferTypeSize::HalfWord => MSize::HalfWord, + BufferTypeSize::Word => MSize::Word, + } + } +} + +impl From for BufferTypeSize { + fn from(val: MSize) -> Self { + match val { + MSize::Byte => BufferTypeSize::Byte, + MSize::HalfWord => BufferTypeSize::HalfWord, + MSize::Word => BufferTypeSize::Word, + } + } +} + +impl From for PSize { + fn from(val: BufferTypeSize) -> Self { + match val { + BufferTypeSize::Byte => PSize::Byte, + BufferTypeSize::HalfWord => PSize::HalfWord, + BufferTypeSize::Word => PSize::Word, + } + } +} + +impl From for BufferTypeSize { + fn from(val: PSize) -> Self { + match val { + PSize::Byte => BufferTypeSize::Byte, + PSize::HalfWord => BufferTypeSize::HalfWord, + PSize::Word => BufferTypeSize::Word, + } + } +} + +impl BufferTypeSize { + pub fn from_buffer_type() -> Self + where + BUF: BufferType, + { + let size_bytes = mem::size_of::(); + + size_bytes.try_into().unwrap_or_else(|_| { + panic!("The Size of the Buffer type must be either 1, 2 or 4 bytes") + }) + } +} + +unsafe impl BufferType for u8 {} + +unsafe impl BufferType for i8 {} + +unsafe impl BufferType for u16 {} + +unsafe impl BufferType for i16 {} + +unsafe impl BufferType for u32 {} + +unsafe impl BufferType for i32 {} + +unsafe impl BufferType for f32 {} + +pub enum ImmutableBuffer<'buf, BUF> +where + BUF: BufferType, +{ + Peripheral(PeripheralBuffer<'buf, BUF>), + Memory(MemoryBuffer), +} + +impl<'buf, BUF> ImmutableBuffer<'buf, BUF> +where + BUF: BufferType, +{ + pub fn peripheral(self) -> PeripheralBuffer<'buf, BUF> { + if let ImmutableBuffer::Peripheral(buffer) = self { + buffer + } else { + panic!("The buffer is a memory buffer."); + } + } + + pub fn memory(self) -> MemoryBuffer { + if let ImmutableBuffer::Memory(buffer) = self { + buffer + } else { + panic!("The buffer is a peripheral buffer."); + } + } +} + +pub enum MutableBuffer<'buf, BUF> +where + BUF: BufferType, +{ + Peripheral(PeripheralBufferMut<'buf, BUF>), + Memory(MemoryBufferMut), +} + +impl<'buf, BUF> MutableBuffer<'buf, BUF> +where + BUF: BufferType, +{ + pub fn peripheral(self) -> PeripheralBufferMut<'buf, BUF> { + if let MutableBuffer::Peripheral(buffer) = self { + buffer + } else { + panic!("The buffer is a memory buffer."); + } + } + + pub fn memory(self) -> MemoryBufferMut { + if let MutableBuffer::Memory(buffer) = self { + buffer + } else { + panic!("The buffer is a peripheral buffer."); + } + } + + pub fn as_immutable(&self) -> ImmutableBuffer { + match self { + MutableBuffer::Memory(buffer) => { + ImmutableBuffer::Memory(buffer.as_immutable()) + } + MutableBuffer::Peripheral(buffer) => { + ImmutableBuffer::Peripheral(buffer.as_immutable()) + } + } + } +} + +pub enum PeripheralBuffer<'buf, BUF> +where + BUF: BufferType, +{ + Fixed(&'static BUF), + Incremented(IncrementedBuffer<'buf, BUF>), +} + +impl<'buf, BUF> PeripheralBuffer<'buf, BUF> +where + BUF: BufferType, +{ + pub fn fixed(self) -> &'static BUF { + if let PeripheralBuffer::Fixed(buffer) = self { + buffer + } else { + panic!("The buffer is incremented."); + } + } + + pub fn incremented(self) -> IncrementedBuffer<'buf, BUF> { + if let PeripheralBuffer::Incremented(buffer) = self { + buffer + } else { + panic!("The buffer is fixed."); + } + } +} + +pub enum PeripheralBufferMut<'buf, BUF> +where + BUF: BufferType, +{ + Fixed(&'static mut BUF), + Incremented(IncrementedBufferMut<'buf, BUF>), +} + +impl<'buf, BUF> PeripheralBufferMut<'buf, BUF> +where + BUF: BufferType, +{ + pub fn as_immutable(&self) -> PeripheralBuffer { + match self { + PeripheralBufferMut::Fixed(buffer) => unsafe { + PeripheralBuffer::Fixed(&*(*buffer as *const _)) + }, + PeripheralBufferMut::Incremented(buffer) => { + PeripheralBuffer::Incremented(buffer.as_immutable()) + } + } + } +} + +pub enum MemoryBuffer +where + BUF: BufferType, +{ + Fixed(&'static BUF), + Incremented(&'static [BUF]), +} + +pub enum MemoryBufferMut +where + BUF: BufferType, +{ + Fixed(&'static mut BUF), + Incremented(&'static mut [BUF]), +} + +impl MemoryBufferMut +where + BUF: BufferType, +{ + pub fn as_immutable(&self) -> MemoryBuffer { + match self { + MemoryBufferMut::Fixed(buffer) => unsafe { + MemoryBuffer::Fixed(&*(*buffer as *const _)) + }, + MemoryBufferMut::Incremented(buffer) => unsafe { + MemoryBuffer::Incremented(&*(*buffer as *const _)) + }, + } + } +} + +pub enum IncrementedBuffer<'buf, BUF> +where + BUF: BufferType, +{ + RegularOffset(&'static [BUF]), + WordOffset(WordOffsetBuffer<'buf, BUF>), +} + +pub enum IncrementedBufferMut<'buf, BUF> +where + BUF: BufferType, +{ + RegularOffset(&'static mut [BUF]), + WordOffset(WordOffsetBufferMut<'buf, BUF>), +} + +impl<'buf, BUF> IncrementedBufferMut<'buf, BUF> +where + BUF: BufferType, +{ + pub fn as_immutable(&self) -> IncrementedBuffer { + match self { + IncrementedBufferMut::RegularOffset(buffer) => unsafe { + IncrementedBuffer::RegularOffset(&*(*buffer as *const _)) + }, + IncrementedBufferMut::WordOffset(buffer) => { + IncrementedBuffer::WordOffset(buffer.as_immutable()) + } + } + } +} + +pub struct FixedBuffer(pub &'static BUF) +where + BUF: BufferType; + +impl Deref for FixedBuffer +where + BUF: BufferType, +{ + type Target = BUF; + + fn deref(&self) -> &BUF { + &*self.0 + } +} + +pub struct FixedBufferMut(pub &'static mut BUF) +where + BUF: BufferType; + +impl Deref for FixedBufferMut +where + BUF: BufferType, +{ + type Target = BUF; + + fn deref(&self) -> &BUF { + &*self.0 + } +} + +impl DerefMut for FixedBufferMut +where + BUF: BufferType, +{ + fn deref_mut(&mut self) -> &mut BUF { + &mut *self.0 + } +} + +pub struct RegularOffsetBuffer(&'static [BUF]) +where + BUF: BufferType; + +impl Deref for RegularOffsetBuffer +where + BUF: BufferType, +{ + type Target = [BUF]; + + fn deref(&self) -> &[BUF] { + &*self.0 + } +} + +pub struct RegularOffsetBufferMut(&'static mut [BUF]) +where + BUF: BufferType; + +impl Deref for RegularOffsetBufferMut +where + BUF: BufferType, +{ + type Target = [BUF]; + + fn deref(&self) -> &[BUF] { + &*self.0 + } +} + +impl DerefMut for RegularOffsetBufferMut +where + BUF: BufferType, +{ + fn deref_mut(&mut self) -> &mut [BUF] { + &mut *self.0 + } +} + +pub struct WordOffsetBuffer<'buf, BUF>(&'buf [&'static BUF]) +where + BUF: BufferType; + +impl<'buf, BUF> Deref for WordOffsetBuffer<'buf, BUF> +where + BUF: BufferType, +{ + type Target = [&'static BUF]; + + fn deref(&self) -> &[&'static BUF] { + &*self.0 + } +} + +pub struct WordOffsetBufferMut<'buf, BUF>(&'buf [&'static mut BUF]) +where + BUF: BufferType; + +impl<'buf, BUF> WordOffsetBufferMut<'buf, BUF> +where + BUF: BufferType, +{ + pub fn as_immutable(&self) -> WordOffsetBuffer { + let buffer = unsafe { &*(self.0 as *const _ as *const _) }; + + WordOffsetBuffer(buffer) + } +} + +impl<'buf, BUF> Deref for WordOffsetBufferMut<'buf, BUF> +where + BUF: BufferType, +{ + type Target = [&'static mut BUF]; + + fn deref(&self) -> &[&'static mut BUF] { + &*self.0 + } +} From 998ef6ae0f619f1bc5c9b0e7cebf5da61c539c7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ad=C3=A4?= Date: Mon, 16 Dec 2019 17:56:20 +0100 Subject: [PATCH 020/103] Reimplemented all kinds of buffers --- Cargo.toml | 1 + src/dma/safe_transfer.rs | 318 ++++++++++++--------------------------- 2 files changed, 99 insertions(+), 220 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 766380f7..86eeee8e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,6 +26,7 @@ stm32h7 = "0.9.0" void = { version = "1.0.2", default-features = false } cast = { version = "0.2.2", default-features = false } nb = "0.1.2" +vcell = "0.1.2" [dependencies.bare-metal] version = "0.2.4" features = ["const-fn"] diff --git a/src/dma/safe_transfer.rs b/src/dma/safe_transfer.rs index d17c8d10..901d3281 100644 --- a/src/dma/safe_transfer.rs +++ b/src/dma/safe_transfer.rs @@ -1,8 +1,8 @@ use super::stream::{MSize, PSize}; use core::convert::TryInto; use core::fmt::Debug; -use core::mem; -use core::ops::{Deref, DerefMut}; +use core::{mem, ptr}; +use vcell::VolatileCell; /// # Safety /// @@ -88,307 +88,185 @@ unsafe impl BufferType for i32 {} unsafe impl BufferType for f32 {} -pub enum ImmutableBuffer<'buf, BUF> +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +pub struct FixedBuffer(*const BUF) where - BUF: BufferType, -{ - Peripheral(PeripheralBuffer<'buf, BUF>), - Memory(MemoryBuffer), -} + BUF: BufferType; -impl<'buf, BUF> ImmutableBuffer<'buf, BUF> +impl FixedBuffer where BUF: BufferType, { - pub fn peripheral(self) -> PeripheralBuffer<'buf, BUF> { - if let ImmutableBuffer::Peripheral(buffer) = self { - buffer - } else { - panic!("The buffer is a memory buffer."); - } + pub fn get(self) -> BUF { + unsafe { self.0.read_volatile() } } - pub fn memory(self) -> MemoryBuffer { - if let ImmutableBuffer::Memory(buffer) = self { - buffer - } else { - panic!("The buffer is a peripheral buffer."); - } + pub fn as_ptr(self) -> *const BUF { + self.0 } } -pub enum MutableBuffer<'buf, BUF> +unsafe impl Send for FixedBuffer where BUF: BufferType {} + +unsafe impl Sync for FixedBuffer where BUF: BufferType {} + +#[derive(Debug, PartialEq, Eq)] +pub struct FixedBufferMut(*mut BUF) where - BUF: BufferType, -{ - Peripheral(PeripheralBufferMut<'buf, BUF>), - Memory(MemoryBufferMut), -} + BUF: BufferType; -impl<'buf, BUF> MutableBuffer<'buf, BUF> +impl FixedBufferMut where BUF: BufferType, { - pub fn peripheral(self) -> PeripheralBufferMut<'buf, BUF> { - if let MutableBuffer::Peripheral(buffer) = self { - buffer - } else { - panic!("The buffer is a memory buffer."); - } + pub fn get(&self) -> BUF { + unsafe { ptr::read_volatile(self.0) } } - pub fn memory(self) -> MemoryBufferMut { - if let MutableBuffer::Memory(buffer) = self { - buffer - } else { - panic!("The buffer is a peripheral buffer."); + pub fn set(&mut self, buf: BUF) { + unsafe { + ptr::write_volatile(self.0, buf); } } - pub fn as_immutable(&self) -> ImmutableBuffer { - match self { - MutableBuffer::Memory(buffer) => { - ImmutableBuffer::Memory(buffer.as_immutable()) - } - MutableBuffer::Peripheral(buffer) => { - ImmutableBuffer::Peripheral(buffer.as_immutable()) - } - } + pub fn as_ptr(&self) -> *const BUF { + self.0 + } + + pub fn as_mut_ptr(&mut self) -> *mut BUF { + self.0 } } -pub enum PeripheralBuffer<'buf, BUF> +unsafe impl Send for FixedBufferMut where BUF: BufferType {} + +unsafe impl Sync for FixedBufferMut where BUF: BufferType {} + +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +pub struct RegularOffsetBuffer(*const [BUF]) where - BUF: BufferType, -{ - Fixed(&'static BUF), - Incremented(IncrementedBuffer<'buf, BUF>), -} + BUF: BufferType; -impl<'buf, BUF> PeripheralBuffer<'buf, BUF> +impl RegularOffsetBuffer where BUF: BufferType, { - pub fn fixed(self) -> &'static BUF { - if let PeripheralBuffer::Fixed(buffer) = self { - buffer - } else { - panic!("The buffer is incremented."); - } + pub fn get(self, index: usize) -> BUF { + unsafe { volatile_read_buffer_slice(self.0, index) } } - pub fn incremented(self) -> IncrementedBuffer<'buf, BUF> { - if let PeripheralBuffer::Incremented(buffer) = self { - buffer - } else { - panic!("The buffer is fixed."); + pub fn as_ptr(self, index: usize) -> *const BUF { + unsafe { + let slice = &*self.0; + &slice[index] as *const _ } } } -pub enum PeripheralBufferMut<'buf, BUF> -where - BUF: BufferType, -{ - Fixed(&'static mut BUF), - Incremented(IncrementedBufferMut<'buf, BUF>), -} +unsafe impl Send for RegularOffsetBuffer where BUF: BufferType {} -impl<'buf, BUF> PeripheralBufferMut<'buf, BUF> -where - BUF: BufferType, -{ - pub fn as_immutable(&self) -> PeripheralBuffer { - match self { - PeripheralBufferMut::Fixed(buffer) => unsafe { - PeripheralBuffer::Fixed(&*(*buffer as *const _)) - }, - PeripheralBufferMut::Incremented(buffer) => { - PeripheralBuffer::Incremented(buffer.as_immutable()) - } - } - } -} +unsafe impl Sync for RegularOffsetBuffer where BUF: BufferType {} -pub enum MemoryBuffer +#[derive(Debug, PartialEq, Eq)] +pub struct RegularOffsetBufferMut(*mut [BUF]) where - BUF: BufferType, -{ - Fixed(&'static BUF), - Incremented(&'static [BUF]), -} + BUF: BufferType; -pub enum MemoryBufferMut +impl RegularOffsetBufferMut where BUF: BufferType, { - Fixed(&'static mut BUF), - Incremented(&'static mut [BUF]), -} + pub fn get(&self, index: usize) -> BUF { + unsafe { volatile_read_buffer_slice(self.0, index) } + } -impl MemoryBufferMut -where - BUF: BufferType, -{ - pub fn as_immutable(&self) -> MemoryBuffer { - match self { - MemoryBufferMut::Fixed(buffer) => unsafe { - MemoryBuffer::Fixed(&*(*buffer as *const _)) - }, - MemoryBufferMut::Incremented(buffer) => unsafe { - MemoryBuffer::Incremented(&*(*buffer as *const _)) - }, + pub fn set(&mut self, index: usize, item: BUF) { + unsafe { + let slice = &mut *self.0; + ptr::write_volatile(&mut slice[index] as *mut _, item); } } -} - -pub enum IncrementedBuffer<'buf, BUF> -where - BUF: BufferType, -{ - RegularOffset(&'static [BUF]), - WordOffset(WordOffsetBuffer<'buf, BUF>), -} -pub enum IncrementedBufferMut<'buf, BUF> -where - BUF: BufferType, -{ - RegularOffset(&'static mut [BUF]), - WordOffset(WordOffsetBufferMut<'buf, BUF>), -} + pub fn as_ptr(&self, index: usize) -> *const BUF { + unsafe { + let slice = &*self.0; + &slice[index] as *const _ + } + } -impl<'buf, BUF> IncrementedBufferMut<'buf, BUF> -where - BUF: BufferType, -{ - pub fn as_immutable(&self) -> IncrementedBuffer { - match self { - IncrementedBufferMut::RegularOffset(buffer) => unsafe { - IncrementedBuffer::RegularOffset(&*(*buffer as *const _)) - }, - IncrementedBufferMut::WordOffset(buffer) => { - IncrementedBuffer::WordOffset(buffer.as_immutable()) - } + pub fn as_mut_ptr(&mut self, index: usize) -> *mut BUF { + unsafe { + let slice = &mut *self.0; + &mut slice[index] as *mut _ } } } -pub struct FixedBuffer(pub &'static BUF) -where - BUF: BufferType; +unsafe impl Send for RegularOffsetBufferMut where BUF: BufferType {} + +unsafe impl Sync for RegularOffsetBufferMut where BUF: BufferType {} -impl Deref for FixedBuffer +unsafe fn volatile_read_buffer_slice( + slice_ptr: *const [BUF], + index: usize, +) -> BUF where BUF: BufferType, { - type Target = BUF; - - fn deref(&self) -> &BUF { - &*self.0 - } + let slice = &*slice_ptr; + ptr::read_volatile(&slice[index] as *const _) } -pub struct FixedBufferMut(pub &'static mut BUF) +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +pub struct WordOffsetBuffer<'buf, BUF>(&'buf [*const BUF]) where BUF: BufferType; -impl Deref for FixedBufferMut +impl<'buf, BUF> WordOffsetBuffer<'buf, BUF> where BUF: BufferType, { - type Target = BUF; - - fn deref(&self) -> &BUF { - &*self.0 + pub fn get(self, index: usize) -> BUF { + unsafe { ptr::read_volatile(self.0[index]) } } -} -impl DerefMut for FixedBufferMut -where - BUF: BufferType, -{ - fn deref_mut(&mut self) -> &mut BUF { - &mut *self.0 + pub fn as_ptr(self, index: usize) -> *const BUF { + self.0[index] } } -pub struct RegularOffsetBuffer(&'static [BUF]) -where - BUF: BufferType; +unsafe impl<'buf, BUF> Send for WordOffsetBuffer<'buf, BUF> where BUF: BufferType +{} -impl Deref for RegularOffsetBuffer -where - BUF: BufferType, -{ - type Target = [BUF]; - - fn deref(&self) -> &[BUF] { - &*self.0 - } -} +unsafe impl<'buf, BUF> Sync for WordOffsetBuffer<'buf, BUF> where BUF: BufferType +{} -pub struct RegularOffsetBufferMut(&'static mut [BUF]) +pub struct WordOffsetBufferMut<'buf, BUF>(&'buf [VolatileCell]) where BUF: BufferType; -impl Deref for RegularOffsetBufferMut +impl<'buf, BUF> WordOffsetBufferMut<'buf, BUF> where BUF: BufferType, { - type Target = [BUF]; - - fn deref(&self) -> &[BUF] { - &*self.0 + pub fn get(&self, index: usize) -> BUF { + self.0[index].get() } -} -impl DerefMut for RegularOffsetBufferMut -where - BUF: BufferType, -{ - fn deref_mut(&mut self) -> &mut [BUF] { - &mut *self.0 + pub fn set(&mut self, index: usize, item: BUF) { + self.0[index].set(item); } -} -pub struct WordOffsetBuffer<'buf, BUF>(&'buf [&'static BUF]) -where - BUF: BufferType; - -impl<'buf, BUF> Deref for WordOffsetBuffer<'buf, BUF> -where - BUF: BufferType, -{ - type Target = [&'static BUF]; - - fn deref(&self) -> &[&'static BUF] { - &*self.0 + pub fn as_ptr(&self, index: usize) -> *const BUF { + self.0[index].as_ptr() } -} -pub struct WordOffsetBufferMut<'buf, BUF>(&'buf [&'static mut BUF]) -where - BUF: BufferType; - -impl<'buf, BUF> WordOffsetBufferMut<'buf, BUF> -where - BUF: BufferType, -{ - pub fn as_immutable(&self) -> WordOffsetBuffer { - let buffer = unsafe { &*(self.0 as *const _ as *const _) }; - - WordOffsetBuffer(buffer) + pub fn as_mut_ptr(&mut self, index: usize) -> *mut BUF { + self.0[index].as_ptr() } } -impl<'buf, BUF> Deref for WordOffsetBufferMut<'buf, BUF> -where - BUF: BufferType, +unsafe impl<'buf, BUF> Sync for WordOffsetBufferMut<'buf, BUF> where + BUF: BufferType { - type Target = [&'static mut BUF]; - - fn deref(&self) -> &[&'static mut BUF] { - &*self.0 - } } From 8f0d9b090dbebdf6707f290afb623d922055c069 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ad=C3=A4?= Date: Mon, 16 Dec 2019 19:19:42 +0100 Subject: [PATCH 021/103] Implemented buffer enums --- src/dma/safe_transfer.rs | 64 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/src/dma/safe_transfer.rs b/src/dma/safe_transfer.rs index 901d3281..77046358 100644 --- a/src/dma/safe_transfer.rs +++ b/src/dma/safe_transfer.rs @@ -88,6 +88,70 @@ unsafe impl BufferType for i32 {} unsafe impl BufferType for f32 {} +pub enum ImmutableBuffer<'buf, BUF> +where + BUF: BufferType, +{ + Memory(MemoryBuffer), + Peripheral(PeripheralBuffer<'buf, BUF>), +} + +pub enum MutableBuffer<'buf, BUF> +where + BUF: BufferType, +{ + Memory(MemoryBufferMut), + Peripheral(PeripheralBufferMut<'buf, BUF>), +} + +pub enum MemoryBuffer +where + BUF: BufferType, +{ + Fixed(FixedBuffer), + Incremented(RegularOffsetBuffer), +} + +pub enum MemoryBufferMut +where + BUF: BufferType, +{ + Fixed(FixedBufferMut), + Incremented(RegularOffsetBufferMut), +} + +pub enum PeripheralBuffer<'buf, BUF> +where + BUF: BufferType, +{ + Fixed(FixedBuffer), + Incremented(IncrementedBuffer<'buf, BUF>), +} + +pub enum PeripheralBufferMut<'buf, BUF> +where + BUF: BufferType, +{ + Fixed(FixedBufferMut), + Incremented(IncrementedBufferMut<'buf, BUF>), +} + +pub enum IncrementedBuffer<'buf, BUF> +where + BUF: BufferType, +{ + RegularOffset(RegularOffsetBuffer), + WordOffset(WordOffsetBuffer<'buf, BUF>), +} + +pub enum IncrementedBufferMut<'buf, BUF> +where + BUF: BufferType, +{ + RegularOffset(RegularOffsetBufferMut), + WordOffset(WordOffsetBufferMut<'buf, BUF>), +} + #[derive(Debug, PartialEq, Eq, Clone, Copy)] pub struct FixedBuffer(*const BUF) where From 4d761da3ab3581cf5f1d47416fb49f2be5c95edc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ad=C3=A4?= Date: Tue, 17 Dec 2019 01:34:12 +0100 Subject: [PATCH 022/103] Added lifetime to buffer types for more flexibility --- src/dma/safe_transfer.rs | 282 ++++++++++++++++++++++++++++++--------- 1 file changed, 216 insertions(+), 66 deletions(-) diff --git a/src/dma/safe_transfer.rs b/src/dma/safe_transfer.rs index 77046358..5a059b26 100644 --- a/src/dma/safe_transfer.rs +++ b/src/dma/safe_transfer.rs @@ -1,6 +1,7 @@ use super::stream::{MSize, PSize}; use core::convert::TryInto; use core::fmt::Debug; +use core::marker::PhantomData; use core::{mem, ptr}; use vcell::VolatileCell; @@ -88,76 +89,76 @@ unsafe impl BufferType for i32 {} unsafe impl BufferType for f32 {} -pub enum ImmutableBuffer<'buf, BUF> +pub enum ImmutableBuffer<'buf, 'wo, BUF> where BUF: BufferType, { - Memory(MemoryBuffer), - Peripheral(PeripheralBuffer<'buf, BUF>), + Memory(MemoryBuffer<'buf, BUF>), + Peripheral(PeripheralBuffer<'buf, 'wo, BUF>), } -pub enum MutableBuffer<'buf, BUF> +pub enum MutableBuffer<'buf, 'wo, BUF> where BUF: BufferType, { - Memory(MemoryBufferMut), - Peripheral(PeripheralBufferMut<'buf, BUF>), + Memory(MemoryBufferMut<'buf, BUF>), + Peripheral(PeripheralBufferMut<'buf, 'wo, BUF>), } -pub enum MemoryBuffer +pub enum MemoryBuffer<'buf, BUF> where BUF: BufferType, { - Fixed(FixedBuffer), - Incremented(RegularOffsetBuffer), + Fixed(FixedBuffer<'buf, BUF>), + Incremented(RegularOffsetBuffer<'buf, BUF>), } -pub enum MemoryBufferMut +pub enum MemoryBufferMut<'buf, BUF> where BUF: BufferType, { - Fixed(FixedBufferMut), - Incremented(RegularOffsetBufferMut), + Fixed(FixedBufferMut<'buf, BUF>), + Incremented(RegularOffsetBufferMut<'buf, BUF>), } -pub enum PeripheralBuffer<'buf, BUF> +pub enum PeripheralBuffer<'buf, 'wo, BUF> where BUF: BufferType, { - Fixed(FixedBuffer), - Incremented(IncrementedBuffer<'buf, BUF>), + Fixed(FixedBuffer<'buf, BUF>), + Incremented(IncrementedBuffer<'buf, 'wo, BUF>), } -pub enum PeripheralBufferMut<'buf, BUF> +pub enum PeripheralBufferMut<'buf, 'wo, BUF> where BUF: BufferType, { - Fixed(FixedBufferMut), - Incremented(IncrementedBufferMut<'buf, BUF>), + Fixed(FixedBufferMut<'buf, BUF>), + Incremented(IncrementedBufferMut<'buf, 'wo, BUF>), } -pub enum IncrementedBuffer<'buf, BUF> +pub enum IncrementedBuffer<'buf, 'wo, BUF> where BUF: BufferType, { - RegularOffset(RegularOffsetBuffer), - WordOffset(WordOffsetBuffer<'buf, BUF>), + RegularOffset(RegularOffsetBuffer<'buf, BUF>), + WordOffset(WordOffsetBuffer<'buf, 'wo, BUF>), } -pub enum IncrementedBufferMut<'buf, BUF> +pub enum IncrementedBufferMut<'buf, 'wo, BUF> where BUF: BufferType, { - RegularOffset(RegularOffsetBufferMut), - WordOffset(WordOffsetBufferMut<'buf, BUF>), + RegularOffset(RegularOffsetBufferMut<'buf, BUF>), + WordOffset(WordOffsetBufferMut<'buf, 'wo, BUF>), } #[derive(Debug, PartialEq, Eq, Clone, Copy)] -pub struct FixedBuffer(*const BUF) +pub struct FixedBuffer<'buf, BUF>(*const BUF, PhantomData<&'buf BUF>) where BUF: BufferType; -impl FixedBuffer +impl<'buf, BUF> FixedBuffer<'buf, BUF> where BUF: BufferType, { @@ -170,27 +171,42 @@ where } } -unsafe impl Send for FixedBuffer where BUF: BufferType {} +unsafe impl<'buf, BUF> Send for FixedBuffer<'buf, BUF> where BUF: BufferType {} -unsafe impl Sync for FixedBuffer where BUF: BufferType {} +unsafe impl<'buf, BUF> Sync for FixedBuffer<'buf, BUF> where BUF: BufferType {} + +pub type FixedBufferStatic = FixedBuffer<'static, BUF>; + +impl FixedBufferStatic +where + BUF: BufferType, +{ + pub fn new(buffer: &'static BUF) -> Self { + FixedBuffer(buffer, PhantomData) + } +} #[derive(Debug, PartialEq, Eq)] -pub struct FixedBufferMut(*mut BUF) +pub struct FixedBufferMut<'buf, BUF>(*mut BUF, PhantomData<&'buf mut BUF>) where BUF: BufferType; -impl FixedBufferMut +impl FixedBufferMut<'_, BUF> where BUF: BufferType, { - pub fn get(&self) -> BUF { - unsafe { ptr::read_volatile(self.0) } + /// # Safety + /// + /// - The caller must ensure, that the DMA is currently not writing this address. + pub unsafe fn get(&self) -> BUF { + ptr::read_volatile(self.0) } - pub fn set(&mut self, buf: BUF) { - unsafe { - ptr::write_volatile(self.0, buf); - } + /// # Safety + /// + /// - The caller must ensure, that the DMA is currently not writing this address. + pub unsafe fn set(&mut self, buf: BUF) { + ptr::write_volatile(self.0, buf); } pub fn as_ptr(&self) -> *const BUF { @@ -200,23 +216,38 @@ where pub fn as_mut_ptr(&mut self) -> *mut BUF { self.0 } + + pub fn as_immutable(&self) -> FixedBuffer { + FixedBuffer(self.0, PhantomData) + } } -unsafe impl Send for FixedBufferMut where BUF: BufferType {} +unsafe impl<'buf, BUF> Send for FixedBufferMut<'buf, BUF> where BUF: BufferType {} -unsafe impl Sync for FixedBufferMut where BUF: BufferType {} +unsafe impl<'buf, BUF> Sync for FixedBufferMut<'buf, BUF> where BUF: BufferType {} + +pub type FixedBufferMutStatic = FixedBufferMut<'static, BUF>; + +impl FixedBufferMutStatic +where + BUF: BufferType, +{ + pub fn new(buffer: &'static mut BUF) -> Self { + FixedBufferMut(buffer, PhantomData) + } +} #[derive(Debug, PartialEq, Eq, Clone, Copy)] -pub struct RegularOffsetBuffer(*const [BUF]) +pub struct RegularOffsetBuffer<'buf, BUF>(*const [BUF], PhantomData<&'buf BUF>) where BUF: BufferType; -impl RegularOffsetBuffer +impl<'buf, BUF> RegularOffsetBuffer<'buf, BUF> where BUF: BufferType, { pub fn get(self, index: usize) -> BUF { - unsafe { volatile_read_buffer_slice(self.0, index) } + unsafe { read_volatile_slice_buffer(self.0, index) } } pub fn as_ptr(self, index: usize) -> *const BUF { @@ -227,28 +258,52 @@ where } } -unsafe impl Send for RegularOffsetBuffer where BUF: BufferType {} +unsafe impl<'buf, BUF> Send for RegularOffsetBuffer<'buf, BUF> where + BUF: BufferType +{ +} -unsafe impl Sync for RegularOffsetBuffer where BUF: BufferType {} +unsafe impl<'buf, BUF> Sync for RegularOffsetBuffer<'buf, BUF> where + BUF: BufferType +{ +} + +pub type RegularOffsetBufferStatic = RegularOffsetBuffer<'static, BUF>; + +impl RegularOffsetBufferStatic +where + BUF: BufferType, +{ + pub fn new(buffer: &'static [BUF]) -> Self { + RegularOffsetBuffer(buffer, PhantomData) + } +} #[derive(Debug, PartialEq, Eq)] -pub struct RegularOffsetBufferMut(*mut [BUF]) +pub struct RegularOffsetBufferMut<'buf, BUF>( + *mut [BUF], + PhantomData<&'buf mut BUF>, +) where BUF: BufferType; -impl RegularOffsetBufferMut +impl<'buf, BUF> RegularOffsetBufferMut<'buf, BUF> where BUF: BufferType, { - pub fn get(&self, index: usize) -> BUF { - unsafe { volatile_read_buffer_slice(self.0, index) } + /// # Safety + /// + /// - The caller must ensure, that the DMA is currently not modifying this address. + pub unsafe fn get(&self, index: usize) -> BUF { + read_volatile_slice_buffer(self.0, index) } - pub fn set(&mut self, index: usize, item: BUF) { - unsafe { - let slice = &mut *self.0; - ptr::write_volatile(&mut slice[index] as *mut _, item); - } + /// # Safety + /// + /// - The caller must ensure, that the DMA is currently not modifying this address. + pub unsafe fn set(&mut self, index: usize, item: BUF) { + let slice = &mut *self.0; + ptr::write_volatile(&mut slice[index] as *mut _, item); } pub fn as_ptr(&self, index: usize) -> *const BUF { @@ -264,13 +319,35 @@ where &mut slice[index] as *mut _ } } + + pub fn as_immutable(&self) -> RegularOffsetBuffer { + RegularOffsetBuffer(self.0, PhantomData) + } +} + +unsafe impl<'buf, BUF> Send for RegularOffsetBufferMut<'buf, BUF> where + BUF: BufferType +{ } -unsafe impl Send for RegularOffsetBufferMut where BUF: BufferType {} +unsafe impl<'buf, BUF> Sync for RegularOffsetBufferMut<'buf, BUF> where + BUF: BufferType +{ +} -unsafe impl Sync for RegularOffsetBufferMut where BUF: BufferType {} +pub type RegularOffsetBufferMutStatic = + RegularOffsetBufferMut<'static, BUF>; -unsafe fn volatile_read_buffer_slice( +impl RegularOffsetBufferMutStatic +where + BUF: BufferType, +{ + pub fn new(buffer: &'static mut [BUF]) -> Self { + RegularOffsetBufferMut(buffer, PhantomData) + } +} + +unsafe fn read_volatile_slice_buffer( slice_ptr: *const [BUF], index: usize, ) -> BUF @@ -282,11 +359,14 @@ where } #[derive(Debug, PartialEq, Eq, Clone, Copy)] -pub struct WordOffsetBuffer<'buf, BUF>(&'buf [*const BUF]) +pub struct WordOffsetBuffer<'buf, 'wo, BUF>( + &'wo [*const BUF], + PhantomData<&'buf BUF>, +) where BUF: BufferType; -impl<'buf, BUF> WordOffsetBuffer<'buf, BUF> +impl<'buf, 'wo, BUF> WordOffsetBuffer<'buf, 'wo, BUF> where BUF: BufferType, { @@ -299,25 +379,53 @@ where } } -unsafe impl<'buf, BUF> Send for WordOffsetBuffer<'buf, BUF> where BUF: BufferType -{} +unsafe impl<'buf, 'wo, BUF> Send for WordOffsetBuffer<'buf, 'wo, BUF> where + BUF: BufferType +{ +} -unsafe impl<'buf, BUF> Sync for WordOffsetBuffer<'buf, BUF> where BUF: BufferType -{} +unsafe impl<'buf, 'wo, BUF> Sync for WordOffsetBuffer<'buf, 'wo, BUF> where + BUF: BufferType +{ +} + +pub type WordOffsetBufferStatic<'wo, BUF> = WordOffsetBuffer<'static, 'wo, BUF>; + +impl<'wo, BUF> WordOffsetBufferStatic<'wo, BUF> +where + BUF: BufferType, +{ + pub fn new(buffer: &'wo [&'static BUF]) -> Self { + let buffer = unsafe { &*(buffer as *const _ as *const _) }; + + check_word_offset(buffer); + + WordOffsetBuffer(buffer, PhantomData) + } +} -pub struct WordOffsetBufferMut<'buf, BUF>(&'buf [VolatileCell]) +pub struct WordOffsetBufferMut<'buf, 'wo, BUF>( + &'wo [VolatileCell], + PhantomData<&'buf mut BUF>, +) where BUF: BufferType; -impl<'buf, BUF> WordOffsetBufferMut<'buf, BUF> +impl<'buf, 'wo, BUF> WordOffsetBufferMut<'buf, 'wo, BUF> where BUF: BufferType, { - pub fn get(&self, index: usize) -> BUF { + /// # Safety + /// + /// - The caller must ensure, that the DMA is currently not modifying this address. + pub unsafe fn get(&self, index: usize) -> BUF { self.0[index].get() } - pub fn set(&mut self, index: usize, item: BUF) { + /// # Safety + /// + /// - The caller must ensure, that the DMA is currently not modifying this address. + pub unsafe fn set(&mut self, index: usize, item: BUF) { self.0[index].set(item); } @@ -328,9 +436,51 @@ where pub fn as_mut_ptr(&mut self, index: usize) -> *mut BUF { self.0[index].as_ptr() } + + pub fn as_immutable(&self) -> WordOffsetBuffer<'_, 'wo, BUF> { + unsafe { + WordOffsetBuffer(&*(self.0 as *const _ as *const _), PhantomData) + } + } } -unsafe impl<'buf, BUF> Sync for WordOffsetBufferMut<'buf, BUF> where +unsafe impl<'buf, 'wo, BUF> Sync for WordOffsetBufferMut<'buf, 'wo, BUF> where BUF: BufferType { } + +pub type WordOffsetBufferMutStatic<'wo, BUF> = + WordOffsetBufferMut<'static, 'wo, BUF>; + +impl<'wo, BUF> WordOffsetBufferMutStatic<'wo, BUF> +where + BUF: BufferType, +{ + pub fn new(buffer: &'wo [&'static mut BUF]) -> Self { + unsafe { + check_word_offset::(&*(buffer as *const _ as *const _)); + + WordOffsetBufferMut(&*(buffer as *const _ as *const _), PhantomData) + } + } +} + +fn check_word_offset(buffer: &[*const BUF]) +where + BUF: BufferType, +{ + if buffer.len() > 0 { + let mut last_pointer = buffer[0] as *const _ as *const u32; + + for i in 1..buffer.len() { + let current_pointer = buffer[i] as *const _ as *const u32; + let current_address = current_pointer as usize; + let expected_address = unsafe { last_pointer.add(1) } as usize; + if current_address != expected_address { + panic!("The offset must be one word (4 bytes)."); + } + + last_pointer = current_pointer; + } + } +} From b0442cfe83d0d531f845e450af6638457c2cf22b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ad=C3=A4?= Date: Tue, 17 Dec 2019 16:55:16 +0100 Subject: [PATCH 023/103] Fixed WordOffsetMut Buffer --- src/dma/safe_transfer.rs | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/src/dma/safe_transfer.rs b/src/dma/safe_transfer.rs index 5a059b26..51f32961 100644 --- a/src/dma/safe_transfer.rs +++ b/src/dma/safe_transfer.rs @@ -405,7 +405,7 @@ where } pub struct WordOffsetBufferMut<'buf, 'wo, BUF>( - &'wo [VolatileCell], + &'wo [&'static mut VolatileCell], PhantomData<&'buf mut BUF>, ) where @@ -469,18 +469,20 @@ fn check_word_offset(buffer: &[*const BUF]) where BUF: BufferType, { - if buffer.len() > 0 { - let mut last_pointer = buffer[0] as *const _ as *const u32; - - for i in 1..buffer.len() { - let current_pointer = buffer[i] as *const _ as *const u32; - let current_address = current_pointer as usize; - let expected_address = unsafe { last_pointer.add(1) } as usize; - if current_address != expected_address { - panic!("The offset must be one word (4 bytes)."); - } - - last_pointer = current_pointer; + if buffer.is_empty() { + return; + } + + let mut last_pointer = buffer[0] as *const _ as *const u32; + + for ¤t_pointer in buffer.iter().skip(1) { + // Size of u32 is one word / 4 bytes + let current_pointer = current_pointer as *const u32; + let expected_pointer = unsafe { last_pointer.add(1) }; + if current_pointer != expected_pointer { + panic!("The offset must be one word (4 bytes)."); } + + last_pointer = current_pointer; } } From 1132792dd8dd6b2b86394a1f9e23d5b445285509 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ad=C3=A4?= Date: Tue, 17 Dec 2019 17:48:22 +0100 Subject: [PATCH 024/103] minor changes --- src/dma/safe_transfer.rs | 102 ++++++++++++++------------------------- 1 file changed, 37 insertions(+), 65 deletions(-) diff --git a/src/dma/safe_transfer.rs b/src/dma/safe_transfer.rs index 51f32961..cb0730fa 100644 --- a/src/dma/safe_transfer.rs +++ b/src/dma/safe_transfer.rs @@ -153,6 +153,9 @@ where WordOffset(WordOffsetBufferMut<'buf, 'wo, BUF>), } +pub type IncrementedBufferMutStatic<'wo, BUF> = + IncrementedBufferMut<'static, 'wo, BUF>; + #[derive(Debug, PartialEq, Eq, Clone, Copy)] pub struct FixedBuffer<'buf, BUF>(*const BUF, PhantomData<&'buf BUF>) where @@ -162,6 +165,10 @@ impl<'buf, BUF> FixedBuffer<'buf, BUF> where BUF: BufferType, { + pub fn new(buffer: &'buf BUF) -> Self { + FixedBuffer(buffer, PhantomData) + } + pub fn get(self) -> BUF { unsafe { self.0.read_volatile() } } @@ -177,24 +184,19 @@ unsafe impl<'buf, BUF> Sync for FixedBuffer<'buf, BUF> where BUF: BufferType {} pub type FixedBufferStatic = FixedBuffer<'static, BUF>; -impl FixedBufferStatic -where - BUF: BufferType, -{ - pub fn new(buffer: &'static BUF) -> Self { - FixedBuffer(buffer, PhantomData) - } -} - #[derive(Debug, PartialEq, Eq)] pub struct FixedBufferMut<'buf, BUF>(*mut BUF, PhantomData<&'buf mut BUF>) where BUF: BufferType; -impl FixedBufferMut<'_, BUF> +impl<'buf, BUF> FixedBufferMut<'buf, BUF> where BUF: BufferType, { + pub fn new(buffer: &'buf mut BUF) -> Self { + FixedBufferMut(buffer, PhantomData) + } + /// # Safety /// /// - The caller must ensure, that the DMA is currently not writing this address. @@ -228,15 +230,6 @@ unsafe impl<'buf, BUF> Sync for FixedBufferMut<'buf, BUF> where BUF: BufferType pub type FixedBufferMutStatic = FixedBufferMut<'static, BUF>; -impl FixedBufferMutStatic -where - BUF: BufferType, -{ - pub fn new(buffer: &'static mut BUF) -> Self { - FixedBufferMut(buffer, PhantomData) - } -} - #[derive(Debug, PartialEq, Eq, Clone, Copy)] pub struct RegularOffsetBuffer<'buf, BUF>(*const [BUF], PhantomData<&'buf BUF>) where @@ -246,6 +239,10 @@ impl<'buf, BUF> RegularOffsetBuffer<'buf, BUF> where BUF: BufferType, { + pub fn new(buffer: &'buf [BUF]) -> Self { + RegularOffsetBuffer(buffer, PhantomData) + } + pub fn get(self, index: usize) -> BUF { unsafe { read_volatile_slice_buffer(self.0, index) } } @@ -270,15 +267,6 @@ unsafe impl<'buf, BUF> Sync for RegularOffsetBuffer<'buf, BUF> where pub type RegularOffsetBufferStatic = RegularOffsetBuffer<'static, BUF>; -impl RegularOffsetBufferStatic -where - BUF: BufferType, -{ - pub fn new(buffer: &'static [BUF]) -> Self { - RegularOffsetBuffer(buffer, PhantomData) - } -} - #[derive(Debug, PartialEq, Eq)] pub struct RegularOffsetBufferMut<'buf, BUF>( *mut [BUF], @@ -291,6 +279,10 @@ impl<'buf, BUF> RegularOffsetBufferMut<'buf, BUF> where BUF: BufferType, { + pub fn new(buffer: &'buf mut [BUF]) -> Self { + RegularOffsetBufferMut(buffer, PhantomData) + } + /// # Safety /// /// - The caller must ensure, that the DMA is currently not modifying this address. @@ -338,15 +330,6 @@ unsafe impl<'buf, BUF> Sync for RegularOffsetBufferMut<'buf, BUF> where pub type RegularOffsetBufferMutStatic = RegularOffsetBufferMut<'static, BUF>; -impl RegularOffsetBufferMutStatic -where - BUF: BufferType, -{ - pub fn new(buffer: &'static mut [BUF]) -> Self { - RegularOffsetBufferMut(buffer, PhantomData) - } -} - unsafe fn read_volatile_slice_buffer( slice_ptr: *const [BUF], index: usize, @@ -370,6 +353,14 @@ impl<'buf, 'wo, BUF> WordOffsetBuffer<'buf, 'wo, BUF> where BUF: BufferType, { + pub fn new(buffer: &'wo [&'buf BUF]) -> Self { + let buffer = unsafe { &*(buffer as *const _ as *const _) }; + + check_word_offset(buffer); + + WordOffsetBuffer(buffer, PhantomData) + } + pub fn get(self, index: usize) -> BUF { unsafe { ptr::read_volatile(self.0[index]) } } @@ -391,22 +382,8 @@ unsafe impl<'buf, 'wo, BUF> Sync for WordOffsetBuffer<'buf, 'wo, BUF> where pub type WordOffsetBufferStatic<'wo, BUF> = WordOffsetBuffer<'static, 'wo, BUF>; -impl<'wo, BUF> WordOffsetBufferStatic<'wo, BUF> -where - BUF: BufferType, -{ - pub fn new(buffer: &'wo [&'static BUF]) -> Self { - let buffer = unsafe { &*(buffer as *const _ as *const _) }; - - check_word_offset(buffer); - - WordOffsetBuffer(buffer, PhantomData) - } -} - pub struct WordOffsetBufferMut<'buf, 'wo, BUF>( - &'wo [&'static mut VolatileCell], - PhantomData<&'buf mut BUF>, + &'wo [&'buf mut VolatileCell], ) where BUF: BufferType; @@ -415,6 +392,14 @@ impl<'buf, 'wo, BUF> WordOffsetBufferMut<'buf, 'wo, BUF> where BUF: BufferType, { + pub fn new(buffer: &'wo [&'buf mut BUF]) -> Self { + unsafe { + check_word_offset::(&*(buffer as *const _ as *const _)); + + WordOffsetBufferMut(&*(buffer as *const _ as *const _)) + } + } + /// # Safety /// /// - The caller must ensure, that the DMA is currently not modifying this address. @@ -452,19 +437,6 @@ unsafe impl<'buf, 'wo, BUF> Sync for WordOffsetBufferMut<'buf, 'wo, BUF> where pub type WordOffsetBufferMutStatic<'wo, BUF> = WordOffsetBufferMut<'static, 'wo, BUF>; -impl<'wo, BUF> WordOffsetBufferMutStatic<'wo, BUF> -where - BUF: BufferType, -{ - pub fn new(buffer: &'wo [&'static mut BUF]) -> Self { - unsafe { - check_word_offset::(&*(buffer as *const _ as *const _)); - - WordOffsetBufferMut(&*(buffer as *const _ as *const _), PhantomData) - } - } -} - fn check_word_offset(buffer: &[*const BUF]) where BUF: BufferType, From a0911be61b20d1b40b3c1cbe3e12bbbab62127fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ad=C3=A4?= Date: Tue, 17 Dec 2019 20:08:38 +0100 Subject: [PATCH 025/103] Implemented unwrap methods for buffer enums --- src/dma/safe_transfer.rs | 327 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 323 insertions(+), 4 deletions(-) diff --git a/src/dma/safe_transfer.rs b/src/dma/safe_transfer.rs index cb0730fa..cd4d616e 100644 --- a/src/dma/safe_transfer.rs +++ b/src/dma/safe_transfer.rs @@ -8,10 +8,7 @@ use vcell::VolatileCell; /// # Safety /// /// * `Self` must be valid for any bit representation -pub unsafe trait BufferType: - Sized + Clone + Copy + Sync + 'static -{ -} +pub unsafe trait BufferType: Sized + Clone + Copy + Sync {} // Maps BufferTypeSize to number of bytes int_enum! { @@ -97,6 +94,29 @@ where Peripheral(PeripheralBuffer<'buf, 'wo, BUF>), } +impl<'buf, 'wo, BUF> ImmutableBuffer<'buf, 'wo, BUF> +where + BUF: BufferType, +{ + pub fn memory(self) -> MemoryBuffer<'buf, BUF> { + if let ImmutableBuffer::Memory(buffer) = self { + buffer + } else { + panic!("The buffer is a peripheral buffer."); + } + } + + pub fn peripheral(self) -> PeripheralBuffer<'buf, 'wo, BUF> { + if let ImmutableBuffer::Peripheral(buffer) = self { + buffer + } else { + panic!("The buffer is a memory buffer."); + } + } +} + +pub type ImmutableBufferStatic<'wo, BUF> = ImmutableBuffer<'static, 'wo, BUF>; + pub enum MutableBuffer<'buf, 'wo, BUF> where BUF: BufferType, @@ -105,6 +125,63 @@ where Peripheral(PeripheralBufferMut<'buf, 'wo, BUF>), } +impl<'buf, 'wo, BUF> MutableBuffer<'buf, 'wo, BUF> +where + BUF: BufferType, +{ + pub fn into_memory(self) -> MemoryBufferMut<'buf, BUF> { + if let MutableBuffer::Memory(buffer) = self { + buffer + } else { + panic!("The buffer is a peripheral buffer."); + } + } + + pub fn as_memory(&self) -> &MemoryBufferMut<'buf, BUF> { + if let MutableBuffer::Memory(buffer) = self { + buffer + } else { + panic!("The buffer is a peripheral buffer."); + } + } + + pub fn as_mut_memory(&mut self) -> &mut MemoryBufferMut<'buf, BUF> { + if let MutableBuffer::Memory(buffer) = self { + buffer + } else { + panic!("The buffer is a peripheral buffer."); + } + } + + pub fn into_peripheral(self) -> PeripheralBufferMut<'buf, 'wo, BUF> { + if let MutableBuffer::Peripheral(buffer) = self { + buffer + } else { + panic!("The buffer is a memory buffer."); + } + } + + pub fn as_peripheral(&self) -> &PeripheralBufferMut<'buf, 'wo, BUF> { + if let MutableBuffer::Peripheral(buffer) = self { + buffer + } else { + panic!("The buffer is a memory buffer."); + } + } + + pub fn as_mut_peripheral( + &mut self, + ) -> &mut PeripheralBufferMut<'buf, 'wo, BUF> { + if let MutableBuffer::Peripheral(buffer) = self { + buffer + } else { + panic!("The buffer is a memory buffer."); + } + } +} + +pub type MutableBufferStatic<'wo, BUF> = MutableBuffer<'static, 'wo, BUF>; + pub enum MemoryBuffer<'buf, BUF> where BUF: BufferType, @@ -113,6 +190,29 @@ where Incremented(RegularOffsetBuffer<'buf, BUF>), } +impl<'buf, BUF> MemoryBuffer<'buf, BUF> +where + BUF: BufferType, +{ + pub fn fixed(self) -> FixedBuffer<'buf, BUF> { + if let MemoryBuffer::Fixed(buffer) = self { + buffer + } else { + panic!("The buffer is incremented."); + } + } + + pub fn incremented(self) -> RegularOffsetBuffer<'buf, BUF> { + if let MemoryBuffer::Incremented(buffer) = self { + buffer + } else { + panic!("The buffer is fixed."); + } + } +} + +pub type MemoryBufferStatic = MemoryBuffer<'static, BUF>; + pub enum MemoryBufferMut<'buf, BUF> where BUF: BufferType, @@ -121,6 +221,63 @@ where Incremented(RegularOffsetBufferMut<'buf, BUF>), } +impl<'buf, BUF> MemoryBufferMut<'buf, BUF> +where + BUF: BufferType, +{ + pub fn into_fixed(self) -> FixedBufferMut<'buf, BUF> { + if let MemoryBufferMut::Fixed(buffer) = self { + buffer + } else { + panic!("The buffer is incremented."); + } + } + + pub fn as_fixed(&self) -> &FixedBufferMut<'buf, BUF> { + if let MemoryBufferMut::Fixed(buffer) = self { + buffer + } else { + panic!("The buffer is incremented."); + } + } + + pub fn as_mut_fixed(&mut self) -> &mut FixedBufferMut<'buf, BUF> { + if let MemoryBufferMut::Fixed(buffer) = self { + buffer + } else { + panic!("The buffer is incremented."); + } + } + + pub fn into_incremented(self) -> RegularOffsetBufferMut<'buf, BUF> { + if let MemoryBufferMut::Incremented(buffer) = self { + buffer + } else { + panic!("The buffer is fixed."); + } + } + + pub fn as_incremented(&self) -> &RegularOffsetBufferMut<'buf, BUF> { + if let MemoryBufferMut::Incremented(buffer) = self { + buffer + } else { + panic!("The buffer is fixed."); + } + } + + pub fn as_mut_incremented( + &mut self, + ) -> &mut RegularOffsetBufferMut<'buf, BUF> { + if let MemoryBufferMut::Incremented(buffer) = self { + buffer + } else { + panic!("The buffer is fixed."); + } + } +} + +pub type MemoryBufferMutStatic = MemoryBufferMut<'static, BUF>; + pub enum PeripheralBuffer<'buf, 'wo, BUF> where BUF: BufferType, @@ -129,6 +286,29 @@ where Incremented(IncrementedBuffer<'buf, 'wo, BUF>), } +impl<'buf, 'wo, BUF> PeripheralBuffer<'buf, 'wo, BUF> +where + BUF: BufferType, +{ + pub fn fixed(self) -> FixedBuffer<'buf, BUF> { + if let PeripheralBuffer::Fixed(buffer) = self { + buffer + } else { + panic!("The buffer is incremented."); + } + } + + pub fn incremented(self) -> IncrementedBuffer<'buf, 'wo, BUF> { + if let PeripheralBuffer::Incremented(buffer) = self { + buffer + } else { + panic!("The buffer is fixed."); + } + } +} + +pub type PeripheralBufferStatic<'wo, BUF> = PeripheralBuffer<'static, 'wo, BUF>; + pub enum PeripheralBufferMut<'buf, 'wo, BUF> where BUF: BufferType, @@ -137,6 +317,64 @@ where Incremented(IncrementedBufferMut<'buf, 'wo, BUF>), } +impl<'buf, 'wo, BUF> PeripheralBufferMut<'buf, 'wo, BUF> +where + BUF: BufferType, +{ + pub fn into_fixed(self) -> FixedBufferMut<'buf, BUF> { + if let PeripheralBufferMut::Fixed(buffer) = self { + buffer + } else { + panic!("The buffer is incremented."); + } + } + + pub fn as_fixed(&self) -> &FixedBufferMut<'buf, BUF> { + if let PeripheralBufferMut::Fixed(buffer) = self { + buffer + } else { + panic!("The buffer is incremented."); + } + } + + pub fn as_mut_fixed(&mut self) -> &mut FixedBufferMut<'buf, BUF> { + if let PeripheralBufferMut::Fixed(buffer) = self { + buffer + } else { + panic!("The buffer is incremented."); + } + } + + pub fn into_incremented(self) -> IncrementedBufferMut<'buf, 'wo, BUF> { + if let PeripheralBufferMut::Incremented(buffer) = self { + buffer + } else { + panic!("The buffer is fixed."); + } + } + + pub fn as_incremented(&self) -> &IncrementedBufferMut<'buf, 'wo, BUF> { + if let PeripheralBufferMut::Incremented(buffer) = self { + buffer + } else { + panic!("The buffer is fixed."); + } + } + + pub fn as_mut_incremented( + &mut self, + ) -> &mut IncrementedBufferMut<'buf, 'wo, BUF> { + if let PeripheralBufferMut::Incremented(buffer) = self { + buffer + } else { + panic!("The buffer is fixed."); + } + } +} + +pub type PeripheralBufferMutStatic<'wo, BUF> = + PeripheralBufferMut<'static, 'wo, BUF>; + pub enum IncrementedBuffer<'buf, 'wo, BUF> where BUF: BufferType, @@ -145,6 +383,30 @@ where WordOffset(WordOffsetBuffer<'buf, 'wo, BUF>), } +impl<'buf, 'wo, BUF> IncrementedBuffer<'buf, 'wo, BUF> +where + BUF: BufferType, +{ + pub fn regular_offset(self) -> RegularOffsetBuffer<'buf, BUF> { + if let IncrementedBuffer::RegularOffset(buffer) = self { + buffer + } else { + panic!("The buffer has word offset."); + } + } + + pub fn word_offset(self) -> WordOffsetBuffer<'buf, 'wo, BUF> { + if let IncrementedBuffer::WordOffset(buffer) = self { + buffer + } else { + panic!("The buffer has regular offset."); + } + } +} + +pub type IncrementedBufferStatic<'wo, BUF> = + IncrementedBuffer<'static, 'wo, BUF>; + pub enum IncrementedBufferMut<'buf, 'wo, BUF> where BUF: BufferType, @@ -153,6 +415,63 @@ where WordOffset(WordOffsetBufferMut<'buf, 'wo, BUF>), } +impl<'buf, 'wo, BUF> IncrementedBufferMut<'buf, 'wo, BUF> +where + BUF: BufferType, +{ + pub fn into_regular_offset(self) -> RegularOffsetBufferMut<'buf, BUF> { + if let IncrementedBufferMut::RegularOffset(buffer) = self { + buffer + } else { + panic!("The buffer has word offset."); + } + } + + pub fn as_regular_offset(&self) -> &RegularOffsetBufferMut<'buf, BUF> { + if let IncrementedBufferMut::RegularOffset(buffer) = self { + buffer + } else { + panic!("The buffer has word offset."); + } + } + + pub fn as_mut_regular_offset( + &mut self, + ) -> &mut RegularOffsetBufferMut<'buf, BUF> { + if let IncrementedBufferMut::RegularOffset(buffer) = self { + buffer + } else { + panic!("The buffer has word offset."); + } + } + + pub fn into_word_offset(self) -> WordOffsetBufferMut<'buf, 'wo, BUF> { + if let IncrementedBufferMut::WordOffset(buffer) = self { + buffer + } else { + panic!("The buffer has regular offset."); + } + } + + pub fn as_word_offset(&self) -> &WordOffsetBufferMut<'buf, 'wo, BUF> { + if let IncrementedBufferMut::WordOffset(buffer) = self { + buffer + } else { + panic!("The buffer has regular offset."); + } + } + + pub fn as_mut_word_offset( + &mut self, + ) -> &mut WordOffsetBufferMut<'buf, 'wo, BUF> { + if let IncrementedBufferMut::WordOffset(buffer) = self { + buffer + } else { + panic!("The buffer has regular offset."); + } + } +} + pub type IncrementedBufferMutStatic<'wo, BUF> = IncrementedBufferMut<'static, 'wo, BUF>; From 4caa09238cee5aef7ff65196e40f5f3d95decd1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ad=C3=A4?= Date: Tue, 17 Dec 2019 20:53:05 +0100 Subject: [PATCH 026/103] implemented as_immutable methods for buffers --- src/dma/safe_transfer.rs | 46 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/src/dma/safe_transfer.rs b/src/dma/safe_transfer.rs index cd4d616e..0ae12e97 100644 --- a/src/dma/safe_transfer.rs +++ b/src/dma/safe_transfer.rs @@ -178,6 +178,17 @@ where panic!("The buffer is a memory buffer."); } } + + pub fn as_immutable(&self) -> ImmutableBuffer { + match self { + MutableBuffer::Memory(buffer) => { + ImmutableBuffer::Memory(buffer.as_immutable()) + } + MutableBuffer::Peripheral(buffer) => { + ImmutableBuffer::Peripheral(buffer.as_immutable()) + } + } + } } pub type MutableBufferStatic<'wo, BUF> = MutableBuffer<'static, 'wo, BUF>; @@ -274,6 +285,17 @@ where panic!("The buffer is fixed."); } } + + pub fn as_immutable(&self) -> MemoryBuffer { + match self { + MemoryBufferMut::Fixed(buffer) => { + MemoryBuffer::Fixed(buffer.as_immutable()) + } + MemoryBufferMut::Incremented(buffer) => { + MemoryBuffer::Incremented(buffer.as_immutable()) + } + } + } } pub type MemoryBufferMutStatic = MemoryBufferMut<'static, BUF>; @@ -370,6 +392,17 @@ where panic!("The buffer is fixed."); } } + + pub fn as_immutable(&self) -> PeripheralBuffer { + match self { + PeripheralBufferMut::Fixed(buffer) => { + PeripheralBuffer::Fixed(buffer.as_immutable()) + } + PeripheralBufferMut::Incremented(buffer) => { + PeripheralBuffer::Incremented(buffer.as_immutable()) + } + } + } } pub type PeripheralBufferMutStatic<'wo, BUF> = @@ -470,6 +503,17 @@ where panic!("The buffer has regular offset."); } } + + pub fn as_immutable(&self) -> IncrementedBuffer { + match self { + IncrementedBufferMut::RegularOffset(buffer) => { + IncrementedBuffer::RegularOffset(buffer.as_immutable()) + } + IncrementedBufferMut::WordOffset(buffer) => { + IncrementedBuffer::WordOffset(buffer.as_immutable()) + } + } + } } pub type IncrementedBufferMutStatic<'wo, BUF> = @@ -741,7 +785,7 @@ where self.0[index].as_ptr() } - pub fn as_immutable(&self) -> WordOffsetBuffer<'_, 'wo, BUF> { + pub fn as_immutable(&self) -> WordOffsetBuffer { unsafe { WordOffsetBuffer(&*(self.0 as *const _ as *const _), PhantomData) } From ae105e8ecc4fdd09a24efbfe0491da067d917e43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ad=C3=A4?= Date: Wed, 18 Dec 2019 18:42:47 +0100 Subject: [PATCH 027/103] Implemented stream configuration for safe transfer --- src/dma.rs | 193 +++++++++++++++++++++++++++++- src/dma/safe_transfer.rs | 250 ++++++++++++++++++++++++++++++++++++--- 2 files changed, 423 insertions(+), 20 deletions(-) diff --git a/src/dma.rs b/src/dma.rs index e253fe8f..4ec6d8ee 100644 --- a/src/dma.rs +++ b/src/dma.rs @@ -17,6 +17,10 @@ use self::mux::{ SyncDisabled, SyncED as SyncEDTrait, SyncEnabled, SyncId, SyncOverrunInterrupt, SyncPolarity, }; +use self::safe_transfer::{ + BufferType, ImmutableBufferStatic, MutableBufferStatic, Ongoing, Start, + TransferState, +}; use self::stm32::dma1::ST; use self::stm32::dmamux1::CCR; use self::stm32::{DMA1, DMA2}; @@ -165,6 +169,10 @@ where self.rb.fcr.read().feie().bit().into() } + /// **Note** (for disabled streams): + /// This config value gets forced to `Dma`, if `transfer_direction` is `M2M`. + /// + /// This invariant is covered in `effective_flow_controller` (defined for disabled streams). pub fn flow_controller(&self) -> FlowController { self.rb.cr.read().pfctrl().bit().into() } @@ -173,6 +181,10 @@ where self.rb.cr.read().dir().bits().try_into().unwrap() } + /// **Note** (for disabled streams): + /// This config value gets forced to `Circular`, if `buffer_mode` is `DoubleBuffer`. + /// + /// This invariant is covered in `effective_circular_mode`. pub fn circular_mode(&self) -> CircularMode { self.rb.cr.read().circ().bit().into() } @@ -189,10 +201,20 @@ where self.rb.cr.read().psize().bits().try_into().unwrap() } + /// **Note** (for disabled streams): + /// This config value gets forced to `p_size`, if `transfer_mode` is `Direct`. + /// + /// This invariant is covered in `effective_m_size`. pub fn m_size(&self) -> MSize { self.rb.cr.read().msize().bits().try_into().unwrap() } + /// **Note** (for disabled and enabled streams): + /// + /// - This config value has no meaning, if `pinc` is `Fixed`. + /// - This config value gets forced to `PSize`, if `p_burst` is not `Single`. + /// + /// These invariants are covered in `effective_pincos` (defined for disabled and enabled streams). pub fn pincos(&self) -> Pincos { self.rb.cr.read().pincos().bit().into() } @@ -205,14 +227,36 @@ where self.rb.cr.read().dbm().bit().into() } + /// **Note** (for disabled and enabled streams): + /// This config value has no meaning, if `BufferMode` is `Regular`. + /// + /// This invariant is covered in `effective_current_target`. pub fn current_target(&self) -> CurrentTarget { self.rb.cr.read().ct().bit().into() } + /// **Note**: If this config value has no meaning (because `BufferMode` is `Regular`), + /// the method returns `CurrentTarget::M0a` instead of `None`. + pub fn effective_current_target(&self) -> CurrentTarget { + if self.buffer_mode() == BufferMode::Regular { + CurrentTarget::M0a + } else { + self.current_target() + } + } + + /// **Note** (for disabled streams): + /// This config value gets forced to `Single`, if `transfer_mode` is `Direct`. + /// + /// This invariant is covered in `effective_p_burst` (defined for disabled streams). pub fn p_burst(&self) -> PBurst { self.rb.cr.read().pburst().bits().try_into().unwrap() } + /// **Note** (for disabled streams): + /// This config value gets forced to `Single`, if `transfer_mode` is `Direct`. + /// + /// This invariant is covered in `effective_m_burst` (defined for disabled streams). pub fn m_burst(&self) -> MBurst { self.rb.cr.read().mburst().bits().try_into().unwrap() } @@ -233,14 +277,38 @@ where self.rb.m0ar.read().m0a().bits().into() } + /// **Note** (for disabled and enabled streams): + /// This config value has no meaning, if `buffer_mode` is `Regular`. + /// + /// This invariant is covered in `effective_m1a` (defined for disabled and enabled streams). pub fn m1a(&self) -> M1a { self.rb.m1ar.read().m1a().bits().into() } + pub fn effective_m1a(&self) -> Option { + if self.buffer_mode() == BufferMode::Regular { + None + } else { + Some(self.m1a()) + } + } + + /// **Note** (for disabled and enabled streams): + /// This config value has no meaning, if `transfer_mode` is `Direct`. + /// + /// This invariant is covered in `effective_fifo_threshold` (defined for disabled and enabled streams). pub fn fifo_threshold(&self) -> FifoThreshold { self.rb.fcr.read().fth().bits().try_into().unwrap() } + pub fn effective_fifo_threshold(&self) -> Option { + if self.transfer_mode() == TransferMode::Direct { + None + } else { + Some(self.fifo_threshold()) + } + } + pub fn transfer_mode(&self) -> TransferMode { self.rb.fcr.read().dmdis().bit().into() } @@ -379,6 +447,64 @@ where .fcr .modify(|_, w| w.dmdis().bit(transfer_mode.into())); } + + pub fn effective_flow_controller(&self) -> FlowController { + if self.transfer_direction() == TransferDirection::M2M { + FlowController::Dma + } else { + self.flow_controller() + } + } + + pub fn effective_circular_mode(&self) -> CircularMode { + if self.buffer_mode() == BufferMode::DoubleBuffer { + CircularMode::Enabled + } else { + self.circular_mode() + } + } + + pub fn effective_m_size(&self) -> MSize { + if self.transfer_mode() == TransferMode::Direct { + match self.p_size() { + PSize::Byte => MSize::Byte, + PSize::HalfWord => MSize::HalfWord, + PSize::Word => MSize::Word, + } + } else { + self.m_size() + } + } + + pub fn effective_pincos(&self) -> Option { + if self.pinc() == Pinc::Fixed { + return None; + } + + if self.transfer_mode() == TransferMode::Direct + || self.p_burst() != PBurst::Single + { + Some(Pincos::PSize) + } else { + Some(self.pincos()) + } + } + + pub fn effective_p_burst(&self) -> PBurst { + if self.transfer_mode() == TransferMode::Direct { + PBurst::Single + } else { + self.p_burst() + } + } + + pub fn effective_m_burst(&self) -> MBurst { + if self.transfer_mode() == TransferMode::Direct { + MBurst::Single + } else { + self.m_burst() + } + } } impl Stream @@ -557,6 +683,14 @@ where self.transmute() } + + pub fn effective_pincos(&self) -> Option { + if self.pinc() == Pinc::Fixed { + None + } else { + Some(self.pincos()) + } + } } impl Stream @@ -1145,4 +1279,61 @@ where { } -pub struct SafeTransfer {} +pub struct SafeTransfer<'wo, Source, Dest, State> +where + Source: BufferType, + Dest: BufferType, + State: TransferState, +{ + source: ImmutableBufferStatic<'wo, Source>, + dest: MutableBufferStatic<'wo, Dest>, + state: State, +} + +impl<'wo, Source, Dest> SafeTransfer<'wo, Source, Dest, Start> +where + Source: BufferType, + Dest: BufferType, +{ + pub fn new( + source: ImmutableBufferStatic<'wo, Source>, + dest: MutableBufferStatic<'wo, Dest>, + ) -> Self { + SafeTransfer { + source, + dest, + state: Start, + } + } + + pub fn start(self, stream: Stream) + where + CXX: ChannelId, + DMA: DMATrait, + { + } +} + +/// Safe Transfer with Double Buffer as Source +pub struct SafeTransferDoubleBufferR<'wo, Source, Dest, State> +where + Source: BufferType, + Dest: BufferType, + State: TransferState, +{ + sources: [ImmutableBufferStatic<'wo, Source>; 2], + dest: MutableBufferStatic<'wo, Dest>, + state: State, +} + +/// Safe Transfer with Double Buffer as Destination +pub struct SafeTransferDoubleBufferW<'wo, Source, Dest, State> +where + Source: BufferType, + Dest: BufferType, + State: TransferState, +{ + source: ImmutableBufferStatic<'wo, Source>, + dests: [MutableBufferStatic<'wo, Dest>; 2], + state: State, +} diff --git a/src/dma/safe_transfer.rs b/src/dma/safe_transfer.rs index 0ae12e97..096e1d2d 100644 --- a/src/dma/safe_transfer.rs +++ b/src/dma/safe_transfer.rs @@ -1,14 +1,43 @@ -use super::stream::{MSize, PSize}; +use super::channel::ChannelId; +use super::stream::{ + Disabled, Enabled, IsrCleared, IsrUncleared, M0a, MSize, Minc, Ndt, PSize, + Pa, Pinc, Pincos, TransferDirection, +}; +use super::{DMATrait, Stream}; +use core::convert::TryFrom; use core::convert::TryInto; use core::fmt::Debug; use core::marker::PhantomData; use core::{mem, ptr}; use vcell::VolatileCell; +pub unsafe trait TransferState {} + +pub struct Start; +unsafe impl TransferState for Start {} + +pub struct Ongoing +where + CXX: ChannelId, + DMA: DMATrait, +{ + pub(super) stream: Stream, +} + +unsafe impl TransferState for Ongoing +where + CXX: ChannelId, + DMA: DMATrait, +{ +} + /// # Safety /// /// * `Self` must be valid for any bit representation -pub unsafe trait BufferType: Sized + Clone + Copy + Sync {} +pub unsafe trait BufferType: + Sized + Clone + Copy + Sync + 'static +{ +} // Maps BufferTypeSize to number of bytes int_enum! { @@ -64,10 +93,10 @@ impl BufferTypeSize { where BUF: BufferType, { - let size_bytes = mem::size_of::(); + let size_bytes: usize = mem::size_of::(); size_bytes.try_into().unwrap_or_else(|_| { - panic!("The Size of the Buffer type must be either 1, 2 or 4 bytes") + panic!("The size of the buffer type must be either 1, 2 or 4 bytes") }) } } @@ -86,6 +115,7 @@ unsafe impl BufferType for i32 {} unsafe impl BufferType for f32 {} +#[derive(Clone, Copy)] pub enum ImmutableBuffer<'buf, 'wo, BUF> where BUF: BufferType, @@ -179,7 +209,11 @@ where } } - pub fn as_immutable(&self) -> ImmutableBuffer { + /// # Safety + /// + /// `ImmutableBuffer` assumes that the DMA is only reading the buffer. + /// Therefore the getters of the immutable version are as unsafe as the getters of this struct. + pub unsafe fn as_immutable(&self) -> ImmutableBuffer { match self { MutableBuffer::Memory(buffer) => { ImmutableBuffer::Memory(buffer.as_immutable()) @@ -193,6 +227,7 @@ where pub type MutableBufferStatic<'wo, BUF> = MutableBuffer<'static, 'wo, BUF>; +#[derive(Clone, Copy)] pub enum MemoryBuffer<'buf, BUF> where BUF: BufferType, @@ -286,7 +321,11 @@ where } } - pub fn as_immutable(&self) -> MemoryBuffer { + /// # Safety + /// + /// `MemoryBuffer` assumes that the DMA is only reading the buffer. + /// Therefore the getters of the immutable version are as unsafe as the getters of this struct. + pub unsafe fn as_immutable(&self) -> MemoryBuffer { match self { MemoryBufferMut::Fixed(buffer) => { MemoryBuffer::Fixed(buffer.as_immutable()) @@ -300,6 +339,7 @@ where pub type MemoryBufferMutStatic = MemoryBufferMut<'static, BUF>; +#[derive(Clone, Copy)] pub enum PeripheralBuffer<'buf, 'wo, BUF> where BUF: BufferType, @@ -393,7 +433,11 @@ where } } - pub fn as_immutable(&self) -> PeripheralBuffer { + /// # Safety + /// + /// `PeripheralBuffer` assumes that the DMA is only reading the buffer. + /// Therefore the getters of the immutable version are as unsafe as the getters of this struct. + pub unsafe fn as_immutable(&self) -> PeripheralBuffer { match self { PeripheralBufferMut::Fixed(buffer) => { PeripheralBuffer::Fixed(buffer.as_immutable()) @@ -408,6 +452,7 @@ where pub type PeripheralBufferMutStatic<'wo, BUF> = PeripheralBufferMut<'static, 'wo, BUF>; +#[derive(Clone, Copy)] pub enum IncrementedBuffer<'buf, 'wo, BUF> where BUF: BufferType, @@ -435,6 +480,13 @@ where panic!("The buffer has regular offset."); } } + + pub fn len(self) -> usize { + match self { + IncrementedBuffer::RegularOffset(buffer) => buffer.len(), + IncrementedBuffer::WordOffset(buffer) => buffer.len(), + } + } } pub type IncrementedBufferStatic<'wo, BUF> = @@ -504,7 +556,18 @@ where } } - pub fn as_immutable(&self) -> IncrementedBuffer { + pub fn len(&self) -> usize { + match self { + IncrementedBufferMut::RegularOffset(buffer) => buffer.len(), + IncrementedBufferMut::WordOffset(buffer) => buffer.len(), + } + } + + /// # Safety + /// + /// `IncrementedBuffer` assumes that the DMA is only reading the buffer. + /// Therefore the getters of the immutable version are as unsafe as the getters of this struct. + pub unsafe fn as_immutable(&self) -> IncrementedBuffer { match self { IncrementedBufferMut::RegularOffset(buffer) => { IncrementedBuffer::RegularOffset(buffer.as_immutable()) @@ -519,7 +582,7 @@ where pub type IncrementedBufferMutStatic<'wo, BUF> = IncrementedBufferMut<'static, 'wo, BUF>; -#[derive(Debug, PartialEq, Eq, Clone, Copy)] +#[derive(Clone, Copy)] pub struct FixedBuffer<'buf, BUF>(*const BUF, PhantomData<&'buf BUF>) where BUF: BufferType; @@ -547,7 +610,6 @@ unsafe impl<'buf, BUF> Sync for FixedBuffer<'buf, BUF> where BUF: BufferType {} pub type FixedBufferStatic = FixedBuffer<'static, BUF>; -#[derive(Debug, PartialEq, Eq)] pub struct FixedBufferMut<'buf, BUF>(*mut BUF, PhantomData<&'buf mut BUF>) where BUF: BufferType; @@ -582,7 +644,11 @@ where self.0 } - pub fn as_immutable(&self) -> FixedBuffer { + /// # Safety + /// + /// `FixedBuffer` assumes that the DMA is only reading the buffer. + /// Therefore the getters of the immutable version are as unsafe as the getters of this struct. + pub unsafe fn as_immutable(&self) -> FixedBuffer { FixedBuffer(self.0, PhantomData) } } @@ -593,7 +659,7 @@ unsafe impl<'buf, BUF> Sync for FixedBufferMut<'buf, BUF> where BUF: BufferType pub type FixedBufferMutStatic = FixedBufferMut<'static, BUF>; -#[derive(Debug, PartialEq, Eq, Clone, Copy)] +#[derive(Clone, Copy)] pub struct RegularOffsetBuffer<'buf, BUF>(*const [BUF], PhantomData<&'buf BUF>) where BUF: BufferType; @@ -616,6 +682,13 @@ where &slice[index] as *const _ } } + + pub fn len(self) -> usize { + unsafe { + let slice = &*self.0; + slice.len() + } + } } unsafe impl<'buf, BUF> Send for RegularOffsetBuffer<'buf, BUF> where @@ -630,7 +703,6 @@ unsafe impl<'buf, BUF> Sync for RegularOffsetBuffer<'buf, BUF> where pub type RegularOffsetBufferStatic = RegularOffsetBuffer<'static, BUF>; -#[derive(Debug, PartialEq, Eq)] pub struct RegularOffsetBufferMut<'buf, BUF>( *mut [BUF], PhantomData<&'buf mut BUF>, @@ -675,7 +747,18 @@ where } } - pub fn as_immutable(&self) -> RegularOffsetBuffer { + pub fn len(&self) -> usize { + unsafe { + let slice = &*self.0; + slice.len() + } + } + + /// # Safety + /// + /// `RegularOffsetBuffer` assumes that the DMA is only reading the buffer. + /// Therefore the getters of the immutable version are as unsafe as the getters of this struct. + pub unsafe fn as_immutable(&self) -> RegularOffsetBuffer { RegularOffsetBuffer(self.0, PhantomData) } } @@ -704,7 +787,7 @@ where ptr::read_volatile(&slice[index] as *const _) } -#[derive(Debug, PartialEq, Eq, Clone, Copy)] +#[derive(Clone, Copy)] pub struct WordOffsetBuffer<'buf, 'wo, BUF>( &'wo [*const BUF], PhantomData<&'buf BUF>, @@ -731,6 +814,10 @@ where pub fn as_ptr(self, index: usize) -> *const BUF { self.0[index] } + + pub fn len(self) -> usize { + self.0.len() + } } unsafe impl<'buf, 'wo, BUF> Send for WordOffsetBuffer<'buf, 'wo, BUF> where @@ -785,10 +872,16 @@ where self.0[index].as_ptr() } - pub fn as_immutable(&self) -> WordOffsetBuffer { - unsafe { - WordOffsetBuffer(&*(self.0 as *const _ as *const _), PhantomData) - } + pub fn len(&self) -> usize { + self.0.len() + } + + /// # Safety + /// + /// `WordOffsetBuffer` assumes that the DMA is only reading the buffer. + /// Therefore the getters of the immutable version are as unsafe as the getters of this struct. + pub unsafe fn as_immutable(&self) -> WordOffsetBuffer { + WordOffsetBuffer(&*(self.0 as *const _ as *const _), PhantomData) } } @@ -800,6 +893,10 @@ unsafe impl<'buf, 'wo, BUF> Sync for WordOffsetBufferMut<'buf, 'wo, BUF> where pub type WordOffsetBufferMutStatic<'wo, BUF> = WordOffsetBufferMut<'static, 'wo, BUF>; +// +// Secure Transfer implementations +// + fn check_word_offset(buffer: &[*const BUF]) where BUF: BufferType, @@ -821,3 +918,118 @@ where last_pointer = current_pointer; } } + +/// Configures the buffers of the transfer. +/// +/// **Note**: Configures the following values: +/// - `Pa`, `M0a` +/// - `Pinc`, `Minc` +/// - `Pincos` +/// - `Ndt` +pub(super) fn configure_safe_transfer( + stream: &mut Stream, + source: ImmutableBuffer, + dest: MutableBuffer, +) where + CXX: ChannelId, + DMA: DMATrait, + Source: BufferType, + Dest: BufferType, +{ + // Note(safety): Safe as the transfer has not started yet. + let dest = unsafe { dest.as_immutable() }; + match stream.transfer_direction() { + TransferDirection::P2M => { + configure_buffers(stream, source.peripheral(), dest.memory()); + } + TransferDirection::M2P => { + configure_buffers(stream, dest.peripheral(), source.memory()); + } + TransferDirection::M2M => { + configure_buffers(stream, source.peripheral(), dest.memory()); + } + } +} + +fn configure_buffers( + stream: &mut Stream, + peripheral: PeripheralBuffer, + memory: MemoryBuffer, +) where + CXX: ChannelId, + DMA: DMATrait, + Peripheral: BufferType, + Memory: BufferType, +{ + match peripheral { + PeripheralBuffer::Fixed(buffer) => { + stream.set_pa(Pa(buffer.as_ptr() as u32)); + stream.set_pinc(Pinc::Fixed); + } + PeripheralBuffer::Incremented(buffer) => match buffer { + IncrementedBuffer::RegularOffset(buffer) => { + stream.set_pa(Pa(buffer.as_ptr(0) as u32)); + stream.set_pinc(Pinc::Incremented); + stream.set_pincos(Pincos::PSize); + } + IncrementedBuffer::WordOffset(buffer) => { + stream.set_pa(Pa(buffer.as_ptr(0) as u32)); + stream.set_pinc(Pinc::Incremented); + stream.set_pincos(Pincos::Word); + } + }, + } + + match memory { + MemoryBuffer::Fixed(buffer) => { + stream.set_m0a(M0a(buffer.as_ptr() as u32)); + stream.set_minc(Minc::Fixed); + } + MemoryBuffer::Incremented(buffer) => { + stream.set_m0a(M0a(buffer.as_ptr(0) as u32)); + stream.set_minc(Minc::Incremented); + } + } + + configure_ndt(stream, peripheral, memory); +} + +fn configure_ndt( + stream: &mut Stream, + peripheral: PeripheralBuffer, + memory: MemoryBuffer, +) where + CXX: ChannelId, + DMA: DMATrait, + Peripheral: BufferType, + Memory: BufferType, +{ + match peripheral { + PeripheralBuffer::Fixed(_) => { + match memory { + MemoryBuffer::Fixed(_) => { + // NDT must be configured in advance + } + MemoryBuffer::Incremented(buffer) => { + let p_size: usize = + BufferTypeSize::from_buffer_type::().into(); + let m_size: usize = + BufferTypeSize::from_buffer_type::().into(); + + let memory_bytes = buffer.len() * m_size; + + if memory_bytes % p_size != 0 { + panic!("Last transfer may be incomplete."); + } + + let ndt = u16::try_from(memory_bytes / p_size).unwrap(); + stream.set_ndt(ndt.into()); + } + } + } + PeripheralBuffer::Incremented(buffer) => { + let ndt = u16::try_from(buffer.len()).unwrap(); + stream.set_ndt(Ndt(ndt)); + } + } +} From 774a413a53140cf8fb4102f7ad91aaf20a3c0504 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ad=C3=A4?= Date: Wed, 18 Dec 2019 19:30:49 +0100 Subject: [PATCH 028/103] Configuring m_size and p_size now --- src/dma/safe_transfer.rs | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/dma/safe_transfer.rs b/src/dma/safe_transfer.rs index 096e1d2d..209e06a3 100644 --- a/src/dma/safe_transfer.rs +++ b/src/dma/safe_transfer.rs @@ -461,6 +461,7 @@ where WordOffset(WordOffsetBuffer<'buf, 'wo, BUF>), } +#[allow(clippy::len_without_is_empty)] impl<'buf, 'wo, BUF> IncrementedBuffer<'buf, 'wo, BUF> where BUF: BufferType, @@ -500,6 +501,7 @@ where WordOffset(WordOffsetBufferMut<'buf, 'wo, BUF>), } +#[allow(clippy::len_without_is_empty)] impl<'buf, 'wo, BUF> IncrementedBufferMut<'buf, 'wo, BUF> where BUF: BufferType, @@ -664,11 +666,14 @@ pub struct RegularOffsetBuffer<'buf, BUF>(*const [BUF], PhantomData<&'buf BUF>) where BUF: BufferType; +#[allow(clippy::len_without_is_empty)] impl<'buf, BUF> RegularOffsetBuffer<'buf, BUF> where BUF: BufferType, { pub fn new(buffer: &'buf [BUF]) -> Self { + check_buffer_not_empty(buffer); + RegularOffsetBuffer(buffer, PhantomData) } @@ -710,11 +715,14 @@ pub struct RegularOffsetBufferMut<'buf, BUF>( where BUF: BufferType; +#[allow(clippy::len_without_is_empty)] impl<'buf, BUF> RegularOffsetBufferMut<'buf, BUF> where BUF: BufferType, { pub fn new(buffer: &'buf mut [BUF]) -> Self { + check_buffer_not_empty(buffer); + RegularOffsetBufferMut(buffer, PhantomData) } @@ -795,11 +803,14 @@ pub struct WordOffsetBuffer<'buf, 'wo, BUF>( where BUF: BufferType; +#[allow(clippy::len_without_is_empty)] impl<'buf, 'wo, BUF> WordOffsetBuffer<'buf, 'wo, BUF> where BUF: BufferType, { pub fn new(buffer: &'wo [&'buf BUF]) -> Self { + check_buffer_not_empty(buffer); + let buffer = unsafe { &*(buffer as *const _ as *const _) }; check_word_offset(buffer); @@ -838,11 +849,14 @@ pub struct WordOffsetBufferMut<'buf, 'wo, BUF>( where BUF: BufferType; +#[allow(clippy::len_without_is_empty)] impl<'buf, 'wo, BUF> WordOffsetBufferMut<'buf, 'wo, BUF> where BUF: BufferType, { pub fn new(buffer: &'wo [&'buf mut BUF]) -> Self { + check_buffer_not_empty(buffer); + unsafe { check_word_offset::(&*(buffer as *const _ as *const _)); @@ -893,6 +907,12 @@ unsafe impl<'buf, 'wo, BUF> Sync for WordOffsetBufferMut<'buf, 'wo, BUF> where pub type WordOffsetBufferMutStatic<'wo, BUF> = WordOffsetBufferMut<'static, 'wo, BUF>; +fn check_buffer_not_empty(buffer: &[T]) { + if buffer.is_empty() { + panic!("The buffer must not be empty."); + } +} + // // Secure Transfer implementations // @@ -922,6 +942,8 @@ where /// Configures the buffers of the transfer. /// /// **Note**: Configures the following values: +/// +/// - `PSize`, `Msize` /// - `Pa`, `M0a` /// - `Pinc`, `Minc` /// - `Pincos` @@ -961,6 +983,9 @@ fn configure_buffers( Peripheral: BufferType, Memory: BufferType, { + stream.set_p_size(BufferTypeSize::from_buffer_type::().into()); + stream.set_m_size(BufferTypeSize::from_buffer_type::().into()); + match peripheral { PeripheralBuffer::Fixed(buffer) => { stream.set_pa(Pa(buffer.as_ptr() as u32)); From f5e69aa849e40acc1e2ed550c5118a78e8c15930 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ad=C3=A4?= Date: Thu, 19 Dec 2019 00:22:05 +0100 Subject: [PATCH 029/103] Implemented secure transfer --- src/dma.rs | 255 +++++++++++++++++++++++++++++++++++++-- src/dma/safe_transfer.rs | 59 +++++++-- 2 files changed, 295 insertions(+), 19 deletions(-) diff --git a/src/dma.rs b/src/dma.rs index 4ec6d8ee..eded6b55 100644 --- a/src/dma.rs +++ b/src/dma.rs @@ -18,8 +18,10 @@ use self::mux::{ SyncOverrunInterrupt, SyncPolarity, }; use self::safe_transfer::{ - BufferType, ImmutableBufferStatic, MutableBufferStatic, Ongoing, Start, - TransferState, + check_double_buffer, configure_safe_transfer, BufferType, ImmutableBuffer, + ImmutableBufferStatic, MemoryBufferMutStatic, MemoryBufferStatic, + MutableBuffer, MutableBufferStatic, Ongoing, PeripheralBufferMutStatic, + PeripheralBufferStatic, Start, TransferState, }; use self::stm32::dma1::ST; use self::stm32::dmamux1::CCR; @@ -1305,12 +1307,66 @@ where state: Start, } } +} + +impl<'wo, Source, Dest, State> SafeTransfer<'wo, Source, Dest, State> +where + Source: BufferType, + Dest: BufferType, + State: TransferState, +{ + pub fn source(&self) -> ImmutableBufferStatic<'wo, Source> { + self.source + } + + pub fn dest(&self) -> &MutableBufferStatic<'wo, Dest> { + &self.dest + } - pub fn start(self, stream: Stream) + pub fn dest_mut(&mut self) -> &mut MutableBufferStatic<'wo, Dest> { + &mut self.dest + } +} + +impl<'wo, Source, Dest> SafeTransfer<'wo, Source, Dest, Start> +where + Source: BufferType, + Dest: BufferType, +{ + pub fn start( + self, + mut stream: Stream, + ) -> SafeTransfer<'wo, Source, Dest, Ongoing> where CXX: ChannelId, DMA: DMATrait, { + configure_safe_transfer(&mut stream, self.source, &self.dest); + stream.set_buffer_mode(BufferMode::Regular); + + SafeTransfer { + source: self.source, + dest: self.dest, + state: Ongoing { + stream: unsafe { stream.enable() }, + }, + } + } +} + +impl SafeTransfer<'_, Source, Dest, Ongoing> +where + Source: BufferType, + Dest: BufferType, + CXX: ChannelId, + DMA: DMATrait, +{ + pub fn stream(&self) -> &Stream { + &self.state.stream + } + + pub fn stop(self) -> Stream { + self.state.stream.disable().await_disabled() } } @@ -1321,11 +1377,101 @@ where Dest: BufferType, State: TransferState, { - sources: [ImmutableBufferStatic<'wo, Source>; 2], - dest: MutableBufferStatic<'wo, Dest>, + sources: [MemoryBufferStatic; 2], + dest: PeripheralBufferMutStatic<'wo, Dest>, state: State, } +impl<'wo, Source, Dest> SafeTransferDoubleBufferR<'wo, Source, Dest, Start> +where + Source: BufferType, + Dest: BufferType, +{ + pub fn new( + sources: [MemoryBufferStatic; 2], + dest: PeripheralBufferMutStatic<'wo, Dest>, + ) -> Self { + check_double_buffer(sources); + + SafeTransferDoubleBufferR { + sources, + dest, + state: Start, + } + } +} + +impl<'wo, Source, Dest, State> + SafeTransferDoubleBufferR<'wo, Source, Dest, State> +where + Source: BufferType, + Dest: BufferType, + State: TransferState, +{ + pub fn sources(&self) -> [MemoryBufferStatic; 2] { + self.sources + } + + pub fn dest(&self) -> &PeripheralBufferMutStatic<'wo, Dest> { + &self.dest + } + + pub fn dest_mut(&mut self) -> &mut PeripheralBufferMutStatic<'wo, Dest> { + &mut self.dest + } +} + +impl<'wo, Source, Dest> SafeTransferDoubleBufferR<'wo, Source, Dest, Start> +where + Source: BufferType, + Dest: BufferType, +{ + pub fn start( + self, + mut stream: Stream, + ) -> SafeTransferDoubleBufferR<'wo, Source, Dest, Ongoing> + where + CXX: ChannelId, + DMA: DMATrait, + { + let dest_buffer = MutableBuffer::Peripheral(self.dest); + + configure_safe_transfer( + &mut stream, + ImmutableBuffer::Memory(self.sources[0]), + &dest_buffer, + ); + stream.set_buffer_mode(BufferMode::DoubleBuffer); + + let dest_buffer = dest_buffer.into_peripheral(); + + SafeTransferDoubleBufferR { + sources: self.sources, + dest: dest_buffer, + state: Ongoing { + stream: unsafe { stream.enable() }, + }, + } + } +} + +impl + SafeTransferDoubleBufferR<'_, Source, Dest, Ongoing> +where + Source: BufferType, + Dest: BufferType, + CXX: ChannelId, + DMA: DMATrait, +{ + pub fn stream(&self) -> &Stream { + &self.state.stream + } + + pub fn stop(self) -> Stream { + self.state.stream.disable().await_disabled() + } +} + /// Safe Transfer with Double Buffer as Destination pub struct SafeTransferDoubleBufferW<'wo, Source, Dest, State> where @@ -1333,7 +1479,102 @@ where Dest: BufferType, State: TransferState, { - source: ImmutableBufferStatic<'wo, Source>, - dests: [MutableBufferStatic<'wo, Dest>; 2], + source: PeripheralBufferStatic<'wo, Source>, + dests: [MemoryBufferMutStatic; 2], state: State, } + +impl<'wo, Source, Dest> SafeTransferDoubleBufferW<'wo, Source, Dest, Start> +where + Source: BufferType, + Dest: BufferType, +{ + pub fn new( + source: PeripheralBufferStatic<'wo, Source>, + dests: [MemoryBufferMutStatic; 2], + ) -> Self { + let [ref buffer_0, ref buffer_1] = dests; + let double_buffer_immutable = + unsafe { [buffer_0.as_immutable(), buffer_1.as_immutable()] }; + + check_double_buffer(double_buffer_immutable); + + SafeTransferDoubleBufferW { + source, + dests, + state: Start, + } + } +} + +impl<'wo, Source, Dest, State> + SafeTransferDoubleBufferW<'wo, Source, Dest, State> +where + Source: BufferType, + Dest: BufferType, + State: TransferState, +{ + pub fn source(&self) -> PeripheralBufferStatic<'wo, Source> { + self.source + } + + pub fn dest(&self) -> &[MemoryBufferMutStatic; 2] { + &self.dests + } + + pub fn dest_mut(&mut self) -> &mut [MemoryBufferMutStatic; 2] { + &mut self.dests + } +} + +impl<'wo, Source, Dest> SafeTransferDoubleBufferW<'wo, Source, Dest, Start> +where + Source: BufferType, + Dest: BufferType, +{ + pub fn start( + self, + mut stream: Stream, + ) -> SafeTransferDoubleBufferW<'wo, Source, Dest, Ongoing> + where + CXX: ChannelId, + DMA: DMATrait, + { + let [dest_buffer_0, dest_buffer_1] = self.dests; + let dest_buffer_0 = MutableBuffer::Memory(dest_buffer_0); + + configure_safe_transfer( + &mut stream, + ImmutableBuffer::Peripheral(self.source), + &dest_buffer_0, + ); + stream.set_buffer_mode(BufferMode::DoubleBuffer); + + let dest_buffer_0 = dest_buffer_0.into_memory(); + + SafeTransferDoubleBufferW { + source: self.source, + dests: [dest_buffer_0, dest_buffer_1], + state: Ongoing { + stream: unsafe { stream.enable() }, + }, + } + } +} + +impl + SafeTransferDoubleBufferW<'_, Source, Dest, Ongoing> +where + Source: BufferType, + Dest: BufferType, + CXX: ChannelId, + DMA: DMATrait, +{ + pub fn stream(&self) -> &Stream { + &self.state.stream + } + + pub fn stop(self) -> Stream { + self.state.stream.disable().await_disabled() + } +} diff --git a/src/dma/safe_transfer.rs b/src/dma/safe_transfer.rs index 209e06a3..2b1a89c2 100644 --- a/src/dma/safe_transfer.rs +++ b/src/dma/safe_transfer.rs @@ -1,7 +1,7 @@ use super::channel::ChannelId; use super::stream::{ Disabled, Enabled, IsrCleared, IsrUncleared, M0a, MSize, Minc, Ndt, PSize, - Pa, Pinc, Pincos, TransferDirection, + Pa, Pinc, Pincos, TransferDirection, TransferMode, }; use super::{DMATrait, Stream}; use core::convert::TryFrom; @@ -9,7 +9,6 @@ use core::convert::TryInto; use core::fmt::Debug; use core::marker::PhantomData; use core::{mem, ptr}; -use vcell::VolatileCell; pub unsafe trait TransferState {} @@ -844,7 +843,8 @@ unsafe impl<'buf, 'wo, BUF> Sync for WordOffsetBuffer<'buf, 'wo, BUF> where pub type WordOffsetBufferStatic<'wo, BUF> = WordOffsetBuffer<'static, 'wo, BUF>; pub struct WordOffsetBufferMut<'buf, 'wo, BUF>( - &'wo [&'buf mut VolatileCell], + &'wo mut [*mut BUF], + PhantomData<&'buf mut BUF>, ) where BUF: BufferType; @@ -854,13 +854,13 @@ impl<'buf, 'wo, BUF> WordOffsetBufferMut<'buf, 'wo, BUF> where BUF: BufferType, { - pub fn new(buffer: &'wo [&'buf mut BUF]) -> Self { + pub fn new(buffer: &'wo mut [&'buf mut BUF]) -> Self { check_buffer_not_empty(buffer); unsafe { check_word_offset::(&*(buffer as *const _ as *const _)); - WordOffsetBufferMut(&*(buffer as *const _ as *const _)) + WordOffsetBufferMut(&mut *(buffer as *mut _ as *mut _), PhantomData) } } @@ -868,22 +868,22 @@ where /// /// - The caller must ensure, that the DMA is currently not modifying this address. pub unsafe fn get(&self, index: usize) -> BUF { - self.0[index].get() + ptr::read_volatile(self.0[index]) } /// # Safety /// /// - The caller must ensure, that the DMA is currently not modifying this address. pub unsafe fn set(&mut self, index: usize, item: BUF) { - self.0[index].set(item); + ptr::write_volatile(self.0[index], item); } pub fn as_ptr(&self, index: usize) -> *const BUF { - self.0[index].as_ptr() + self.0[index] } pub fn as_mut_ptr(&mut self, index: usize) -> *mut BUF { - self.0[index].as_ptr() + self.0[index] } pub fn len(&self) -> usize { @@ -951,7 +951,7 @@ where pub(super) fn configure_safe_transfer( stream: &mut Stream, source: ImmutableBuffer, - dest: MutableBuffer, + dest: &MutableBuffer, ) where CXX: ChannelId, DMA: DMATrait, @@ -983,8 +983,15 @@ fn configure_buffers( Peripheral: BufferType, Memory: BufferType, { - stream.set_p_size(BufferTypeSize::from_buffer_type::().into()); - stream.set_m_size(BufferTypeSize::from_buffer_type::().into()); + let p_size = BufferTypeSize::from_buffer_type::(); + let m_size = BufferTypeSize::from_buffer_type::(); + + if stream.transfer_mode() == TransferMode::Direct && p_size != m_size { + panic!("The buffer sizes must match if the stream is configured in direct mode."); + } + + stream.set_p_size(p_size.into()); + stream.set_m_size(m_size.into()); match peripheral { PeripheralBuffer::Fixed(buffer) => { @@ -1058,3 +1065,31 @@ fn configure_ndt( } } } + +pub(super) fn check_double_buffer(double_buffer: [MemoryBuffer; 2]) +where + BUF: BufferType, +{ + match double_buffer[0] { + MemoryBuffer::Fixed(_) => { + if let MemoryBuffer::Incremented(_) = double_buffer[1] { + panic!("Invalid double buffer config: First buffer `Fixed`, second buffer `Incremented`."); + } + } + MemoryBuffer::Incremented(buffer_0) => { + if let MemoryBuffer::Fixed(_) = double_buffer[1] { + panic!("Invalid double buffer config: First buffer `Incremented`, second buffer `Fixed`."); + } + + let len_0 = buffer_0.len(); + let len_1 = double_buffer[1].incremented().len(); + + if len_0 != len_1 { + panic!( + "Invalid double buffer config: len_0 ({}) != len_1({})", + len_0, len_1 + ); + } + } + } +} From af64d65c80a5dc8e6fe135f3ad61fe53a2c15aa6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ad=C3=A4?= Date: Fri, 20 Dec 2019 17:04:30 +0100 Subject: [PATCH 030/103] Improved safe transfer safety --- src/dma.rs | 271 ++++++++++++++++++++++++++++++++------- src/dma/safe_transfer.rs | 264 ++++++++++++++++++++++++-------------- 2 files changed, 395 insertions(+), 140 deletions(-) diff --git a/src/dma.rs b/src/dma.rs index eded6b55..16fca1fb 100644 --- a/src/dma.rs +++ b/src/dma.rs @@ -18,10 +18,11 @@ use self::mux::{ SyncOverrunInterrupt, SyncPolarity, }; use self::safe_transfer::{ - check_double_buffer, configure_safe_transfer, BufferType, ImmutableBuffer, - ImmutableBufferStatic, MemoryBufferMutStatic, MemoryBufferStatic, - MutableBuffer, MutableBufferStatic, Ongoing, PeripheralBufferMutStatic, - PeripheralBufferStatic, Start, TransferState, + check_double_buffer, check_double_buffer_mut, configure_safe_transfer, + double_buffer_idx, DoubleBuffer, ImmutableBuffer, ImmutableBufferStatic, + MemoryBuffer, MemoryBufferMut, MemoryBufferMutStatic, MemoryBufferStatic, + MutableBuffer, MutableBufferStatic, Ongoing, Payload, + PeripheralBufferMutStatic, PeripheralBufferStatic, Start, TransferState, }; use self::stm32::dma1::ST; use self::stm32::dmamux1::CCR; @@ -35,9 +36,10 @@ use self::stream::{ StreamIsr, TransferCompleteInterrupt, TransferDirection, TransferErrorInterrupt, TransferMode, ED as EDTrait, }; -use crate::nb::{self, Error as NbError}; +use crate::nb::{self, block, Error as NbError}; use core::convert::{Infallible, TryFrom, TryInto}; use core::marker::PhantomData; +use core::mem; use stm32h7::stm32h743 as stm32; pub unsafe trait DMATrait {} @@ -1283,8 +1285,8 @@ where pub struct SafeTransfer<'wo, Source, Dest, State> where - Source: BufferType, - Dest: BufferType, + Source: Payload, + Dest: Payload, State: TransferState, { source: ImmutableBufferStatic<'wo, Source>, @@ -1294,8 +1296,8 @@ where impl<'wo, Source, Dest> SafeTransfer<'wo, Source, Dest, Start> where - Source: BufferType, - Dest: BufferType, + Source: Payload, + Dest: Payload, { pub fn new( source: ImmutableBufferStatic<'wo, Source>, @@ -1311,8 +1313,8 @@ where impl<'wo, Source, Dest, State> SafeTransfer<'wo, Source, Dest, State> where - Source: BufferType, - Dest: BufferType, + Source: Payload, + Dest: Payload, State: TransferState, { pub fn source(&self) -> ImmutableBufferStatic<'wo, Source> { @@ -1323,15 +1325,59 @@ where &self.dest } - pub fn dest_mut(&mut self) -> &mut MutableBufferStatic<'wo, Dest> { - &mut self.dest + /// # Safety + /// + /// The caller must ensure, that the DMA is currently not modifying this address. + pub unsafe fn set_dest_fixed(&mut self, payload: Dest) { + match &mut self.dest { + MutableBuffer::Peripheral(buffer) => { + buffer.as_mut_fixed().set(payload); + } + MutableBuffer::Memory(buffer) => { + buffer.as_mut_fixed().set(payload); + } + } + } + + /// # Safety + /// + /// The caller must ensure, that the DMA is currently not modifying this address. + pub unsafe fn set_dest_incremented(&mut self, index: usize, payload: Dest) { + match &mut self.dest { + MutableBuffer::Peripheral(buffer) => { + buffer.as_mut_incremented().set(index, payload); + } + MutableBuffer::Memory(buffer) => { + buffer.as_mut_incremented().set(index, payload); + } + } + } + + pub fn dest_ptr_fixed(&mut self) -> *mut Dest { + match &mut self.dest { + MutableBuffer::Peripheral(buffer) => { + buffer.as_mut_fixed().as_mut_ptr() + } + MutableBuffer::Memory(buffer) => buffer.as_mut_fixed().as_mut_ptr(), + } + } + + pub fn dest_ptr_incremented(&mut self, index: usize) -> *mut Dest { + match &mut self.dest { + MutableBuffer::Peripheral(buffer) => { + buffer.as_mut_incremented().as_mut_ptr(index) + } + MutableBuffer::Memory(buffer) => { + buffer.as_mut_incremented().as_mut_ptr(index) + } + } } } impl<'wo, Source, Dest> SafeTransfer<'wo, Source, Dest, Start> where - Source: BufferType, - Dest: BufferType, + Source: Payload, + Dest: Payload, { pub fn start( self, @@ -1356,8 +1402,8 @@ where impl SafeTransfer<'_, Source, Dest, Ongoing> where - Source: BufferType, - Dest: BufferType, + Source: Payload, + Dest: Payload, CXX: ChannelId, DMA: DMATrait, { @@ -1373,8 +1419,8 @@ where /// Safe Transfer with Double Buffer as Source pub struct SafeTransferDoubleBufferR<'wo, Source, Dest, State> where - Source: BufferType, - Dest: BufferType, + Source: Payload, + Dest: Payload, State: TransferState, { sources: [MemoryBufferStatic; 2], @@ -1384,8 +1430,8 @@ where impl<'wo, Source, Dest> SafeTransferDoubleBufferR<'wo, Source, Dest, Start> where - Source: BufferType, - Dest: BufferType, + Source: Payload, + Dest: Payload, { pub fn new( sources: [MemoryBufferStatic; 2], @@ -1404,8 +1450,8 @@ where impl<'wo, Source, Dest, State> SafeTransferDoubleBufferR<'wo, Source, Dest, State> where - Source: BufferType, - Dest: BufferType, + Source: Payload, + Dest: Payload, State: TransferState, { pub fn sources(&self) -> [MemoryBufferStatic; 2] { @@ -1416,15 +1462,33 @@ where &self.dest } - pub fn dest_mut(&mut self) -> &mut PeripheralBufferMutStatic<'wo, Dest> { - &mut self.dest + /// # Safety + /// + /// The caller must ensure, that the DMA is currently not modifying this address. + pub unsafe fn set_dest_fixed(&mut self, payload: Dest) { + self.dest.as_mut_fixed().set(payload); + } + + /// # Safety + /// + /// The caller must ensure, that the DMA is currently not modifying this address. + pub unsafe fn set_dest_incremented(&mut self, index: usize, payload: Dest) { + self.dest.as_mut_incremented().set(index, payload); + } + + pub fn dest_ptr_fixed(&mut self) -> *mut Dest { + self.dest.as_mut_fixed().as_mut_ptr() + } + + pub fn dest_ptr_incremented(&mut self, index: usize) -> *mut Dest { + self.dest.as_mut_incremented().as_mut_ptr(index) } } impl<'wo, Source, Dest> SafeTransferDoubleBufferR<'wo, Source, Dest, Start> where - Source: BufferType, - Dest: BufferType, + Source: Payload, + Dest: Payload, { pub fn start( self, @@ -1458,8 +1522,8 @@ where impl SafeTransferDoubleBufferR<'_, Source, Dest, Ongoing> where - Source: BufferType, - Dest: BufferType, + Source: Payload, + Dest: Payload, CXX: ChannelId, DMA: DMATrait, { @@ -1467,6 +1531,46 @@ where &self.state.stream } + pub fn set_double_buffer( + &mut self, + buffer: MemoryBufferStatic, + double_buffer: DoubleBuffer, + ) { + let address = match buffer { + MemoryBuffer::Fixed(buffer) => { + // `self.sources[0]` and `self.sources[1]` have the same increment mode + if let MemoryBuffer::Incremented(_) = self.sources[0] { + panic!("The new buffer is fixed, but the old one is incremented."); + } + + buffer.as_ptr() as u32 + } + MemoryBuffer::Incremented(buffer) => { + // `self.sources[0]` and `self.sources[1]` have the same len + if buffer.len() != self.sources[0].incremented().len() { + panic!("The new buffer must have the same size as the old buffer."); + } + + buffer.as_ptr(0) as u32 + } + }; + + match double_buffer { + DoubleBuffer::First => { + let m0a = M0a(address); + block!(self.state.stream.set_m0a(m0a)).unwrap(); + + mem::replace(&mut self.sources[0], buffer); + } + DoubleBuffer::Second => { + let m1a = M1a(address); + block!(self.state.stream.set_m1a(m1a)).unwrap(); + + mem::replace(&mut self.sources[1], buffer); + } + } + } + pub fn stop(self) -> Stream { self.state.stream.disable().await_disabled() } @@ -1475,8 +1579,8 @@ where /// Safe Transfer with Double Buffer as Destination pub struct SafeTransferDoubleBufferW<'wo, Source, Dest, State> where - Source: BufferType, - Dest: BufferType, + Source: Payload, + Dest: Payload, State: TransferState, { source: PeripheralBufferStatic<'wo, Source>, @@ -1486,18 +1590,14 @@ where impl<'wo, Source, Dest> SafeTransferDoubleBufferW<'wo, Source, Dest, Start> where - Source: BufferType, - Dest: BufferType, + Source: Payload, + Dest: Payload, { pub fn new( source: PeripheralBufferStatic<'wo, Source>, dests: [MemoryBufferMutStatic; 2], ) -> Self { - let [ref buffer_0, ref buffer_1] = dests; - let double_buffer_immutable = - unsafe { [buffer_0.as_immutable(), buffer_1.as_immutable()] }; - - check_double_buffer(double_buffer_immutable); + check_double_buffer_mut(&dests); SafeTransferDoubleBufferW { source, @@ -1510,8 +1610,8 @@ where impl<'wo, Source, Dest, State> SafeTransferDoubleBufferW<'wo, Source, Dest, State> where - Source: BufferType, - Dest: BufferType, + Source: Payload, + Dest: Payload, State: TransferState, { pub fn source(&self) -> PeripheralBufferStatic<'wo, Source> { @@ -1522,15 +1622,54 @@ where &self.dests } - pub fn dest_mut(&mut self) -> &mut [MemoryBufferMutStatic; 2] { - &mut self.dests + /// # Safety + /// + /// The caller must ensure, that the DMA is currently not modifying this address. + pub unsafe fn set_dest_fixed( + &mut self, + payload: Dest, + buffer: DoubleBuffer, + ) { + let idx = double_buffer_idx(buffer); + + self.dests[idx].as_mut_fixed().set(payload); + } + + /// # Safety + /// + /// The caller must ensure, that the DMA is currently not modifying this address. + pub unsafe fn set_dest_incremented( + &mut self, + index: usize, + payload: Dest, + buffer: DoubleBuffer, + ) { + let idx = double_buffer_idx(buffer); + + self.dests[idx].as_mut_incremented().set(index, payload); + } + + pub fn dest_ptr_fixed(&mut self, buffer: DoubleBuffer) -> *mut Dest { + let idx = double_buffer_idx(buffer); + + self.dests[idx].as_mut_fixed().as_mut_ptr() + } + + pub fn dest_ptr_incremented( + &mut self, + index: usize, + buffer: DoubleBuffer, + ) -> *mut Dest { + let idx = double_buffer_idx(buffer); + + self.dests[idx].as_mut_incremented().as_mut_ptr(index) } } impl<'wo, Source, Dest> SafeTransferDoubleBufferW<'wo, Source, Dest, Start> where - Source: BufferType, - Dest: BufferType, + Source: Payload, + Dest: Payload, { pub fn start( self, @@ -1565,8 +1704,8 @@ where impl SafeTransferDoubleBufferW<'_, Source, Dest, Ongoing> where - Source: BufferType, - Dest: BufferType, + Source: Payload, + Dest: Payload, CXX: ChannelId, DMA: DMATrait, { @@ -1574,6 +1713,46 @@ where &self.state.stream } + pub fn set_double_buffer( + &mut self, + buffer: MemoryBufferMutStatic, + double_buffer: DoubleBuffer, + ) { + let address = match &buffer { + MemoryBufferMut::Fixed(buffer) => { + // `self.dests[0]` and `self.dests[1]` have the same increment mode + if let MemoryBufferMut::Incremented(_) = &self.dests[0] { + panic!("The new buffer is fixed, but the old one is incremented."); + } + + buffer.as_ptr() as u32 + } + MemoryBufferMut::Incremented(buffer) => { + // `self.sources[0]` and `self.sources[1]` have the same len + if buffer.len() != self.dests[0].as_incremented().len() { + panic!("The new buffer must have the same size as the old buffer."); + } + + buffer.as_ptr(0) as u32 + } + }; + + match double_buffer { + DoubleBuffer::First => { + let m0a = M0a(address); + block!(self.state.stream.set_m0a(m0a)).unwrap(); + + mem::replace(&mut self.dests[0], buffer); + } + DoubleBuffer::Second => { + let m1a = M1a(address); + block!(self.state.stream.set_m1a(m1a)).unwrap(); + + mem::replace(&mut self.dests[1], buffer); + } + } + } + pub fn stop(self) -> Stream { self.state.stream.disable().await_disabled() } diff --git a/src/dma/safe_transfer.rs b/src/dma/safe_transfer.rs index 2b1a89c2..b64b6013 100644 --- a/src/dma/safe_transfer.rs +++ b/src/dma/safe_transfer.rs @@ -33,64 +33,61 @@ where /// # Safety /// /// * `Self` must be valid for any bit representation -pub unsafe trait BufferType: - Sized + Clone + Copy + Sync + 'static -{ -} +pub unsafe trait Payload: Sized + Clone + Copy + Sync + 'static {} -// Maps BufferTypeSize to number of bytes +// Maps Payload to number of bytes int_enum! { - BufferTypeSize <=> usize, + PayloadSize <=> usize, "Buffer Size", Byte <=> 1, HalfWord <=> 2, Word <=> 4 } -impl From for MSize { - fn from(val: BufferTypeSize) -> Self { +impl From for MSize { + fn from(val: PayloadSize) -> Self { match val { - BufferTypeSize::Byte => MSize::Byte, - BufferTypeSize::HalfWord => MSize::HalfWord, - BufferTypeSize::Word => MSize::Word, + PayloadSize::Byte => MSize::Byte, + PayloadSize::HalfWord => MSize::HalfWord, + PayloadSize::Word => MSize::Word, } } } -impl From for BufferTypeSize { +impl From for PayloadSize { fn from(val: MSize) -> Self { match val { - MSize::Byte => BufferTypeSize::Byte, - MSize::HalfWord => BufferTypeSize::HalfWord, - MSize::Word => BufferTypeSize::Word, + MSize::Byte => PayloadSize::Byte, + MSize::HalfWord => PayloadSize::HalfWord, + MSize::Word => PayloadSize::Word, } } } -impl From for PSize { - fn from(val: BufferTypeSize) -> Self { +impl From for PSize { + fn from(val: PayloadSize) -> Self { match val { - BufferTypeSize::Byte => PSize::Byte, - BufferTypeSize::HalfWord => PSize::HalfWord, - BufferTypeSize::Word => PSize::Word, + PayloadSize::Byte => PSize::Byte, + PayloadSize::HalfWord => PSize::HalfWord, + PayloadSize::Word => PSize::Word, } } } -impl From for BufferTypeSize { +impl From for PayloadSize { fn from(val: PSize) -> Self { match val { - PSize::Byte => BufferTypeSize::Byte, - PSize::HalfWord => BufferTypeSize::HalfWord, - PSize::Word => BufferTypeSize::Word, + PSize::Byte => PayloadSize::Byte, + PSize::HalfWord => PayloadSize::HalfWord, + PSize::Word => PayloadSize::Word, } } } -impl BufferTypeSize { - pub fn from_buffer_type() -> Self +impl PayloadSize { + pub fn from_payload() -> Self where - BUF: BufferType, + BUF: Payload, { let size_bytes: usize = mem::size_of::(); @@ -100,24 +97,24 @@ impl BufferTypeSize { } } -unsafe impl BufferType for u8 {} +unsafe impl Payload for u8 {} -unsafe impl BufferType for i8 {} +unsafe impl Payload for i8 {} -unsafe impl BufferType for u16 {} +unsafe impl Payload for u16 {} -unsafe impl BufferType for i16 {} +unsafe impl Payload for i16 {} -unsafe impl BufferType for u32 {} +unsafe impl Payload for u32 {} -unsafe impl BufferType for i32 {} +unsafe impl Payload for i32 {} -unsafe impl BufferType for f32 {} +unsafe impl Payload for f32 {} #[derive(Clone, Copy)] pub enum ImmutableBuffer<'buf, 'wo, BUF> where - BUF: BufferType, + BUF: Payload, { Memory(MemoryBuffer<'buf, BUF>), Peripheral(PeripheralBuffer<'buf, 'wo, BUF>), @@ -125,7 +122,7 @@ where impl<'buf, 'wo, BUF> ImmutableBuffer<'buf, 'wo, BUF> where - BUF: BufferType, + BUF: Payload, { pub fn memory(self) -> MemoryBuffer<'buf, BUF> { if let ImmutableBuffer::Memory(buffer) = self { @@ -148,7 +145,7 @@ pub type ImmutableBufferStatic<'wo, BUF> = ImmutableBuffer<'static, 'wo, BUF>; pub enum MutableBuffer<'buf, 'wo, BUF> where - BUF: BufferType, + BUF: Payload, { Memory(MemoryBufferMut<'buf, BUF>), Peripheral(PeripheralBufferMut<'buf, 'wo, BUF>), @@ -156,7 +153,7 @@ where impl<'buf, 'wo, BUF> MutableBuffer<'buf, 'wo, BUF> where - BUF: BufferType, + BUF: Payload, { pub fn into_memory(self) -> MemoryBufferMut<'buf, BUF> { if let MutableBuffer::Memory(buffer) = self { @@ -229,7 +226,7 @@ pub type MutableBufferStatic<'wo, BUF> = MutableBuffer<'static, 'wo, BUF>; #[derive(Clone, Copy)] pub enum MemoryBuffer<'buf, BUF> where - BUF: BufferType, + BUF: Payload, { Fixed(FixedBuffer<'buf, BUF>), Incremented(RegularOffsetBuffer<'buf, BUF>), @@ -237,7 +234,7 @@ where impl<'buf, BUF> MemoryBuffer<'buf, BUF> where - BUF: BufferType, + BUF: Payload, { pub fn fixed(self) -> FixedBuffer<'buf, BUF> { if let MemoryBuffer::Fixed(buffer) = self { @@ -260,7 +257,7 @@ pub type MemoryBufferStatic = MemoryBuffer<'static, BUF>; pub enum MemoryBufferMut<'buf, BUF> where - BUF: BufferType, + BUF: Payload, { Fixed(FixedBufferMut<'buf, BUF>), Incremented(RegularOffsetBufferMut<'buf, BUF>), @@ -268,7 +265,7 @@ where impl<'buf, BUF> MemoryBufferMut<'buf, BUF> where - BUF: BufferType, + BUF: Payload, { pub fn into_fixed(self) -> FixedBufferMut<'buf, BUF> { if let MemoryBufferMut::Fixed(buffer) = self { @@ -341,7 +338,7 @@ pub type MemoryBufferMutStatic = MemoryBufferMut<'static, BUF>; #[derive(Clone, Copy)] pub enum PeripheralBuffer<'buf, 'wo, BUF> where - BUF: BufferType, + BUF: Payload, { Fixed(FixedBuffer<'buf, BUF>), Incremented(IncrementedBuffer<'buf, 'wo, BUF>), @@ -349,7 +346,7 @@ where impl<'buf, 'wo, BUF> PeripheralBuffer<'buf, 'wo, BUF> where - BUF: BufferType, + BUF: Payload, { pub fn fixed(self) -> FixedBuffer<'buf, BUF> { if let PeripheralBuffer::Fixed(buffer) = self { @@ -372,7 +369,7 @@ pub type PeripheralBufferStatic<'wo, BUF> = PeripheralBuffer<'static, 'wo, BUF>; pub enum PeripheralBufferMut<'buf, 'wo, BUF> where - BUF: BufferType, + BUF: Payload, { Fixed(FixedBufferMut<'buf, BUF>), Incremented(IncrementedBufferMut<'buf, 'wo, BUF>), @@ -380,7 +377,7 @@ where impl<'buf, 'wo, BUF> PeripheralBufferMut<'buf, 'wo, BUF> where - BUF: BufferType, + BUF: Payload, { pub fn into_fixed(self) -> FixedBufferMut<'buf, BUF> { if let PeripheralBufferMut::Fixed(buffer) = self { @@ -454,7 +451,7 @@ pub type PeripheralBufferMutStatic<'wo, BUF> = #[derive(Clone, Copy)] pub enum IncrementedBuffer<'buf, 'wo, BUF> where - BUF: BufferType, + BUF: Payload, { RegularOffset(RegularOffsetBuffer<'buf, BUF>), WordOffset(WordOffsetBuffer<'buf, 'wo, BUF>), @@ -463,7 +460,7 @@ where #[allow(clippy::len_without_is_empty)] impl<'buf, 'wo, BUF> IncrementedBuffer<'buf, 'wo, BUF> where - BUF: BufferType, + BUF: Payload, { pub fn regular_offset(self) -> RegularOffsetBuffer<'buf, BUF> { if let IncrementedBuffer::RegularOffset(buffer) = self { @@ -487,6 +484,20 @@ where IncrementedBuffer::WordOffset(buffer) => buffer.len(), } } + + pub fn get(self, index: usize) -> BUF { + match self { + IncrementedBuffer::RegularOffset(buffer) => buffer.get(index), + IncrementedBuffer::WordOffset(buffer) => buffer.get(index), + } + } + + pub fn as_ptr(&self, index: usize) -> *const BUF { + match self { + IncrementedBuffer::RegularOffset(buffer) => buffer.as_ptr(index), + IncrementedBuffer::WordOffset(buffer) => buffer.as_ptr(index), + } + } } pub type IncrementedBufferStatic<'wo, BUF> = @@ -494,7 +505,7 @@ pub type IncrementedBufferStatic<'wo, BUF> = pub enum IncrementedBufferMut<'buf, 'wo, BUF> where - BUF: BufferType, + BUF: Payload, { RegularOffset(RegularOffsetBufferMut<'buf, BUF>), WordOffset(WordOffsetBufferMut<'buf, 'wo, BUF>), @@ -503,7 +514,7 @@ where #[allow(clippy::len_without_is_empty)] impl<'buf, 'wo, BUF> IncrementedBufferMut<'buf, 'wo, BUF> where - BUF: BufferType, + BUF: Payload, { pub fn into_regular_offset(self) -> RegularOffsetBufferMut<'buf, BUF> { if let IncrementedBufferMut::RegularOffset(buffer) = self { @@ -564,6 +575,48 @@ where } } + /// # Safety + /// + /// The caller must ensure, that the DMA is currently not modifying this address. + pub unsafe fn get(&self, index: usize) -> BUF { + match self { + IncrementedBufferMut::RegularOffset(buffer) => buffer.get(index), + IncrementedBufferMut::WordOffset(buffer) => buffer.get(index), + } + } + + /// # Safety + /// + /// The caller must ensure, that the DMA is currently not modifying this address. + pub unsafe fn set(&mut self, index: usize, payload: BUF) { + match self { + IncrementedBufferMut::RegularOffset(buffer) => { + buffer.set(index, payload) + } + IncrementedBufferMut::WordOffset(buffer) => { + buffer.set(index, payload) + } + } + } + + pub fn as_ptr(&self, index: usize) -> *const BUF { + match self { + IncrementedBufferMut::RegularOffset(buffer) => buffer.as_ptr(index), + IncrementedBufferMut::WordOffset(buffer) => buffer.as_ptr(index), + } + } + + pub fn as_mut_ptr(&mut self, index: usize) -> *mut BUF { + match self { + IncrementedBufferMut::RegularOffset(buffer) => { + buffer.as_mut_ptr(index) + } + IncrementedBufferMut::WordOffset(buffer) => { + buffer.as_mut_ptr(index) + } + } + } + /// # Safety /// /// `IncrementedBuffer` assumes that the DMA is only reading the buffer. @@ -586,11 +639,11 @@ pub type IncrementedBufferMutStatic<'wo, BUF> = #[derive(Clone, Copy)] pub struct FixedBuffer<'buf, BUF>(*const BUF, PhantomData<&'buf BUF>) where - BUF: BufferType; + BUF: Payload; impl<'buf, BUF> FixedBuffer<'buf, BUF> where - BUF: BufferType, + BUF: Payload, { pub fn new(buffer: &'buf BUF) -> Self { FixedBuffer(buffer, PhantomData) @@ -605,19 +658,19 @@ where } } -unsafe impl<'buf, BUF> Send for FixedBuffer<'buf, BUF> where BUF: BufferType {} +unsafe impl<'buf, BUF> Send for FixedBuffer<'buf, BUF> where BUF: Payload {} -unsafe impl<'buf, BUF> Sync for FixedBuffer<'buf, BUF> where BUF: BufferType {} +unsafe impl<'buf, BUF> Sync for FixedBuffer<'buf, BUF> where BUF: Payload {} pub type FixedBufferStatic = FixedBuffer<'static, BUF>; pub struct FixedBufferMut<'buf, BUF>(*mut BUF, PhantomData<&'buf mut BUF>) where - BUF: BufferType; + BUF: Payload; impl<'buf, BUF> FixedBufferMut<'buf, BUF> where - BUF: BufferType, + BUF: Payload, { pub fn new(buffer: &'buf mut BUF) -> Self { FixedBufferMut(buffer, PhantomData) @@ -654,21 +707,21 @@ where } } -unsafe impl<'buf, BUF> Send for FixedBufferMut<'buf, BUF> where BUF: BufferType {} +unsafe impl<'buf, BUF> Send for FixedBufferMut<'buf, BUF> where BUF: Payload {} -unsafe impl<'buf, BUF> Sync for FixedBufferMut<'buf, BUF> where BUF: BufferType {} +unsafe impl<'buf, BUF> Sync for FixedBufferMut<'buf, BUF> where BUF: Payload {} pub type FixedBufferMutStatic = FixedBufferMut<'static, BUF>; #[derive(Clone, Copy)] pub struct RegularOffsetBuffer<'buf, BUF>(*const [BUF], PhantomData<&'buf BUF>) where - BUF: BufferType; + BUF: Payload; #[allow(clippy::len_without_is_empty)] impl<'buf, BUF> RegularOffsetBuffer<'buf, BUF> where - BUF: BufferType, + BUF: Payload, { pub fn new(buffer: &'buf [BUF]) -> Self { check_buffer_not_empty(buffer); @@ -695,15 +748,11 @@ where } } -unsafe impl<'buf, BUF> Send for RegularOffsetBuffer<'buf, BUF> where - BUF: BufferType -{ -} +unsafe impl<'buf, BUF> Send for RegularOffsetBuffer<'buf, BUF> where BUF: Payload +{} -unsafe impl<'buf, BUF> Sync for RegularOffsetBuffer<'buf, BUF> where - BUF: BufferType -{ -} +unsafe impl<'buf, BUF> Sync for RegularOffsetBuffer<'buf, BUF> where BUF: Payload +{} pub type RegularOffsetBufferStatic = RegularOffsetBuffer<'static, BUF>; @@ -712,12 +761,12 @@ pub struct RegularOffsetBufferMut<'buf, BUF>( PhantomData<&'buf mut BUF>, ) where - BUF: BufferType; + BUF: Payload; #[allow(clippy::len_without_is_empty)] impl<'buf, BUF> RegularOffsetBufferMut<'buf, BUF> where - BUF: BufferType, + BUF: Payload, { pub fn new(buffer: &'buf mut [BUF]) -> Self { check_buffer_not_empty(buffer); @@ -771,12 +820,12 @@ where } unsafe impl<'buf, BUF> Send for RegularOffsetBufferMut<'buf, BUF> where - BUF: BufferType + BUF: Payload { } unsafe impl<'buf, BUF> Sync for RegularOffsetBufferMut<'buf, BUF> where - BUF: BufferType + BUF: Payload { } @@ -788,7 +837,7 @@ unsafe fn read_volatile_slice_buffer( index: usize, ) -> BUF where - BUF: BufferType, + BUF: Payload, { let slice = &*slice_ptr; ptr::read_volatile(&slice[index] as *const _) @@ -800,12 +849,12 @@ pub struct WordOffsetBuffer<'buf, 'wo, BUF>( PhantomData<&'buf BUF>, ) where - BUF: BufferType; + BUF: Payload; #[allow(clippy::len_without_is_empty)] impl<'buf, 'wo, BUF> WordOffsetBuffer<'buf, 'wo, BUF> where - BUF: BufferType, + BUF: Payload, { pub fn new(buffer: &'wo [&'buf BUF]) -> Self { check_buffer_not_empty(buffer); @@ -831,12 +880,12 @@ where } unsafe impl<'buf, 'wo, BUF> Send for WordOffsetBuffer<'buf, 'wo, BUF> where - BUF: BufferType + BUF: Payload { } unsafe impl<'buf, 'wo, BUF> Sync for WordOffsetBuffer<'buf, 'wo, BUF> where - BUF: BufferType + BUF: Payload { } @@ -847,12 +896,12 @@ pub struct WordOffsetBufferMut<'buf, 'wo, BUF>( PhantomData<&'buf mut BUF>, ) where - BUF: BufferType; + BUF: Payload; #[allow(clippy::len_without_is_empty)] impl<'buf, 'wo, BUF> WordOffsetBufferMut<'buf, 'wo, BUF> where - BUF: BufferType, + BUF: Payload, { pub fn new(buffer: &'wo mut [&'buf mut BUF]) -> Self { check_buffer_not_empty(buffer); @@ -866,14 +915,14 @@ where /// # Safety /// - /// - The caller must ensure, that the DMA is currently not modifying this address. + /// The caller must ensure, that the DMA is currently not modifying this address. pub unsafe fn get(&self, index: usize) -> BUF { ptr::read_volatile(self.0[index]) } /// # Safety /// - /// - The caller must ensure, that the DMA is currently not modifying this address. + /// The caller must ensure, that the DMA is currently not modifying this address. pub unsafe fn set(&mut self, index: usize, item: BUF) { ptr::write_volatile(self.0[index], item); } @@ -900,7 +949,7 @@ where } unsafe impl<'buf, 'wo, BUF> Sync for WordOffsetBufferMut<'buf, 'wo, BUF> where - BUF: BufferType + BUF: Payload { } @@ -919,7 +968,7 @@ fn check_buffer_not_empty(buffer: &[T]) { fn check_word_offset(buffer: &[*const BUF]) where - BUF: BufferType, + BUF: Payload, { if buffer.is_empty() { return; @@ -955,8 +1004,8 @@ pub(super) fn configure_safe_transfer( ) where CXX: ChannelId, DMA: DMATrait, - Source: BufferType, - Dest: BufferType, + Source: Payload, + Dest: Payload, { // Note(safety): Safe as the transfer has not started yet. let dest = unsafe { dest.as_immutable() }; @@ -980,11 +1029,11 @@ fn configure_buffers( ) where CXX: ChannelId, DMA: DMATrait, - Peripheral: BufferType, - Memory: BufferType, + Peripheral: Payload, + Memory: Payload, { - let p_size = BufferTypeSize::from_buffer_type::(); - let m_size = BufferTypeSize::from_buffer_type::(); + let p_size = PayloadSize::from_payload::(); + let m_size = PayloadSize::from_payload::(); if stream.transfer_mode() == TransferMode::Direct && p_size != m_size { panic!("The buffer sizes must match if the stream is configured in direct mode."); @@ -1033,8 +1082,8 @@ fn configure_ndt( ) where CXX: ChannelId, DMA: DMATrait, - Peripheral: BufferType, - Memory: BufferType, + Peripheral: Payload, + Memory: Payload, { match peripheral { PeripheralBuffer::Fixed(_) => { @@ -1044,9 +1093,9 @@ fn configure_ndt( } MemoryBuffer::Incremented(buffer) => { let p_size: usize = - BufferTypeSize::from_buffer_type::().into(); + PayloadSize::from_payload::().into(); let m_size: usize = - BufferTypeSize::from_buffer_type::().into(); + PayloadSize::from_payload::().into(); let memory_bytes = buffer.len() * m_size; @@ -1066,9 +1115,23 @@ fn configure_ndt( } } +pub(super) fn check_double_buffer_mut( + double_buffer: &[MemoryBufferMut; 2], +) where + BUF: Payload, +{ + unsafe { + let [buffer_0, buffer_1] = double_buffer; + let double_buffer_immutable = + [buffer_0.as_immutable(), buffer_1.as_immutable()]; + + check_double_buffer(double_buffer_immutable); + } +} + pub(super) fn check_double_buffer(double_buffer: [MemoryBuffer; 2]) where - BUF: BufferType, + BUF: Payload, { match double_buffer[0] { MemoryBuffer::Fixed(_) => { @@ -1093,3 +1156,16 @@ where } } } + +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +pub enum DoubleBuffer { + First, + Second, +} + +pub(super) fn double_buffer_idx(buffer: DoubleBuffer) -> usize { + match buffer { + DoubleBuffer::First => 0, + DoubleBuffer::Second => 1, + } +} From b082c1f530b93c254144e84065951b24ffa1ec92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ad=C3=A4?= Date: Fri, 20 Dec 2019 19:10:43 +0100 Subject: [PATCH 031/103] Pre-PR-commit --- Cargo.toml | 1 - src/dma.rs | 2 ++ src/lib.rs | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 86eeee8e..766380f7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,7 +26,6 @@ stm32h7 = "0.9.0" void = { version = "1.0.2", default-features = false } cast = { version = "0.2.2", default-features = false } nb = "0.1.2" -vcell = "0.1.2" [dependencies.bare-metal] version = "0.2.4" features = ["const-fn"] diff --git a/src/dma.rs b/src/dma.rs index 16fca1fb..1b49e533 100644 --- a/src/dma.rs +++ b/src/dma.rs @@ -1,3 +1,4 @@ +// TODO: Remove when merging. #![warn(clippy::all)] #[macro_use] @@ -40,6 +41,7 @@ use crate::nb::{self, block, Error as NbError}; use core::convert::{Infallible, TryFrom, TryInto}; use core::marker::PhantomData; use core::mem; +// TODO: Remove when merging. Necessary for me as I'm using CLion with rust plugin, which doesn't support conditionally imported items yet. use stm32h7::stm32h743 as stm32; pub unsafe trait DMATrait {} diff --git a/src/lib.rs b/src/lib.rs index f7e6bb0c..16192c09 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,6 @@ #![no_std] #![allow(non_camel_case_types)] +// TODO: Remove when merging. #![allow(clippy::all)] #[derive(Debug)] From aa429d2f5007f0118718173ddb71ed64a55a9635 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ad=C3=A4?= Date: Fri, 20 Dec 2019 19:52:33 +0100 Subject: [PATCH 032/103] Removed idea files --- .idea/.gitignore | 2 -- .idea/misc.xml | 6 ------ .idea/modules.xml | 8 -------- .idea/stm32h7xx-hal.iml | 14 -------------- .idea/vcs.xml | 6 ------ 5 files changed, 36 deletions(-) delete mode 100644 .idea/.gitignore delete mode 100644 .idea/misc.xml delete mode 100644 .idea/modules.xml delete mode 100644 .idea/stm32h7xx-hal.iml delete mode 100644 .idea/vcs.xml diff --git a/.idea/.gitignore b/.idea/.gitignore deleted file mode 100644 index 5c98b428..00000000 --- a/.idea/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# Default ignored files -/workspace.xml \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml deleted file mode 100644 index 28a804d8..00000000 --- a/.idea/misc.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml deleted file mode 100644 index 2ea6aa53..00000000 --- a/.idea/modules.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/.idea/stm32h7xx-hal.iml b/.idea/stm32h7xx-hal.iml deleted file mode 100644 index b7b42421..00000000 --- a/.idea/stm32h7xx-hal.iml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml deleted file mode 100644 index 94a25f7f..00000000 --- a/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file From 47497fbaecc9544fa0fac1a2b93cb1be6452c9e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ad=C3=A4?= Date: Sat, 21 Dec 2019 01:06:30 +0100 Subject: [PATCH 033/103] Removed manual implementation of Send where possible --- src/dma.rs | 2 +- src/dma/channel.rs | 5 +---- src/dma/macros.rs | 2 +- src/dma/mux.rs | 9 ++++++++- src/dma/mux/request_gen.rs | 5 +---- src/dma/mux/shared.rs | 2 ++ src/dma/safe_transfer.rs | 38 ++++++++++++++++---------------------- src/dma/stream.rs | 1 + 8 files changed, 31 insertions(+), 33 deletions(-) diff --git a/src/dma.rs b/src/dma.rs index 1b49e533..f96ae6c5 100644 --- a/src/dma.rs +++ b/src/dma.rs @@ -44,7 +44,7 @@ use core::mem; // TODO: Remove when merging. Necessary for me as I'm using CLion with rust plugin, which doesn't support conditionally imported items yet. use stm32h7::stm32h743 as stm32; -pub unsafe trait DMATrait {} +pub unsafe trait DMATrait: Send {} unsafe impl DMATrait for DMA1 {} unsafe impl DMATrait for DMA2 {} diff --git a/src/dma/channel.rs b/src/dma/channel.rs index f8887064..61050d8c 100644 --- a/src/dma/channel.rs +++ b/src/dma/channel.rs @@ -1,6 +1,4 @@ -use core::fmt::Debug; - -pub unsafe trait ChannelId: Debug { +pub unsafe trait ChannelId: Send { const STREAM_ID: usize; const MUX_ID: usize; } @@ -8,7 +6,6 @@ pub unsafe trait ChannelId: Debug { macro_rules! channels { ($($channel:ident => [$stream:tt, $mux:tt]),*) => { $( - #[derive(Debug)] pub struct $channel; unsafe impl ChannelId for $channel { diff --git a/src/dma/macros.rs b/src/dma/macros.rs index ca7c1f4f..da2e2fc5 100644 --- a/src/dma/macros.rs +++ b/src/dma/macros.rs @@ -1,6 +1,6 @@ macro_rules! type_state { ($trait:ident, $($type_state:ident),*) => { - pub unsafe trait $trait: core::fmt::Debug + PartialEq + Eq + Clone + Copy {} + pub unsafe trait $trait: core::fmt::Debug + PartialEq + Eq + Clone + Copy + Send + Sync {} $( #[derive(Debug, PartialEq, Eq, Clone, Copy)] diff --git a/src/dma/mux.rs b/src/dma/mux.rs index 7bad0451..64e7130c 100644 --- a/src/dma/mux.rs +++ b/src/dma/mux.rs @@ -84,7 +84,7 @@ macro_rules! request_id { pub mod request_ids { use super::RequestId as RequestIdEnum; - pub unsafe trait RequestId { + pub unsafe trait RequestId: Send { const REQUEST_ID: RequestIdEnum; } @@ -390,3 +390,10 @@ where } } } + +unsafe impl Sync for RequestGenerator +where + GXX: GenId, + ED: GenED, +{ +} diff --git a/src/dma/mux/request_gen.rs b/src/dma/mux/request_gen.rs index e9894b58..0b6651cc 100644 --- a/src/dma/mux/request_gen.rs +++ b/src/dma/mux/request_gen.rs @@ -1,17 +1,14 @@ -use core::fmt::Debug; - type_state! { ED, Disabled, Enabled } -pub unsafe trait GenId: Debug { +pub unsafe trait GenId: Send { const ID: usize; } macro_rules! gen_ids { ($($name:ident => $id:tt),*) => { $( - #[derive(Debug)] pub struct $name; unsafe impl GenId for $name { diff --git a/src/dma/mux/shared.rs b/src/dma/mux/shared.rs index 791012b5..d8265697 100644 --- a/src/dma/mux/shared.rs +++ b/src/dma/mux/shared.rs @@ -6,6 +6,7 @@ pub struct MuxIsr { pub(in super::super) cfr: &'static mut CFR, } +unsafe impl Send for MuxIsr {} unsafe impl Sync for MuxIsr {} pub struct RequestGenIsr { @@ -14,4 +15,5 @@ pub struct RequestGenIsr { pub(super) rgcfr: &'static mut RGCFR, } +unsafe impl Send for RequestGenIsr {} unsafe impl Sync for RequestGenIsr {} diff --git a/src/dma/safe_transfer.rs b/src/dma/safe_transfer.rs index b64b6013..e9a3eeed 100644 --- a/src/dma/safe_transfer.rs +++ b/src/dma/safe_transfer.rs @@ -10,7 +10,7 @@ use core::fmt::Debug; use core::marker::PhantomData; use core::{mem, ptr}; -pub unsafe trait TransferState {} +pub unsafe trait TransferState: Send + Sync {} pub struct Start; unsafe impl TransferState for Start {} @@ -33,7 +33,10 @@ where /// # Safety /// /// * `Self` must be valid for any bit representation -pub unsafe trait Payload: Sized + Clone + Copy + Sync + 'static {} +pub unsafe trait Payload: + Sized + Clone + Copy + Send + Sync + 'static +{ +} // Maps Payload to number of bytes int_enum! { @@ -658,9 +661,9 @@ where } } -unsafe impl<'buf, BUF> Send for FixedBuffer<'buf, BUF> where BUF: Payload {} +unsafe impl Send for FixedBuffer<'_, BUF> where BUF: Payload {} -unsafe impl<'buf, BUF> Sync for FixedBuffer<'buf, BUF> where BUF: Payload {} +unsafe impl Sync for FixedBuffer<'_, BUF> where BUF: Payload {} pub type FixedBufferStatic = FixedBuffer<'static, BUF>; @@ -707,9 +710,9 @@ where } } -unsafe impl<'buf, BUF> Send for FixedBufferMut<'buf, BUF> where BUF: Payload {} +unsafe impl Send for FixedBufferMut<'_, BUF> where BUF: Payload {} -unsafe impl<'buf, BUF> Sync for FixedBufferMut<'buf, BUF> where BUF: Payload {} +unsafe impl Sync for FixedBufferMut<'_, BUF> where BUF: Payload {} pub type FixedBufferMutStatic = FixedBufferMut<'static, BUF>; @@ -748,11 +751,9 @@ where } } -unsafe impl<'buf, BUF> Send for RegularOffsetBuffer<'buf, BUF> where BUF: Payload -{} +unsafe impl Send for RegularOffsetBuffer<'_, BUF> where BUF: Payload {} -unsafe impl<'buf, BUF> Sync for RegularOffsetBuffer<'buf, BUF> where BUF: Payload -{} +unsafe impl Sync for RegularOffsetBuffer<'_, BUF> where BUF: Payload {} pub type RegularOffsetBufferStatic = RegularOffsetBuffer<'static, BUF>; @@ -819,15 +820,9 @@ where } } -unsafe impl<'buf, BUF> Send for RegularOffsetBufferMut<'buf, BUF> where - BUF: Payload -{ -} +unsafe impl Send for RegularOffsetBufferMut<'_, BUF> where BUF: Payload {} -unsafe impl<'buf, BUF> Sync for RegularOffsetBufferMut<'buf, BUF> where - BUF: Payload -{ -} +unsafe impl Sync for RegularOffsetBufferMut<'_, BUF> where BUF: Payload {} pub type RegularOffsetBufferMutStatic = RegularOffsetBufferMut<'static, BUF>; @@ -948,10 +943,9 @@ where } } -unsafe impl<'buf, 'wo, BUF> Sync for WordOffsetBufferMut<'buf, 'wo, BUF> where - BUF: Payload -{ -} +unsafe impl Send for WordOffsetBufferMut<'_, '_, BUF> where BUF: Payload {} + +unsafe impl Sync for WordOffsetBufferMut<'_, '_, BUF> where BUF: Payload {} pub type WordOffsetBufferMutStatic<'wo, BUF> = WordOffsetBufferMut<'static, 'wo, BUF>; diff --git a/src/dma/stream.rs b/src/dma/stream.rs index 7654d0ae..7173f774 100644 --- a/src/dma/stream.rs +++ b/src/dma/stream.rs @@ -213,6 +213,7 @@ where _phantom_data: PhantomData, } +unsafe impl Send for StreamIsr where DMA: DMATrait {} unsafe impl Sync for StreamIsr where DMA: DMATrait {} #[derive(Debug, PartialEq, Eq, Clone, Copy)] From 942b97a7abc5a4a9960f00904158e55ac2220052 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ad=C3=A4?= Date: Sat, 21 Dec 2019 18:23:57 +0100 Subject: [PATCH 034/103] Implemented missing setters for interrupt configuration for dma stream --- src/dma.rs | 20 ++++++++++++++++++++ src/dma/safe_transfer.rs | 4 ++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/src/dma.rs b/src/dma.rs index f96ae6c5..d5964ba1 100644 --- a/src/dma.rs +++ b/src/dma.rs @@ -159,22 +159,42 @@ where self.rb.cr.read().tcie().bit().into() } + pub fn set_transfer_complete_interrupt(&mut self, tc_intrpt: TransferCompleteInterrupt) { + self.rb.cr.modify(|_, w| w.tcie().bit(tc_intrpt.into())); + } + pub fn half_transfer_interrupt(&self) -> HalfTransferInterrupt { self.rb.cr.read().htie().bit().into() } + pub fn set_half_transfer_interrupt(&mut self, ht_intrpt: HalfTransferInterrupt) { + self.rb.cr.modify(|_, w| w.htie().bit(ht_intrpt.into())); + } + pub fn transfer_error_interrupt(&self) -> TransferErrorInterrupt { self.rb.cr.read().teie().bit().into() } + pub fn set_transfer_error_interrupt(&mut self, te_intrpt: TransferErrorInterrupt) { + self.rb.cr.modify(|_, w| w.teie().bit(te_intrpt.into())); + } + pub fn direct_mode_error_interrupt(&self) -> DirectModeErrorInterrupt { self.rb.cr.read().dmeie().bit().into() } + pub fn set_direct_mode_error_interrupt(&mut self, dme_intrpt: DirectModeErrorInterrupt) { + self.rb.cr.modify(|_, w| w.dmeie().bit(dme_intrpt.into())); + } + pub fn fifo_error_interrupt(&self) -> FifoErrorInterrupt { self.rb.fcr.read().feie().bit().into() } + pub fn set_fifo_error_interrupt(&mut self, fe_intrpt: FifoErrorInterrupt) { + self.rb.fcr.modify(|_, w| w.feie().bit(fe_intrpt.into())); + } + /// **Note** (for disabled streams): /// This config value gets forced to `Dma`, if `transfer_direction` is `M2M`. /// diff --git a/src/dma/safe_transfer.rs b/src/dma/safe_transfer.rs index e9a3eeed..efdcb782 100644 --- a/src/dma/safe_transfer.rs +++ b/src/dma/safe_transfer.rs @@ -38,10 +38,10 @@ pub unsafe trait Payload: { } -// Maps Payload to number of bytes +// Maps Payload size to number of bytes int_enum! { PayloadSize <=> usize, - "Buffer Size", + "Payload Size", Byte <=> 1, HalfWord <=> 2, Word <=> 4 From f6a9a6a21a8b0dcabd0fbfd56fd1943928d878b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ad=C3=A4?= Date: Sat, 21 Dec 2019 18:39:48 +0100 Subject: [PATCH 035/103] Added setters to the safe transfers to allow stream interrupt configuration on the fly --- src/dma.rs | 122 +++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 118 insertions(+), 4 deletions(-) diff --git a/src/dma.rs b/src/dma.rs index d5964ba1..ac1df31d 100644 --- a/src/dma.rs +++ b/src/dma.rs @@ -159,7 +159,10 @@ where self.rb.cr.read().tcie().bit().into() } - pub fn set_transfer_complete_interrupt(&mut self, tc_intrpt: TransferCompleteInterrupt) { + pub fn set_transfer_complete_interrupt( + &mut self, + tc_intrpt: TransferCompleteInterrupt, + ) { self.rb.cr.modify(|_, w| w.tcie().bit(tc_intrpt.into())); } @@ -167,7 +170,10 @@ where self.rb.cr.read().htie().bit().into() } - pub fn set_half_transfer_interrupt(&mut self, ht_intrpt: HalfTransferInterrupt) { + pub fn set_half_transfer_interrupt( + &mut self, + ht_intrpt: HalfTransferInterrupt, + ) { self.rb.cr.modify(|_, w| w.htie().bit(ht_intrpt.into())); } @@ -175,7 +181,10 @@ where self.rb.cr.read().teie().bit().into() } - pub fn set_transfer_error_interrupt(&mut self, te_intrpt: TransferErrorInterrupt) { + pub fn set_transfer_error_interrupt( + &mut self, + te_intrpt: TransferErrorInterrupt, + ) { self.rb.cr.modify(|_, w| w.teie().bit(te_intrpt.into())); } @@ -183,7 +192,10 @@ where self.rb.cr.read().dmeie().bit().into() } - pub fn set_direct_mode_error_interrupt(&mut self, dme_intrpt: DirectModeErrorInterrupt) { + pub fn set_direct_mode_error_interrupt( + &mut self, + dme_intrpt: DirectModeErrorInterrupt, + ) { self.rb.cr.modify(|_, w| w.dmeie().bit(dme_intrpt.into())); } @@ -1433,6 +1445,40 @@ where &self.state.stream } + pub fn set_transfer_complete_interrupt( + &mut self, + tc_intrpt: TransferCompleteInterrupt, + ) { + self.state.stream.set_transfer_complete_interrupt(tc_intrpt); + } + + pub fn set_half_transfer_interrupt( + &mut self, + ht_intrpt: HalfTransferInterrupt, + ) { + self.state.stream.set_half_transfer_interrupt(ht_intrpt); + } + + pub fn set_transfer_error_interrupt( + &mut self, + te_intrpt: TransferErrorInterrupt, + ) { + self.state.stream.set_transfer_error_interrupt(te_intrpt); + } + + pub fn set_direct_mode_error_interrupt( + &mut self, + dme_intrpt: DirectModeErrorInterrupt, + ) { + self.state + .stream + .set_direct_mode_error_interrupt(dme_intrpt); + } + + pub fn set_fifo_error_interrupt(&mut self, fe_intrpt: FifoErrorInterrupt) { + self.state.stream.set_fifo_error_interrupt(fe_intrpt); + } + pub fn stop(self) -> Stream { self.state.stream.disable().await_disabled() } @@ -1553,6 +1599,40 @@ where &self.state.stream } + pub fn set_transfer_complete_interrupt( + &mut self, + tc_intrpt: TransferCompleteInterrupt, + ) { + self.state.stream.set_transfer_complete_interrupt(tc_intrpt); + } + + pub fn set_half_transfer_interrupt( + &mut self, + ht_intrpt: HalfTransferInterrupt, + ) { + self.state.stream.set_half_transfer_interrupt(ht_intrpt); + } + + pub fn set_transfer_error_interrupt( + &mut self, + te_intrpt: TransferErrorInterrupt, + ) { + self.state.stream.set_transfer_error_interrupt(te_intrpt); + } + + pub fn set_direct_mode_error_interrupt( + &mut self, + dme_intrpt: DirectModeErrorInterrupt, + ) { + self.state + .stream + .set_direct_mode_error_interrupt(dme_intrpt); + } + + pub fn set_fifo_error_interrupt(&mut self, fe_intrpt: FifoErrorInterrupt) { + self.state.stream.set_fifo_error_interrupt(fe_intrpt); + } + pub fn set_double_buffer( &mut self, buffer: MemoryBufferStatic, @@ -1735,6 +1815,40 @@ where &self.state.stream } + pub fn set_transfer_complete_interrupt( + &mut self, + tc_intrpt: TransferCompleteInterrupt, + ) { + self.state.stream.set_transfer_complete_interrupt(tc_intrpt); + } + + pub fn set_half_transfer_interrupt( + &mut self, + ht_intrpt: HalfTransferInterrupt, + ) { + self.state.stream.set_half_transfer_interrupt(ht_intrpt); + } + + pub fn set_transfer_error_interrupt( + &mut self, + te_intrpt: TransferErrorInterrupt, + ) { + self.state.stream.set_transfer_error_interrupt(te_intrpt); + } + + pub fn set_direct_mode_error_interrupt( + &mut self, + dme_intrpt: DirectModeErrorInterrupt, + ) { + self.state + .stream + .set_direct_mode_error_interrupt(dme_intrpt); + } + + pub fn set_fifo_error_interrupt(&mut self, fe_intrpt: FifoErrorInterrupt) { + self.state.stream.set_fifo_error_interrupt(fe_intrpt); + } + pub fn set_double_buffer( &mut self, buffer: MemoryBufferMutStatic, From c49226c9384948a6386009edf9f8bfd15d885e9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ad=C3=A4?= Date: Sat, 21 Dec 2019 23:16:17 +0100 Subject: [PATCH 036/103] Added check of stream compatibility for double buffer transfers --- src/dma.rs | 7 ++++++- src/dma/safe_transfer.rs | 19 +++++++++++++++++-- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/src/dma.rs b/src/dma.rs index ac1df31d..c3a54745 100644 --- a/src/dma.rs +++ b/src/dma.rs @@ -19,7 +19,8 @@ use self::mux::{ SyncOverrunInterrupt, SyncPolarity, }; use self::safe_transfer::{ - check_double_buffer, check_double_buffer_mut, configure_safe_transfer, + check_double_buffer, check_double_buffer_mut, + check_double_buffer_stream_config, configure_safe_transfer, double_buffer_idx, DoubleBuffer, ImmutableBuffer, ImmutableBufferStatic, MemoryBuffer, MemoryBufferMut, MemoryBufferMutStatic, MemoryBufferStatic, MutableBuffer, MutableBufferStatic, Ongoing, Payload, @@ -1566,6 +1567,8 @@ where CXX: ChannelId, DMA: DMATrait, { + check_double_buffer_stream_config(&stream); + let dest_buffer = MutableBuffer::Peripheral(self.dest); configure_safe_transfer( @@ -1781,6 +1784,8 @@ where CXX: ChannelId, DMA: DMATrait, { + check_double_buffer_stream_config(&stream); + let [dest_buffer_0, dest_buffer_1] = self.dests; let dest_buffer_0 = MutableBuffer::Memory(dest_buffer_0); diff --git a/src/dma/safe_transfer.rs b/src/dma/safe_transfer.rs index efdcb782..e6da23fb 100644 --- a/src/dma/safe_transfer.rs +++ b/src/dma/safe_transfer.rs @@ -1,7 +1,7 @@ use super::channel::ChannelId; use super::stream::{ - Disabled, Enabled, IsrCleared, IsrUncleared, M0a, MSize, Minc, Ndt, PSize, - Pa, Pinc, Pincos, TransferDirection, TransferMode, + Disabled, Enabled, FlowController, IsrCleared, IsrUncleared, M0a, MSize, + Minc, Ndt, PSize, Pa, Pinc, Pincos, TransferDirection, TransferMode, }; use super::{DMATrait, Stream}; use core::convert::TryFrom; @@ -1109,6 +1109,21 @@ fn configure_ndt( } } +pub(super) fn check_double_buffer_stream_config( + stream: &Stream, +) where + CXX: ChannelId, + DMA: DMATrait, +{ + if stream.transfer_direction() == TransferDirection::M2M { + panic!("The stream direction must not be `M2M` when configuring double buffer streams."); + } + + if stream.effective_flow_controller() == FlowController::Peripheral { + panic!("The flow controller must not be `Peripheral` when configuring double buffer streams."); + } +} + pub(super) fn check_double_buffer_mut( double_buffer: &[MemoryBufferMut; 2], ) where From 09d613e3b4ff634ec36feaf194047e443c076b36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ad=C3=A4?= Date: Sun, 22 Dec 2019 16:14:49 +0100 Subject: [PATCH 037/103] Implemented DMA Extension trait --- examples/dma.rs | 62 +++++++ src/dma.rs | 388 ++++++++++++++++++++++++++++++++++++--- src/dma/channel.rs | 41 +++-- src/dma/mux.rs | 15 +- src/dma/mux/shared.rs | 13 +- src/dma/safe_transfer.rs | 12 +- src/dma/stream.rs | 24 ++- 7 files changed, 497 insertions(+), 58 deletions(-) create mode 100644 examples/dma.rs diff --git a/examples/dma.rs b/examples/dma.rs new file mode 100644 index 00000000..abbd7746 --- /dev/null +++ b/examples/dma.rs @@ -0,0 +1,62 @@ +#![deny(unsafe_code)] +#![no_main] +#![no_std] + +extern crate panic_itm; + +use cortex_m; +use cortex_m_rt::entry; + +use stm32h7xx_hal::{adc, delay::Delay, pac, prelude::*}; + +use cortex_m_log::println; +use cortex_m_log::{ + destination::Itm, printer::itm::InterruptSync as InterruptSyncItm, +}; + +#[entry] +fn main() -> ! { + let cp = cortex_m::Peripherals::take().unwrap(); + let dp = pac::Peripherals::take().unwrap(); + let mut log = InterruptSyncItm::new(Itm::new(cp.ITM)); + + // Constrain and Freeze power + println!(log, "Setup PWR... "); + let pwr = dp.PWR.constrain(); + let vos = pwr.freeze(); + + // Constrain and Freeze clock + println!(log, "Setup RCC... "); + let rcc = dp.RCC.constrain(); + + // setting this per_ck to 4 Mhz here (which is gonna choose the CSI that runs at exactly 4 Mhz) as the adc requires per_ck as its + // own kernel clock and wouldn't work at all if per_ck wouldnt be enabled or loose a few bits if it was too fast + // (the maximum for this is 36 Mhz) + let mut ccdr = rcc + .sys_ck(100.mhz()) + .per_ck(4.mhz()) + .freeze(vos, &dp.SYSCFG); + + let mut delay = Delay::new(cp.SYST, ccdr.clocks); + + // Setup ADC + let mut adc3 = adc::Adc::adc3(dp.ADC3, &mut delay, &mut ccdr).enable(); + adc3.set_resolution(adc::Resolution::SIXTEENBIT); + + // Setup GPIOC + let gpioc = dp.GPIOC.split(&mut ccdr.ahb4); + + // Configure pc0 as an analog input + let mut channel = gpioc.pc0.into_analog(); + + loop { + let data: u32 = adc3.read(&mut channel).unwrap(); + // voltage = reading * (vref/resolution) + println!( + log, + "ADC reading: {}, voltage for nucleo: {}", + data, + data as f32 * (3.3 / adc3.max_sample() as f32) + ); + } +} diff --git a/src/dma.rs b/src/dma.rs index c3a54745..a4557a47 100644 --- a/src/dma.rs +++ b/src/dma.rs @@ -8,15 +8,21 @@ pub mod mux; pub mod safe_transfer; pub mod stream; -use self::channel::ChannelId; +use self::channel::{ + ChannelId, C0, C1, C10, C11, C12, C13, C14, C15, C2, C3, C4, C5, C6, C7, + C8, C9, +}; +use self::mux::request_gen::{ + Disabled as GenDisabled, G0, G1, G2, G3, G4, G5, G6, G7, +}; use self::mux::request_ids::{ ReqNone, RequestId as RequestIdTrait, RequestIdSome, }; -use self::mux::shared::MuxIsr; +use self::mux::shared::{MuxIsr, RequestGenIsr}; use self::mux::{ - EgDisabled, EgED as EgEDTrait, EgEnabled, NbReq, OverrunError, RequestId, - SyncDisabled, SyncED as SyncEDTrait, SyncEnabled, SyncId, - SyncOverrunInterrupt, SyncPolarity, + EgDisabled, EgED as EgEDTrait, EgEnabled, NbReq, OverrunError, + RequestGenerator, RequestId, SyncDisabled, SyncED as SyncEDTrait, + SyncEnabled, SyncId, SyncOverrunInterrupt, SyncPolarity, }; use self::safe_transfer::{ check_double_buffer, check_double_buffer_mut, @@ -28,7 +34,7 @@ use self::safe_transfer::{ }; use self::stm32::dma1::ST; use self::stm32::dmamux1::CCR; -use self::stm32::{DMA1, DMA2}; +use self::stm32::{DMA1, DMA2, RCC}; use self::stream::{ BufferMode, CircularMode, CurrentTarget, DirectModeErrorInterrupt, Disabled, Disabling, Enabled, Error, Event, FifoErrorInterrupt, @@ -43,7 +49,9 @@ use core::convert::{Infallible, TryFrom, TryInto}; use core::marker::PhantomData; use core::mem; // TODO: Remove when merging. Necessary for me as I'm using CLion with rust plugin, which doesn't support conditionally imported items yet. +use crate::dma::mux::MuxShared; use stm32h7::stm32h743 as stm32; +use stm32h7::stm32h743::DMAMUX1; pub unsafe trait DMATrait: Send {} unsafe impl DMATrait for DMA1 {} @@ -51,7 +59,7 @@ unsafe impl DMATrait for DMA2 {} pub struct Channel where - CXX: ChannelId, + CXX: ChannelId, DMA: DMATrait, StreamED: EDTrait, IsrState: IsrStateTrait, @@ -66,7 +74,7 @@ where impl Channel where - CXX: ChannelId, + CXX: ChannelId, DMA: DMATrait, StreamED: EDTrait, IsrState: IsrStateTrait, @@ -116,23 +124,23 @@ where pub struct Stream where - CXX: ChannelId, + CXX: ChannelId, DMA: DMATrait, ED: EDTrait, IsrState: IsrStateTrait, { /// This field *must not* be mutated using shared references - rb: &'static mut ST, + rb: &'static ST, config_ndt: Ndt, _phantom_data: PhantomData<(CXX, DMA, ED, IsrState)>, } impl Stream where - CXX: ChannelId, + CXX: ChannelId, DMA: DMATrait, { - fn new(rb: &'static mut ST) -> Self { + fn after_reset(rb: &'static ST) -> Self { Stream { rb, config_ndt: Ndt::default(), @@ -143,7 +151,7 @@ where impl Stream where - CXX: ChannelId, + CXX: ChannelId, DMA: DMATrait, ED: EDTrait, IsrState: IsrStateTrait, @@ -381,7 +389,7 @@ where impl Stream where - CXX: ChannelId, + CXX: ChannelId, DMA: DMATrait, IsrState: IsrStateTrait, { @@ -548,7 +556,7 @@ where impl Stream where - CXX: ChannelId, + CXX: ChannelId, DMA: DMATrait, ED: NotDisabled, IsrState: IsrStateTrait, @@ -586,7 +594,7 @@ where impl Stream where - CXX: ChannelId, + CXX: ChannelId, DMA: DMATrait, { /// # Safety @@ -713,7 +721,7 @@ where impl Stream where - CXX: ChannelId, + CXX: ChannelId, DMA: DMATrait, IsrState: IsrStateTrait, { @@ -734,7 +742,7 @@ where impl Stream where - CXX: ChannelId, + CXX: ChannelId, DMA: DMATrait, IsrState: IsrStateTrait, { @@ -747,7 +755,7 @@ where impl Stream where - CXX: ChannelId, + CXX: ChannelId, DMA: DMATrait, ED: EDTrait, { @@ -1013,7 +1021,7 @@ where impl Stream where - CXX: ChannelId, + CXX: ChannelId, DMA: DMATrait, { pub fn clear_isr( @@ -1028,7 +1036,7 @@ where impl Stream where - CXX: ChannelId, + CXX: ChannelId, DMA: DMATrait, ED: NotDisabled, { @@ -1037,9 +1045,18 @@ where } } +unsafe impl Send for Stream +where + CXX: ChannelId, + DMA: DMATrait, + ED: EDTrait, + IsrState: IsrStateTrait, +{ +} + unsafe impl Sync for Stream where - CXX: ChannelId, + CXX: ChannelId, DMA: DMATrait, ED: EDTrait, IsrState: IsrStateTrait, @@ -1054,11 +1071,24 @@ where EgED: EgEDTrait, { /// This field *must not* be mutated using shared references - rb: &'static mut CCR, + rb: &'static CCR, req_id: ReqId, _phantom_data: PhantomData<(CXX, SyncED, EgED)>, } +impl DmaMux +where + CXX: ChannelId, +{ + fn after_reset(rb: &'static CCR) -> Self { + DmaMux { + rb, + req_id: ReqNone, + _phantom_data: PhantomData, + } + } +} + impl DmaMux where CXX: ChannelId, @@ -1309,6 +1339,15 @@ where } } +unsafe impl Send for DmaMux +where + CXX: ChannelId, + ReqId: RequestIdTrait, + SyncED: SyncEDTrait, + EgED: EgEDTrait, +{ +} + unsafe impl Sync for DmaMux where CXX: ChannelId, @@ -1419,7 +1458,7 @@ where mut stream: Stream, ) -> SafeTransfer<'wo, Source, Dest, Ongoing> where - CXX: ChannelId, + CXX: ChannelId, DMA: DMATrait, { configure_safe_transfer(&mut stream, self.source, &self.dest); @@ -1439,7 +1478,7 @@ impl SafeTransfer<'_, Source, Dest, Ongoing> where Source: Payload, Dest: Payload, - CXX: ChannelId, + CXX: ChannelId, DMA: DMATrait, { pub fn stream(&self) -> &Stream { @@ -1564,7 +1603,7 @@ where mut stream: Stream, ) -> SafeTransferDoubleBufferR<'wo, Source, Dest, Ongoing> where - CXX: ChannelId, + CXX: ChannelId, DMA: DMATrait, { check_double_buffer_stream_config(&stream); @@ -1595,7 +1634,7 @@ impl where Source: Payload, Dest: Payload, - CXX: ChannelId, + CXX: ChannelId, DMA: DMATrait, { pub fn stream(&self) -> &Stream { @@ -1781,7 +1820,7 @@ where mut stream: Stream, ) -> SafeTransferDoubleBufferW<'wo, Source, Dest, Ongoing> where - CXX: ChannelId, + CXX: ChannelId, DMA: DMATrait, { check_double_buffer_stream_config(&stream); @@ -1813,7 +1852,7 @@ impl where Source: Payload, Dest: Payload, - CXX: ChannelId, + CXX: ChannelId, DMA: DMATrait, { pub fn stream(&self) -> &Stream { @@ -1898,3 +1937,294 @@ where self.state.stream.disable().await_disabled() } } + +pub type ChannelsDma1 = ( + Channel, + Channel, + Channel, + Channel, + Channel, + Channel, + Channel, + Channel, +); + +pub type ChannelsDma2 = ( + Channel, + Channel, + Channel, + Channel, + Channel, + Channel, + Channel, + Channel, +); + +pub type RequestGenerators = ( + RequestGenerator, + RequestGenerator, + RequestGenerator, + RequestGenerator, + RequestGenerator, + RequestGenerator, + RequestGenerator, + RequestGenerator, +); + +pub struct DmaShared { + pub stream_isr_dma_1: StreamIsr, + pub stream_isr_dma_2: StreamIsr, + pub mux_shared: MuxShared, +} + +pub struct Dma { + pub channels_dma_1: ChannelsDma1, + pub channels_dma_2: ChannelsDma2, + pub dma_shared: DmaShared, + pub request_generators: RequestGenerators, + /// Do not access this field. This is stored in case the user want's the peripheral back. + _dma_1: DMA1, + /// Do not access this field. This is stored in case the user want's the peripheral back. + _dma_2: DMA2, + /// Do not access this field. This is stored in case the user want's the peripheral back. + _dma_mux: DMAMUX1, +} + +impl Dma { + pub fn new( + dma_1: DMA1, + dma_2: DMA2, + mut dma_mux: DMAMUX1, + rcc: &mut RCC, + ) -> Self { + Dma::reset_dma(rcc); + Dma::enable_dma(rcc); + + Dma::reset_mux(&mut dma_mux); + + let dma1_rb = unsafe { &*DMA1::ptr() }; + let dma2_rb = unsafe { &*DMA2::ptr() }; + let dma_mux_rb = unsafe { &*DMAMUX1::ptr() }; + + let stream_isr_dma_1 = StreamIsr::new( + &dma1_rb.lisr, + &dma1_rb.hisr, + &dma1_rb.lifcr, + &dma1_rb.hifcr, + ); + let stream_isr_dma_2 = StreamIsr::new( + &dma2_rb.lisr, + &dma2_rb.hisr, + &dma2_rb.lifcr, + &dma2_rb.hifcr, + ); + + let mux_isr = MuxIsr { + csr: &dma_mux_rb.csr, + cfr: &dma_mux_rb.cfr, + }; + let req_gen_isr = + RequestGenIsr::new(&dma_mux_rb.rgsr, &dma_mux_rb.rgcfr); + let mux_shared = MuxShared::new(mux_isr, req_gen_isr); + + let dma_shared = DmaShared { + stream_isr_dma_1, + stream_isr_dma_2, + mux_shared, + }; + + let channels_dma_1 = ( + Channel { + stream: Stream::after_reset(&dma1_rb.st[0]), + mux: DmaMux::after_reset(&dma_mux_rb.ccr[0]), + }, + Channel { + stream: Stream::after_reset(&dma1_rb.st[1]), + mux: DmaMux::after_reset(&dma_mux_rb.ccr[1]), + }, + Channel { + stream: Stream::after_reset(&dma1_rb.st[2]), + mux: DmaMux::after_reset(&dma_mux_rb.ccr[2]), + }, + Channel { + stream: Stream::after_reset(&dma1_rb.st[3]), + mux: DmaMux::after_reset(&dma_mux_rb.ccr[3]), + }, + Channel { + stream: Stream::after_reset(&dma1_rb.st[4]), + mux: DmaMux::after_reset(&dma_mux_rb.ccr[4]), + }, + Channel { + stream: Stream::after_reset(&dma1_rb.st[5]), + mux: DmaMux::after_reset(&dma_mux_rb.ccr[5]), + }, + Channel { + stream: Stream::after_reset(&dma1_rb.st[6]), + mux: DmaMux::after_reset(&dma_mux_rb.ccr[6]), + }, + Channel { + stream: Stream::after_reset(&dma1_rb.st[7]), + mux: DmaMux::after_reset(&dma_mux_rb.ccr[7]), + }, + ); + + let channels_dma_2 = ( + Channel { + stream: Stream::after_reset(&dma1_rb.st[0]), + mux: DmaMux::after_reset(&dma_mux_rb.ccr[8]), + }, + Channel { + stream: Stream::after_reset(&dma1_rb.st[1]), + mux: DmaMux::after_reset(&dma_mux_rb.ccr[9]), + }, + Channel { + stream: Stream::after_reset(&dma1_rb.st[2]), + mux: DmaMux::after_reset(&dma_mux_rb.ccr[10]), + }, + Channel { + stream: Stream::after_reset(&dma1_rb.st[3]), + mux: DmaMux::after_reset(&dma_mux_rb.ccr[11]), + }, + Channel { + stream: Stream::after_reset(&dma1_rb.st[4]), + mux: DmaMux::after_reset(&dma_mux_rb.ccr[12]), + }, + Channel { + stream: Stream::after_reset(&dma1_rb.st[5]), + mux: DmaMux::after_reset(&dma_mux_rb.ccr[13]), + }, + Channel { + stream: Stream::after_reset(&dma1_rb.st[6]), + mux: DmaMux::after_reset(&dma_mux_rb.ccr[14]), + }, + Channel { + stream: Stream::after_reset(&dma1_rb.st[7]), + mux: DmaMux::after_reset(&dma_mux_rb.ccr[15]), + }, + ); + + let request_generators = ( + RequestGenerator::after_reset(&dma_mux_rb.rgcr[0]), + RequestGenerator::after_reset(&dma_mux_rb.rgcr[1]), + RequestGenerator::after_reset(&dma_mux_rb.rgcr[2]), + RequestGenerator::after_reset(&dma_mux_rb.rgcr[3]), + RequestGenerator::after_reset(&dma_mux_rb.rgcr[4]), + RequestGenerator::after_reset(&dma_mux_rb.rgcr[5]), + RequestGenerator::after_reset(&dma_mux_rb.rgcr[6]), + RequestGenerator::after_reset(&dma_mux_rb.rgcr[7]), + ); + + Dma { + channels_dma_1, + channels_dma_2, + dma_shared, + request_generators, + _dma_1: dma_1, + _dma_2: dma_2, + _dma_mux: dma_mux, + } + } + + fn reset_dma(rcc: &mut RCC) { + rcc.ahb1rstr.modify(|_, w| w.dma1rst().set_bit()); + rcc.ahb1rstr.modify(|_, w| w.dma1rst().clear_bit()); + rcc.ahb1rstr.modify(|_, w| w.dma2rst().set_bit()); + rcc.ahb1rstr.modify(|_, w| w.dma2rst().clear_bit()); + } + + fn enable_dma(rcc: &mut RCC) { + rcc.ahb1enr.modify(|_, w| w.dma1en().set_bit()); + rcc.ahb1enr.modify(|_, w| w.dma2en().set_bit()); + } + + fn reset_mux(mux: &mut DMAMUX1) { + for ccr in mux.ccr.iter() { + ccr.reset(); + } + + mux.cfr.write(|w| { + w.csof0() + .set_bit() + .csof1() + .set_bit() + .csof2() + .set_bit() + .csof3() + .set_bit() + .csof4() + .set_bit() + .csof5() + .set_bit() + .csof6() + .set_bit() + .csof7() + .set_bit() + .csof8() + .set_bit() + .csof9() + .set_bit() + .csof10() + .set_bit() + .csof11() + .set_bit() + .csof12() + .set_bit() + .csof13() + .set_bit() + .csof14() + .set_bit() + .csof15() + .set_bit() + }); + + for rgcr in mux.rgcr.iter() { + rgcr.reset(); + } + + mux.rgcfr.write(|w| { + w.cof0() + .set_bit() + .cof1() + .set_bit() + .cof2() + .set_bit() + .cof3() + .set_bit() + .cof4() + .set_bit() + .cof5() + .set_bit() + .cof6() + .set_bit() + .cof7() + .set_bit() + }); + } +} + +pub trait DmaExt: DMATrait { + type Other: DMATrait; + + fn dma( + self, + other_dma: Self::Other, + dma_mux: DMAMUX1, + rcc: &mut RCC, + ) -> Dma; +} + +impl DmaExt for DMA1 { + type Other = DMA2; + + fn dma(self, dma_2: DMA2, dma_mux: DMAMUX1, rcc: &mut RCC) -> Dma { + Dma::new(self, dma_2, dma_mux, rcc) + } +} + +impl DmaExt for DMA2 { + type Other = DMA1; + + fn dma(self, dma_1: DMA1, dma_mux: DMAMUX1, rcc: &mut RCC) -> Dma { + Dma::new(dma_1, self, dma_mux, rcc) + } +} diff --git a/src/dma/channel.rs b/src/dma/channel.rs index 61050d8c..decab70a 100644 --- a/src/dma/channel.rs +++ b/src/dma/channel.rs @@ -1,36 +1,43 @@ +use super::stm32::{DMA1, DMA2}; +use super::DMATrait; + pub unsafe trait ChannelId: Send { const STREAM_ID: usize; const MUX_ID: usize; + + type DMA: DMATrait; } macro_rules! channels { - ($($channel:ident => [$stream:tt, $mux:tt]),*) => { + ($($channel:ident => [$stream:tt, $mux:tt, $dma:ident]),*) => { $( pub struct $channel; unsafe impl ChannelId for $channel { const STREAM_ID: usize = $stream; const MUX_ID: usize = $mux; + + type DMA = $dma; } )* }; } channels! { - C0 => [0, 0], - C1 => [1, 1], - C2 => [2, 2], - C3 => [3, 3], - C4 => [4, 4], - C5 => [5, 5], - C6 => [6, 6], - C7 => [7, 7], - C8 => [0, 8], - C9 => [1, 9], - C10 => [2, 10], - C11 => [3, 11], - C12 => [4, 12], - C13 => [5, 13], - C14 => [6, 14], - C15 => [7, 15] + C0 => [0, 0, DMA1], + C1 => [1, 1, DMA1], + C2 => [2, 2, DMA1], + C3 => [3, 3, DMA1], + C4 => [4, 4, DMA1], + C5 => [5, 5, DMA1], + C6 => [6, 6, DMA1], + C7 => [7, 7, DMA1], + C8 => [0, 8, DMA2], + C9 => [1, 9, DMA2], + C10 => [2, 10, DMA2], + C11 => [3, 11, DMA2], + C12 => [4, 12, DMA2], + C13 => [5, 13, DMA2], + C14 => [6, 14, DMA2], + C15 => [7, 15, DMA2] } diff --git a/src/dma/mux.rs b/src/dma/mux.rs index 64e7130c..5c5830d5 100644 --- a/src/dma/mux.rs +++ b/src/dma/mux.rs @@ -242,6 +242,17 @@ request_id! { pub struct MuxShared { pub mux_isr: MuxIsr, pub req_gen_isr: RequestGenIsr, + pub request_ids: RequestIds, +} + +impl MuxShared { + pub(super) fn new(mux_isr: MuxIsr, req_gen_isr: RequestGenIsr) -> Self { + MuxShared { + mux_isr, + req_gen_isr, + request_ids: RequestIds::new(), + } + } } pub struct OverrunError; @@ -252,7 +263,7 @@ where ED: GenED, { /// This field *must not* be mutated using shared references - rb: &'static mut RGCR, + rb: &'static RGCR, _phantom_data: PhantomData<(GXX, ED)>, } @@ -260,7 +271,7 @@ impl RequestGenerator where GXX: GenId, { - pub(super) fn after_reset(rb: &'static mut RGCR) -> Self { + pub(super) fn after_reset(rb: &'static RGCR) -> Self { RequestGenerator { rb, _phantom_data: PhantomData, diff --git a/src/dma/mux/shared.rs b/src/dma/mux/shared.rs index d8265697..cfbb32bf 100644 --- a/src/dma/mux/shared.rs +++ b/src/dma/mux/shared.rs @@ -3,7 +3,7 @@ use super::super::stm32::dmamux1::{CFR, CSR, RGCFR, RGSR}; pub struct MuxIsr { pub(in super::super) csr: &'static CSR, /// This field *must not* be mutated using shared references - pub(in super::super) cfr: &'static mut CFR, + pub(in super::super) cfr: &'static CFR, } unsafe impl Send for MuxIsr {} @@ -12,7 +12,16 @@ unsafe impl Sync for MuxIsr {} pub struct RequestGenIsr { pub(super) rgsr: &'static RGSR, /// This field *must not* be mutated using shared references - pub(super) rgcfr: &'static mut RGCFR, + pub(super) rgcfr: &'static RGCFR, +} + +impl RequestGenIsr { + pub(in super::super) fn new( + rgsr: &'static RGSR, + rgcfr: &'static RGCFR, + ) -> Self { + RequestGenIsr { rgsr, rgcfr } + } } unsafe impl Send for RequestGenIsr {} diff --git a/src/dma/safe_transfer.rs b/src/dma/safe_transfer.rs index e6da23fb..39f6a3ed 100644 --- a/src/dma/safe_transfer.rs +++ b/src/dma/safe_transfer.rs @@ -17,7 +17,7 @@ unsafe impl TransferState for Start {} pub struct Ongoing where - CXX: ChannelId, + CXX: ChannelId, DMA: DMATrait, { pub(super) stream: Stream, @@ -25,7 +25,7 @@ where unsafe impl TransferState for Ongoing where - CXX: ChannelId, + CXX: ChannelId, DMA: DMATrait, { } @@ -996,7 +996,7 @@ pub(super) fn configure_safe_transfer( source: ImmutableBuffer, dest: &MutableBuffer, ) where - CXX: ChannelId, + CXX: ChannelId, DMA: DMATrait, Source: Payload, Dest: Payload, @@ -1021,7 +1021,7 @@ fn configure_buffers( peripheral: PeripheralBuffer, memory: MemoryBuffer, ) where - CXX: ChannelId, + CXX: ChannelId, DMA: DMATrait, Peripheral: Payload, Memory: Payload, @@ -1074,7 +1074,7 @@ fn configure_ndt( peripheral: PeripheralBuffer, memory: MemoryBuffer, ) where - CXX: ChannelId, + CXX: ChannelId, DMA: DMATrait, Peripheral: Payload, Memory: Payload, @@ -1112,7 +1112,7 @@ fn configure_ndt( pub(super) fn check_double_buffer_stream_config( stream: &Stream, ) where - CXX: ChannelId, + CXX: ChannelId, DMA: DMATrait, { if stream.transfer_direction() == TransferDirection::M2M { diff --git a/src/dma/stream.rs b/src/dma/stream.rs index 7173f774..115e8df3 100644 --- a/src/dma/stream.rs +++ b/src/dma/stream.rs @@ -207,12 +207,32 @@ where pub(super) lisr: &'static LISR, pub(super) hisr: &'static HISR, /// This field *must not* be mutated using shared references - pub(super) lifcr: &'static mut LIFCR, + pub(super) lifcr: &'static LIFCR, /// This field *must not* be mutated using shared references - pub(super) hifcr: &'static mut HIFCR, + pub(super) hifcr: &'static HIFCR, _phantom_data: PhantomData, } +impl StreamIsr +where + DMA: DMATrait, +{ + pub(super) fn new( + lisr: &'static LISR, + hisr: &'static HISR, + lifcr: &'static LIFCR, + hifcr: &'static HIFCR, + ) -> Self { + StreamIsr { + lisr, + hisr, + lifcr, + hifcr, + _phantom_data: PhantomData, + } + } +} + unsafe impl Send for StreamIsr where DMA: DMATrait {} unsafe impl Sync for StreamIsr where DMA: DMATrait {} From 66156aaea0407d286af44dbd29feef92af1b57da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ad=C3=A4?= Date: Sun, 22 Dec 2019 16:23:13 +0100 Subject: [PATCH 038/103] Removed example (didn't mean to push that) --- examples/dma.rs | 62 ------------------------------------------------- 1 file changed, 62 deletions(-) delete mode 100644 examples/dma.rs diff --git a/examples/dma.rs b/examples/dma.rs deleted file mode 100644 index abbd7746..00000000 --- a/examples/dma.rs +++ /dev/null @@ -1,62 +0,0 @@ -#![deny(unsafe_code)] -#![no_main] -#![no_std] - -extern crate panic_itm; - -use cortex_m; -use cortex_m_rt::entry; - -use stm32h7xx_hal::{adc, delay::Delay, pac, prelude::*}; - -use cortex_m_log::println; -use cortex_m_log::{ - destination::Itm, printer::itm::InterruptSync as InterruptSyncItm, -}; - -#[entry] -fn main() -> ! { - let cp = cortex_m::Peripherals::take().unwrap(); - let dp = pac::Peripherals::take().unwrap(); - let mut log = InterruptSyncItm::new(Itm::new(cp.ITM)); - - // Constrain and Freeze power - println!(log, "Setup PWR... "); - let pwr = dp.PWR.constrain(); - let vos = pwr.freeze(); - - // Constrain and Freeze clock - println!(log, "Setup RCC... "); - let rcc = dp.RCC.constrain(); - - // setting this per_ck to 4 Mhz here (which is gonna choose the CSI that runs at exactly 4 Mhz) as the adc requires per_ck as its - // own kernel clock and wouldn't work at all if per_ck wouldnt be enabled or loose a few bits if it was too fast - // (the maximum for this is 36 Mhz) - let mut ccdr = rcc - .sys_ck(100.mhz()) - .per_ck(4.mhz()) - .freeze(vos, &dp.SYSCFG); - - let mut delay = Delay::new(cp.SYST, ccdr.clocks); - - // Setup ADC - let mut adc3 = adc::Adc::adc3(dp.ADC3, &mut delay, &mut ccdr).enable(); - adc3.set_resolution(adc::Resolution::SIXTEENBIT); - - // Setup GPIOC - let gpioc = dp.GPIOC.split(&mut ccdr.ahb4); - - // Configure pc0 as an analog input - let mut channel = gpioc.pc0.into_analog(); - - loop { - let data: u32 = adc3.read(&mut channel).unwrap(); - // voltage = reading * (vref/resolution) - println!( - log, - "ADC reading: {}, voltage for nucleo: {}", - data, - data as f32 * (3.3 / adc3.max_sample() as f32) - ); - } -} From c3689f0465d95cfcbe9ee2292f33264ff2be7d1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ad=C3=A4?= Date: Sun, 22 Dec 2019 17:01:46 +0100 Subject: [PATCH 039/103] Changed rcc type from RCC to Ccdr --- src/dma.rs | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/dma.rs b/src/dma.rs index a4557a47..7aaea412 100644 --- a/src/dma.rs +++ b/src/dma.rs @@ -45,6 +45,7 @@ use self::stream::{ TransferErrorInterrupt, TransferMode, ED as EDTrait, }; use crate::nb::{self, block, Error as NbError}; +use crate::rcc::Ccdr; use core::convert::{Infallible, TryFrom, TryInto}; use core::marker::PhantomData; use core::mem; @@ -1995,10 +1996,10 @@ impl Dma { dma_1: DMA1, dma_2: DMA2, mut dma_mux: DMAMUX1, - rcc: &mut RCC, + ccdr: &mut Ccdr, ) -> Self { - Dma::reset_dma(rcc); - Dma::enable_dma(rcc); + Dma::reset_dma(&mut ccdr.rb); + Dma::enable_dma(&mut ccdr.rb); Dma::reset_mux(&mut dma_mux); @@ -2209,22 +2210,22 @@ pub trait DmaExt: DMATrait { self, other_dma: Self::Other, dma_mux: DMAMUX1, - rcc: &mut RCC, + ccdr: &mut Ccdr, ) -> Dma; } impl DmaExt for DMA1 { type Other = DMA2; - fn dma(self, dma_2: DMA2, dma_mux: DMAMUX1, rcc: &mut RCC) -> Dma { - Dma::new(self, dma_2, dma_mux, rcc) + fn dma(self, dma_2: DMA2, dma_mux: DMAMUX1, ccdr: &mut Ccdr) -> Dma { + Dma::new(self, dma_2, dma_mux, ccdr) } } impl DmaExt for DMA2 { type Other = DMA1; - fn dma(self, dma_1: DMA1, dma_mux: DMAMUX1, rcc: &mut RCC) -> Dma { - Dma::new(dma_1, self, dma_mux, rcc) + fn dma(self, dma_1: DMA1, dma_mux: DMAMUX1, ccdr: &mut Ccdr) -> Dma { + Dma::new(dma_1, self, dma_mux, ccdr) } } From b189688925aa456de4be3efdc3ca052445c97237 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ad=C3=A4?= Date: Sun, 22 Dec 2019 17:10:25 +0100 Subject: [PATCH 040/103] Added DmaExt to prelude --- src/prelude.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/prelude.rs b/src/prelude.rs index 981954b3..ad28662d 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -3,6 +3,7 @@ pub use embedded_hal::prelude::*; pub use crate::adc::AdcExt as _stm32h7xx_hal_adc_AdcExt; pub use crate::delay::DelayExt as _stm32h7xx_hal_delay_DelayExt; +pub use crate::dma::DmaExt as _stm32h7xx_hal_dma_DmaExt; pub use crate::flash::FlashExt as _stm32h7xx_hal_flash_FlashExt; pub use crate::gpio::GpioExt as _stm32h7xx_hal_gpio_GpioExt; pub use crate::i2c::I2cExt as _stm32h7xx_hal_i2c_I2cExt; From d62d6b196a3e4ff22571f3868e5170dbc6068a82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ad=C3=A4?= Date: Mon, 23 Dec 2019 13:48:39 +0100 Subject: [PATCH 041/103] Fixed compilation issue for other mcus --- src/prelude.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/prelude.rs b/src/prelude.rs index ad28662d..dd95b165 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -3,6 +3,7 @@ pub use embedded_hal::prelude::*; pub use crate::adc::AdcExt as _stm32h7xx_hal_adc_AdcExt; pub use crate::delay::DelayExt as _stm32h7xx_hal_delay_DelayExt; +#[cfg(feature = "stm32h743")] pub use crate::dma::DmaExt as _stm32h7xx_hal_dma_DmaExt; pub use crate::flash::FlashExt as _stm32h7xx_hal_flash_FlashExt; pub use crate::gpio::GpioExt as _stm32h7xx_hal_gpio_GpioExt; From 9c73e3b352fd86f811e9b5d9965f7139710b71d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ad=C3=A4?= Date: Tue, 24 Dec 2019 16:43:21 +0100 Subject: [PATCH 042/103] uhh hard to explain :) (fixed config register assignment of dma2 streams) --- src/dma.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/dma.rs b/src/dma.rs index 7aaea412..da8632b6 100644 --- a/src/dma.rs +++ b/src/dma.rs @@ -2071,35 +2071,35 @@ impl Dma { let channels_dma_2 = ( Channel { - stream: Stream::after_reset(&dma1_rb.st[0]), + stream: Stream::after_reset(&dma2_rb.st[0]), mux: DmaMux::after_reset(&dma_mux_rb.ccr[8]), }, Channel { - stream: Stream::after_reset(&dma1_rb.st[1]), + stream: Stream::after_reset(&dma2_rb.st[1]), mux: DmaMux::after_reset(&dma_mux_rb.ccr[9]), }, Channel { - stream: Stream::after_reset(&dma1_rb.st[2]), + stream: Stream::after_reset(&dma2_rb.st[2]), mux: DmaMux::after_reset(&dma_mux_rb.ccr[10]), }, Channel { - stream: Stream::after_reset(&dma1_rb.st[3]), + stream: Stream::after_reset(&dma2_rb.st[3]), mux: DmaMux::after_reset(&dma_mux_rb.ccr[11]), }, Channel { - stream: Stream::after_reset(&dma1_rb.st[4]), + stream: Stream::after_reset(&dma2_rb.st[4]), mux: DmaMux::after_reset(&dma_mux_rb.ccr[12]), }, Channel { - stream: Stream::after_reset(&dma1_rb.st[5]), + stream: Stream::after_reset(&dma2_rb.st[5]), mux: DmaMux::after_reset(&dma_mux_rb.ccr[13]), }, Channel { - stream: Stream::after_reset(&dma1_rb.st[6]), + stream: Stream::after_reset(&dma2_rb.st[6]), mux: DmaMux::after_reset(&dma_mux_rb.ccr[14]), }, Channel { - stream: Stream::after_reset(&dma1_rb.st[7]), + stream: Stream::after_reset(&dma2_rb.st[7]), mux: DmaMux::after_reset(&dma_mux_rb.ccr[15]), }, ); From 965802233a68ff683fc1c8f6605c2480f45754de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ad=C3=A4?= Date: Tue, 24 Dec 2019 17:34:32 +0100 Subject: [PATCH 043/103] Moved RAM into AXISRAM --- memory.x | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/memory.x b/memory.x index 27c21c6b..79c5521f 100644 --- a/memory.x +++ b/memory.x @@ -3,10 +3,9 @@ MEMORY /* FLASH and RAM are mandatory memory regions */ FLASH : ORIGIN = 0x08000000, LENGTH = 1024K FLASH1 : ORIGIN = 0x08100000, LENGTH = 1024K - RAM : ORIGIN = 0x20000000, LENGTH = 128K - /* AXISRAM */ - AXISRAM : ORIGIN = 0x24000000, LENGTH = 512K + /* AXISRAM = RAM */ + RAM : ORIGIN = 0x24000000, LENGTH = 512K /* SRAM */ SRAM1 : ORIGIN = 0x30000000, LENGTH = 128K @@ -19,6 +18,9 @@ MEMORY /* Instruction TCM */ ITCM : ORIGIN = 0x00000000, LENGTH = 64K + + /* Data TCM */ + DTCM : ORIGIN = 0x20000000, LENGTH = 128K } /* The location of the stack can be overridden using the From 1674e8094063aca8e3995386aa3364fc14055687 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ad=C3=A4?= Date: Tue, 24 Dec 2019 18:43:29 +0100 Subject: [PATCH 044/103] Added effective_buffer_mode and fixed effective_circular_mode methods for dma stream --- src/dma.rs | 42 ++++++++++++++++++++++++++++++++++++---- src/dma/safe_transfer.rs | 7 +++++-- 2 files changed, 43 insertions(+), 6 deletions(-) diff --git a/src/dma.rs b/src/dma.rs index da8632b6..2c2a5d1f 100644 --- a/src/dma.rs +++ b/src/dma.rs @@ -230,9 +230,12 @@ where } /// **Note** (for disabled streams): - /// This config value gets forced to `Circular`, if `buffer_mode` is `DoubleBuffer`. + /// This config value gets forced /// - /// This invariant is covered in `effective_circular_mode`. + /// - **by hardware** to `Enabled`, if `buffer_mode` is `DoubleBuffer`. + /// - **by software** to `Disabled` if `transfer_direction` is `M2M`. + /// + /// These invariants is covered in `effective_circular_mode`. pub fn circular_mode(&self) -> CircularMode { self.rb.cr.read().circ().bit().into() } @@ -271,6 +274,13 @@ where self.rb.cr.read().pl().bits().try_into().unwrap() } + /// **Note** (for disabled streams): + /// This config value gets forced to `Regular` **by software** (to avoid TransferError-Flag), if + /// + /// - `TransferDirection` is `M2M` or + /// - `FlowController` is `Peripheral` + /// + /// These invariants are covered in `effective_buffer_mode` (defined for disabled streams). pub fn buffer_mode(&self) -> BufferMode { self.rb.cr.read().dbm().bit().into() } @@ -505,13 +515,22 @@ where } pub fn effective_circular_mode(&self) -> CircularMode { - if self.buffer_mode() == BufferMode::DoubleBuffer { + if !self.circular_mode_possible() { + CircularMode::Disabled + } else if self.buffer_mode() == BufferMode::DoubleBuffer { CircularMode::Enabled } else { self.circular_mode() } } + fn circular_mode_possible(&self) -> bool { + // `effective_flow_controller` not needed because `flow_controller` gets only forced to + // `DMA`, if `transfer_dir` is `M2M`, which is already covered in first case. + self.transfer_direction() != TransferDirection::M2M + && self.flow_controller() == FlowController::Dma + } + pub fn effective_m_size(&self) -> MSize { if self.transfer_mode() == TransferMode::Direct { match self.p_size() { @@ -524,6 +543,14 @@ where } } + pub fn effective_buffer_mode(&self) -> BufferMode { + if !self.circular_mode_possible() { + BufferMode::Regular + } else { + self.buffer_mode() + } + } + pub fn effective_pincos(&self) -> Option { if self.pinc() == Pinc::Fixed { return None; @@ -601,9 +628,16 @@ where /// # Safety /// /// Aliasing rules aren't enforced - pub unsafe fn enable(self) -> Stream { + pub unsafe fn enable(mut self) -> Stream { self.check_config(); + // To avoid TransferErrorInterrupt because of invalid configuration + self.set_buffer_mode(self.effective_buffer_mode()); + // Only in this case we need to force this value **by software** + if self.transfer_direction() == TransferDirection::M2M { + self.set_circular_mode(CircularMode::Disabled); + } + self.enable_unchecked() } diff --git a/src/dma/safe_transfer.rs b/src/dma/safe_transfer.rs index 39f6a3ed..57bb9b2f 100644 --- a/src/dma/safe_transfer.rs +++ b/src/dma/safe_transfer.rs @@ -1,7 +1,8 @@ use super::channel::ChannelId; use super::stream::{ - Disabled, Enabled, FlowController, IsrCleared, IsrUncleared, M0a, MSize, - Minc, Ndt, PSize, Pa, Pinc, Pincos, TransferDirection, TransferMode, + BufferMode, Disabled, Enabled, FlowController, IsrCleared, IsrUncleared, + M0a, MSize, Minc, Ndt, PSize, Pa, Pinc, Pincos, TransferDirection, + TransferMode, }; use super::{DMATrait, Stream}; use core::convert::TryFrom; @@ -1122,6 +1123,8 @@ pub(super) fn check_double_buffer_stream_config( if stream.effective_flow_controller() == FlowController::Peripheral { panic!("The flow controller must not be `Peripheral` when configuring double buffer streams."); } + + debug_assert_eq!(stream.effective_buffer_mode(), BufferMode::DoubleBuffer); } pub(super) fn check_double_buffer_mut( From 5292c1fd27b04dc07dc93fc54695a19e927a49fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ad=C3=A4?= Date: Wed, 25 Dec 2019 00:56:21 +0100 Subject: [PATCH 045/103] Added AsImmutable trait --- src/dma/safe_transfer.rs | 180 +++++++++++++++++++++++++++++++++------ 1 file changed, 154 insertions(+), 26 deletions(-) diff --git a/src/dma/safe_transfer.rs b/src/dma/safe_transfer.rs index 57bb9b2f..0b229ca4 100644 --- a/src/dma/safe_transfer.rs +++ b/src/dma/safe_transfer.rs @@ -115,6 +115,17 @@ unsafe impl Payload for i32 {} unsafe impl Payload for f32 {} +pub trait AsImmutable<'s> { + type Target: 's; + + /// # Safety + /// + /// All unsafe methods of `Self` remain unsafe. + /// + /// If `Self` was already immutable, this is safe. + unsafe fn as_immutable(&'s self) -> Self::Target; +} + #[derive(Clone, Copy)] pub enum ImmutableBuffer<'buf, 'wo, BUF> where @@ -145,6 +156,17 @@ where } } +impl<'s, BUF> AsImmutable<'s> for ImmutableBuffer<'_, '_, BUF> +where + BUF: Payload, +{ + type Target = ImmutableBuffer<'s, 's, BUF>; + + unsafe fn as_immutable(&self) -> ImmutableBuffer { + *self + } +} + pub type ImmutableBufferStatic<'wo, BUF> = ImmutableBuffer<'static, 'wo, BUF>; pub enum MutableBuffer<'buf, 'wo, BUF> @@ -208,12 +230,15 @@ where panic!("The buffer is a memory buffer."); } } +} - /// # Safety - /// - /// `ImmutableBuffer` assumes that the DMA is only reading the buffer. - /// Therefore the getters of the immutable version are as unsafe as the getters of this struct. - pub unsafe fn as_immutable(&self) -> ImmutableBuffer { +impl<'s, BUF> AsImmutable<'s> for MutableBuffer<'_, '_, BUF> +where + BUF: Payload, +{ + type Target = ImmutableBuffer<'s, 's, BUF>; + + unsafe fn as_immutable(&'s self) -> ImmutableBuffer { match self { MutableBuffer::Memory(buffer) => { ImmutableBuffer::Memory(buffer.as_immutable()) @@ -257,6 +282,17 @@ where } } +impl<'s, BUF> AsImmutable<'s> for MemoryBuffer<'_, BUF> +where + BUF: Payload, +{ + type Target = MemoryBuffer<'s, BUF>; + + unsafe fn as_immutable(&self) -> MemoryBuffer { + *self + } +} + pub type MemoryBufferStatic = MemoryBuffer<'static, BUF>; pub enum MemoryBufferMut<'buf, BUF> @@ -320,12 +356,15 @@ where panic!("The buffer is fixed."); } } +} - /// # Safety - /// - /// `MemoryBuffer` assumes that the DMA is only reading the buffer. - /// Therefore the getters of the immutable version are as unsafe as the getters of this struct. - pub unsafe fn as_immutable(&self) -> MemoryBuffer { +impl<'s, BUF> AsImmutable<'s> for MemoryBufferMut<'_, BUF> +where + BUF: Payload, +{ + type Target = MemoryBuffer<'s, BUF>; + + unsafe fn as_immutable(&self) -> MemoryBuffer { match self { MemoryBufferMut::Fixed(buffer) => { MemoryBuffer::Fixed(buffer.as_immutable()) @@ -369,6 +408,17 @@ where } } +impl<'s, BUF> AsImmutable<'s> for PeripheralBuffer<'_, '_, BUF> +where + BUF: Payload, +{ + type Target = PeripheralBuffer<'s, 's, BUF>; + + unsafe fn as_immutable(&self) -> PeripheralBuffer { + *self + } +} + pub type PeripheralBufferStatic<'wo, BUF> = PeripheralBuffer<'static, 'wo, BUF>; pub enum PeripheralBufferMut<'buf, 'wo, BUF> @@ -449,6 +499,24 @@ where } } +impl<'s, BUF> AsImmutable<'s> for PeripheralBufferMut<'_, '_, BUF> +where + BUF: Payload, +{ + type Target = PeripheralBuffer<'s, 's, BUF>; + + unsafe fn as_immutable(&self) -> PeripheralBuffer { + match self { + PeripheralBufferMut::Fixed(buffer) => { + PeripheralBuffer::Fixed(buffer.as_immutable()) + } + PeripheralBufferMut::Incremented(buffer) => { + PeripheralBuffer::Incremented(buffer.as_immutable()) + } + } + } +} + pub type PeripheralBufferMutStatic<'wo, BUF> = PeripheralBufferMut<'static, 'wo, BUF>; @@ -504,6 +572,17 @@ where } } +impl<'s, BUF> AsImmutable<'s> for IncrementedBuffer<'_, '_, BUF> +where + BUF: Payload, +{ + type Target = IncrementedBuffer<'s, 's, BUF>; + + unsafe fn as_immutable(&self) -> IncrementedBuffer { + *self + } +} + pub type IncrementedBufferStatic<'wo, BUF> = IncrementedBuffer<'static, 'wo, BUF>; @@ -620,12 +699,19 @@ where } } } +} + +impl<'s, BUF> AsImmutable<'s> for IncrementedBufferMut<'_, '_, BUF> +where + BUF: Payload, +{ + type Target = IncrementedBuffer<'s, 's, BUF>; /// # Safety /// /// `IncrementedBuffer` assumes that the DMA is only reading the buffer. /// Therefore the getters of the immutable version are as unsafe as the getters of this struct. - pub unsafe fn as_immutable(&self) -> IncrementedBuffer { + unsafe fn as_immutable(&self) -> IncrementedBuffer { match self { IncrementedBufferMut::RegularOffset(buffer) => { IncrementedBuffer::RegularOffset(buffer.as_immutable()) @@ -662,6 +748,17 @@ where } } +impl<'s, BUF> AsImmutable<'s> for FixedBuffer<'_, BUF> +where + BUF: Payload, +{ + type Target = FixedBuffer<'s, BUF>; + + unsafe fn as_immutable(&self) -> FixedBuffer { + *self + } +} + unsafe impl Send for FixedBuffer<'_, BUF> where BUF: Payload {} unsafe impl Sync for FixedBuffer<'_, BUF> where BUF: Payload {} @@ -701,12 +798,15 @@ where pub fn as_mut_ptr(&mut self) -> *mut BUF { self.0 } +} - /// # Safety - /// - /// `FixedBuffer` assumes that the DMA is only reading the buffer. - /// Therefore the getters of the immutable version are as unsafe as the getters of this struct. - pub unsafe fn as_immutable(&self) -> FixedBuffer { +impl<'s, BUF> AsImmutable<'s> for FixedBufferMut<'_, BUF> +where + BUF: Payload, +{ + type Target = FixedBuffer<'s, BUF>; + + unsafe fn as_immutable(&self) -> FixedBuffer { FixedBuffer(self.0, PhantomData) } } @@ -752,6 +852,17 @@ where } } +impl<'s, BUF> AsImmutable<'s> for RegularOffsetBuffer<'_, BUF> +where + BUF: Payload, +{ + type Target = RegularOffsetBuffer<'s, BUF>; + + unsafe fn as_immutable(&self) -> RegularOffsetBuffer { + *self + } +} + unsafe impl Send for RegularOffsetBuffer<'_, BUF> where BUF: Payload {} unsafe impl Sync for RegularOffsetBuffer<'_, BUF> where BUF: Payload {} @@ -811,12 +922,15 @@ where slice.len() } } +} - /// # Safety - /// - /// `RegularOffsetBuffer` assumes that the DMA is only reading the buffer. - /// Therefore the getters of the immutable version are as unsafe as the getters of this struct. - pub unsafe fn as_immutable(&self) -> RegularOffsetBuffer { +impl<'s, BUF> AsImmutable<'s> for RegularOffsetBufferMut<'_, BUF> +where + BUF: Payload, +{ + type Target = RegularOffsetBuffer<'s, BUF>; + + unsafe fn as_immutable(&self) -> RegularOffsetBuffer { RegularOffsetBuffer(self.0, PhantomData) } } @@ -875,6 +989,17 @@ where } } +impl<'s, BUF> AsImmutable<'s> for WordOffsetBuffer<'_, '_, BUF> +where + BUF: Payload, +{ + type Target = WordOffsetBuffer<'s, 's, BUF>; + + unsafe fn as_immutable(&self) -> WordOffsetBuffer { + *self + } +} + unsafe impl<'buf, 'wo, BUF> Send for WordOffsetBuffer<'buf, 'wo, BUF> where BUF: Payload { @@ -934,12 +1059,15 @@ where pub fn len(&self) -> usize { self.0.len() } +} - /// # Safety - /// - /// `WordOffsetBuffer` assumes that the DMA is only reading the buffer. - /// Therefore the getters of the immutable version are as unsafe as the getters of this struct. - pub unsafe fn as_immutable(&self) -> WordOffsetBuffer { +impl<'s, BUF> AsImmutable<'s> for WordOffsetBufferMut<'_, '_, BUF> +where + BUF: Payload, +{ + type Target = WordOffsetBuffer<'s, 's, BUF>; + + unsafe fn as_immutable(&self) -> WordOffsetBuffer { WordOffsetBuffer(&*(self.0 as *const _ as *const _), PhantomData) } } From 16a617b4a02577813c8c3a7ba916a6f292ecf451 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ad=C3=A4?= Date: Wed, 25 Dec 2019 01:59:48 +0100 Subject: [PATCH 046/103] Using AsImmutable when input type might me mutable --- src/dma.rs | 16 ++++++++-------- src/dma/safe_transfer.rs | 24 +++++++++--------------- 2 files changed, 17 insertions(+), 23 deletions(-) diff --git a/src/dma.rs b/src/dma.rs index 2c2a5d1f..b31f9e65 100644 --- a/src/dma.rs +++ b/src/dma.rs @@ -25,12 +25,12 @@ use self::mux::{ SyncEnabled, SyncId, SyncOverrunInterrupt, SyncPolarity, }; use self::safe_transfer::{ - check_double_buffer, check_double_buffer_mut, - check_double_buffer_stream_config, configure_safe_transfer, - double_buffer_idx, DoubleBuffer, ImmutableBuffer, ImmutableBufferStatic, - MemoryBuffer, MemoryBufferMut, MemoryBufferMutStatic, MemoryBufferStatic, - MutableBuffer, MutableBufferStatic, Ongoing, Payload, - PeripheralBufferMutStatic, PeripheralBufferStatic, Start, TransferState, + check_double_buffer, check_double_buffer_stream_config, + configure_safe_transfer, double_buffer_idx, DoubleBuffer, ImmutableBuffer, + ImmutableBufferStatic, MemoryBuffer, MemoryBufferMut, + MemoryBufferMutStatic, MemoryBufferStatic, MutableBuffer, + MutableBufferStatic, Ongoing, Payload, PeripheralBufferMutStatic, + PeripheralBufferStatic, Start, TransferState, }; use self::stm32::dma1::ST; use self::stm32::dmamux1::CCR; @@ -1580,7 +1580,7 @@ where sources: [MemoryBufferStatic; 2], dest: PeripheralBufferMutStatic<'wo, Dest>, ) -> Self { - check_double_buffer(sources); + check_double_buffer(&sources); SafeTransferDoubleBufferR { sources, @@ -1776,7 +1776,7 @@ where source: PeripheralBufferStatic<'wo, Source>, dests: [MemoryBufferMutStatic; 2], ) -> Self { - check_double_buffer_mut(&dests); + check_double_buffer(&dests); SafeTransferDoubleBufferW { source, diff --git a/src/dma/safe_transfer.rs b/src/dma/safe_transfer.rs index 0b229ca4..5ce13ca0 100644 --- a/src/dma/safe_transfer.rs +++ b/src/dma/safe_transfer.rs @@ -1255,24 +1255,18 @@ pub(super) fn check_double_buffer_stream_config( debug_assert_eq!(stream.effective_buffer_mode(), BufferMode::DoubleBuffer); } -pub(super) fn check_double_buffer_mut( - double_buffer: &[MemoryBufferMut; 2], +pub(super) fn check_double_buffer<'s, MemBuf, BUF>( + double_buffer: &'s [MemBuf; 2], ) where + MemBuf: AsImmutable<'s, Target = MemoryBuffer<'s, BUF>>, BUF: Payload, { - unsafe { - let [buffer_0, buffer_1] = double_buffer; - let double_buffer_immutable = - [buffer_0.as_immutable(), buffer_1.as_immutable()]; - - check_double_buffer(double_buffer_immutable); - } -} - -pub(super) fn check_double_buffer(double_buffer: [MemoryBuffer; 2]) -where - BUF: Payload, -{ + let double_buffer = unsafe { + [ + double_buffer[0].as_immutable(), + double_buffer[1].as_immutable(), + ] + }; match double_buffer[0] { MemoryBuffer::Fixed(_) => { if let MemoryBuffer::Incremented(_) = double_buffer[1] { From 08213eb53b096765d7d4ab53f144afa3a60b3ad2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ad=C3=A4?= Date: Wed, 25 Dec 2019 12:35:51 +0100 Subject: [PATCH 047/103] bit of rework --- src/dma.rs | 158 ++++++++++++++++----------------------- src/dma/safe_transfer.rs | 24 ++++-- 2 files changed, 81 insertions(+), 101 deletions(-) diff --git a/src/dma.rs b/src/dma.rs index b31f9e65..71449cef 100644 --- a/src/dma.rs +++ b/src/dma.rs @@ -26,11 +26,10 @@ use self::mux::{ }; use self::safe_transfer::{ check_double_buffer, check_double_buffer_stream_config, - configure_safe_transfer, double_buffer_idx, DoubleBuffer, ImmutableBuffer, - ImmutableBufferStatic, MemoryBuffer, MemoryBufferMut, - MemoryBufferMutStatic, MemoryBufferStatic, MutableBuffer, - MutableBufferStatic, Ongoing, Payload, PeripheralBufferMutStatic, - PeripheralBufferStatic, Start, TransferState, + configure_safe_transfer, first_ptr_from_buffer, ImmutableBuffer, + ImmutableBufferStatic, MemoryBufferMutStatic, MemoryBufferStatic, + MutableBuffer, MutableBufferStatic, Ongoing, Payload, + PeripheralBufferMutStatic, PeripheralBufferStatic, Start, TransferState, }; use self::stm32::dma1::ST; use self::stm32::dmamux1::CCR; @@ -1710,44 +1709,24 @@ where self.state.stream.set_fifo_error_interrupt(fe_intrpt); } - pub fn set_double_buffer( - &mut self, - buffer: MemoryBufferStatic, - double_buffer: DoubleBuffer, - ) { - let address = match buffer { - MemoryBuffer::Fixed(buffer) => { - // `self.sources[0]` and `self.sources[1]` have the same increment mode - if let MemoryBuffer::Incremented(_) = self.sources[0] { - panic!("The new buffer is fixed, but the old one is incremented."); - } - - buffer.as_ptr() as u32 - } - MemoryBuffer::Incremented(buffer) => { - // `self.sources[0]` and `self.sources[1]` have the same len - if buffer.len() != self.sources[0].incremented().len() { - panic!("The new buffer must have the same size as the old buffer."); - } + pub fn set_m0a(&mut self, m0a: MemoryBufferStatic) { + let ptr = first_ptr_from_buffer(&ImmutableBuffer::Memory(m0a)); - buffer.as_ptr(0) as u32 - } - }; + mem::replace(&mut self.sources[0], m0a); - match double_buffer { - DoubleBuffer::First => { - let m0a = M0a(address); - block!(self.state.stream.set_m0a(m0a)).unwrap(); + check_double_buffer(&self.sources); - mem::replace(&mut self.sources[0], buffer); - } - DoubleBuffer::Second => { - let m1a = M1a(address); - block!(self.state.stream.set_m1a(m1a)).unwrap(); + block!(self.state.stream.set_m0a(M0a(ptr as u32))).unwrap(); + } - mem::replace(&mut self.sources[1], buffer); - } - } + pub fn set_m1a(&mut self, m1a: MemoryBufferStatic) { + let ptr = first_ptr_from_buffer(&ImmutableBuffer::Memory(m1a)); + + mem::replace(&mut self.sources[1], m1a); + + check_double_buffer(&self.sources); + + block!(self.state.stream.set_m1a(M1a(ptr as u32))).unwrap(); } pub fn stop(self) -> Stream { @@ -1804,44 +1783,53 @@ where /// # Safety /// /// The caller must ensure, that the DMA is currently not modifying this address. - pub unsafe fn set_dest_fixed( + pub unsafe fn set_dest_fixed_m0a(&mut self, payload: Dest) { + self.dests[0].as_mut_fixed().set(payload); + } + + /// # Safety + /// + /// The caller must ensure, that the DMA is currently not modifying this address. + pub unsafe fn set_dest_fixed_m1a(&mut self, payload: Dest) { + self.dests[1].as_mut_fixed().set(payload); + } + + /// # Safety + /// + /// The caller must ensure, that the DMA is currently not modifying this address. + pub unsafe fn set_dest_incremented_m0a( &mut self, + index: usize, payload: Dest, - buffer: DoubleBuffer, ) { - let idx = double_buffer_idx(buffer); - - self.dests[idx].as_mut_fixed().set(payload); + self.dests[0].as_mut_incremented().set(index, payload); } /// # Safety /// /// The caller must ensure, that the DMA is currently not modifying this address. - pub unsafe fn set_dest_incremented( + pub unsafe fn set_dest_incremented_m1a( &mut self, index: usize, payload: Dest, - buffer: DoubleBuffer, ) { - let idx = double_buffer_idx(buffer); - - self.dests[idx].as_mut_incremented().set(index, payload); + self.dests[1].as_mut_incremented().set(index, payload); } - pub fn dest_ptr_fixed(&mut self, buffer: DoubleBuffer) -> *mut Dest { - let idx = double_buffer_idx(buffer); + pub fn dest_ptr_fixed_m0a(&mut self) -> *mut Dest { + self.dests[0].as_mut_fixed().as_mut_ptr() + } - self.dests[idx].as_mut_fixed().as_mut_ptr() + pub fn dest_ptr_fixed_m1a(&mut self) -> *mut Dest { + self.dests[1].as_mut_fixed().as_mut_ptr() } - pub fn dest_ptr_incremented( - &mut self, - index: usize, - buffer: DoubleBuffer, - ) -> *mut Dest { - let idx = double_buffer_idx(buffer); + pub fn dest_ptr_incremented_m0a(&mut self, index: usize) -> *mut Dest { + self.dests[0].as_mut_incremented().as_mut_ptr(index) + } - self.dests[idx].as_mut_incremented().as_mut_ptr(index) + pub fn dest_ptr_incremented_m1a(&mut self, index: usize) -> *mut Dest { + self.dests[1].as_mut_incremented().as_mut_ptr(index) } } @@ -1928,44 +1916,28 @@ where self.state.stream.set_fifo_error_interrupt(fe_intrpt); } - pub fn set_double_buffer( - &mut self, - buffer: MemoryBufferMutStatic, - double_buffer: DoubleBuffer, - ) { - let address = match &buffer { - MemoryBufferMut::Fixed(buffer) => { - // `self.dests[0]` and `self.dests[1]` have the same increment mode - if let MemoryBufferMut::Incremented(_) = &self.dests[0] { - panic!("The new buffer is fixed, but the old one is incremented."); - } - - buffer.as_ptr() as u32 - } - MemoryBufferMut::Incremented(buffer) => { - // `self.sources[0]` and `self.sources[1]` have the same len - if buffer.len() != self.dests[0].as_incremented().len() { - panic!("The new buffer must have the same size as the old buffer."); - } + pub fn set_m0a(&mut self, m0a: MemoryBufferMutStatic) { + let m0a = MutableBuffer::Memory(m0a); + let ptr = first_ptr_from_buffer(&m0a); + let m0a = m0a.into_memory(); - buffer.as_ptr(0) as u32 - } - }; + mem::replace(&mut self.dests[0], m0a); - match double_buffer { - DoubleBuffer::First => { - let m0a = M0a(address); - block!(self.state.stream.set_m0a(m0a)).unwrap(); + check_double_buffer(&self.dests); - mem::replace(&mut self.dests[0], buffer); - } - DoubleBuffer::Second => { - let m1a = M1a(address); - block!(self.state.stream.set_m1a(m1a)).unwrap(); + block!(self.state.stream.set_m0a(M0a(ptr as u32))).unwrap(); + } - mem::replace(&mut self.dests[1], buffer); - } - } + pub fn set_m1a(&mut self, m1a: MemoryBufferMutStatic) { + let m1a = MutableBuffer::Memory(m1a); + let ptr = first_ptr_from_buffer(&m1a); + let m1a = m1a.into_memory(); + + mem::replace(&mut self.dests[1], m1a); + + check_double_buffer(&self.dests); + + block!(self.state.stream.set_m1a(M1a(ptr as u32))).unwrap(); } pub fn stop(self) -> Stream { diff --git a/src/dma/safe_transfer.rs b/src/dma/safe_transfer.rs index 5ce13ca0..7de8aa09 100644 --- a/src/dma/safe_transfer.rs +++ b/src/dma/safe_transfer.rs @@ -1291,15 +1291,23 @@ pub(super) fn check_double_buffer<'s, MemBuf, BUF>( } } -#[derive(Debug, PartialEq, Eq, Clone, Copy)] -pub enum DoubleBuffer { - First, - Second, -} +pub(super) fn first_ptr_from_buffer<'s, ImmutBuf, BUF>( + buffer: &'s ImmutBuf, +) -> *const BUF +where + ImmutBuf: AsImmutable<'s, Target = ImmutableBuffer<'s, 's, BUF>>, + BUF: Payload, +{ + let buffer = unsafe { buffer.as_immutable() }; -pub(super) fn double_buffer_idx(buffer: DoubleBuffer) -> usize { match buffer { - DoubleBuffer::First => 0, - DoubleBuffer::Second => 1, + ImmutableBuffer::Peripheral(buffer) => match buffer { + PeripheralBuffer::Fixed(buffer) => buffer.as_ptr(), + PeripheralBuffer::Incremented(buffer) => buffer.as_ptr(0), + }, + ImmutableBuffer::Memory(buffer) => match buffer { + MemoryBuffer::Fixed(buffer) => buffer.as_ptr(), + MemoryBuffer::Incremented(buffer) => buffer.as_ptr(0), + }, } } From 13271a59744e878e94b8f01d123b7ff27e270c0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ad=C3=A4?= Date: Sat, 28 Dec 2019 13:04:07 +0100 Subject: [PATCH 048/103] Renamed Type parameter of safe transfer buffer --- src/dma.rs | 3 +- src/dma/safe_transfer.rs | 512 +++++++++++++++++++-------------------- 2 files changed, 246 insertions(+), 269 deletions(-) diff --git a/src/dma.rs b/src/dma.rs index 71449cef..f4a811e8 100644 --- a/src/dma.rs +++ b/src/dma.rs @@ -20,7 +20,7 @@ use self::mux::request_ids::{ }; use self::mux::shared::{MuxIsr, RequestGenIsr}; use self::mux::{ - EgDisabled, EgED as EgEDTrait, EgEnabled, NbReq, OverrunError, + EgDisabled, EgED as EgEDTrait, EgEnabled, MuxShared, NbReq, OverrunError, RequestGenerator, RequestId, SyncDisabled, SyncED as SyncEDTrait, SyncEnabled, SyncId, SyncOverrunInterrupt, SyncPolarity, }; @@ -49,7 +49,6 @@ use core::convert::{Infallible, TryFrom, TryInto}; use core::marker::PhantomData; use core::mem; // TODO: Remove when merging. Necessary for me as I'm using CLion with rust plugin, which doesn't support conditionally imported items yet. -use crate::dma::mux::MuxShared; use stm32h7::stm32h743 as stm32; use stm32h7::stm32h743::DMAMUX1; diff --git a/src/dma/safe_transfer.rs b/src/dma/safe_transfer.rs index 7de8aa09..1fbc3d46 100644 --- a/src/dma/safe_transfer.rs +++ b/src/dma/safe_transfer.rs @@ -5,8 +5,7 @@ use super::stream::{ TransferMode, }; use super::{DMATrait, Stream}; -use core::convert::TryFrom; -use core::convert::TryInto; +use core::convert::{TryFrom, TryInto}; use core::fmt::Debug; use core::marker::PhantomData; use core::{mem, ptr}; @@ -89,11 +88,11 @@ impl From for PayloadSize { } impl PayloadSize { - pub fn from_payload() -> Self + pub fn from_payload

() -> Self where - BUF: Payload, + P: Payload, { - let size_bytes: usize = mem::size_of::(); + let size_bytes: usize = mem::size_of::

(); size_bytes.try_into().unwrap_or_else(|_| { panic!("The size of the buffer type must be either 1, 2 or 4 bytes") @@ -127,19 +126,19 @@ pub trait AsImmutable<'s> { } #[derive(Clone, Copy)] -pub enum ImmutableBuffer<'buf, 'wo, BUF> +pub enum ImmutableBuffer<'buf, 'wo, P> where - BUF: Payload, + P: Payload, { - Memory(MemoryBuffer<'buf, BUF>), - Peripheral(PeripheralBuffer<'buf, 'wo, BUF>), + Memory(MemoryBuffer<'buf, P>), + Peripheral(PeripheralBuffer<'buf, 'wo, P>), } -impl<'buf, 'wo, BUF> ImmutableBuffer<'buf, 'wo, BUF> +impl<'buf, 'wo, P> ImmutableBuffer<'buf, 'wo, P> where - BUF: Payload, + P: Payload, { - pub fn memory(self) -> MemoryBuffer<'buf, BUF> { + pub fn memory(self) -> MemoryBuffer<'buf, P> { if let ImmutableBuffer::Memory(buffer) = self { buffer } else { @@ -147,7 +146,7 @@ where } } - pub fn peripheral(self) -> PeripheralBuffer<'buf, 'wo, BUF> { + pub fn peripheral(self) -> PeripheralBuffer<'buf, 'wo, P> { if let ImmutableBuffer::Peripheral(buffer) = self { buffer } else { @@ -156,32 +155,32 @@ where } } -impl<'s, BUF> AsImmutable<'s> for ImmutableBuffer<'_, '_, BUF> +impl<'s, P> AsImmutable<'s> for ImmutableBuffer<'_, '_, P> where - BUF: Payload, + P: Payload, { - type Target = ImmutableBuffer<'s, 's, BUF>; + type Target = ImmutableBuffer<'s, 's, P>; - unsafe fn as_immutable(&self) -> ImmutableBuffer { + unsafe fn as_immutable(&self) -> ImmutableBuffer

{ *self } } -pub type ImmutableBufferStatic<'wo, BUF> = ImmutableBuffer<'static, 'wo, BUF>; +pub type ImmutableBufferStatic<'wo, P> = ImmutableBuffer<'static, 'wo, P>; -pub enum MutableBuffer<'buf, 'wo, BUF> +pub enum MutableBuffer<'buf, 'wo, P> where - BUF: Payload, + P: Payload, { - Memory(MemoryBufferMut<'buf, BUF>), - Peripheral(PeripheralBufferMut<'buf, 'wo, BUF>), + Memory(MemoryBufferMut<'buf, P>), + Peripheral(PeripheralBufferMut<'buf, 'wo, P>), } -impl<'buf, 'wo, BUF> MutableBuffer<'buf, 'wo, BUF> +impl<'buf, 'wo, P> MutableBuffer<'buf, 'wo, P> where - BUF: Payload, + P: Payload, { - pub fn into_memory(self) -> MemoryBufferMut<'buf, BUF> { + pub fn into_memory(self) -> MemoryBufferMut<'buf, P> { if let MutableBuffer::Memory(buffer) = self { buffer } else { @@ -189,7 +188,7 @@ where } } - pub fn as_memory(&self) -> &MemoryBufferMut<'buf, BUF> { + pub fn as_memory(&self) -> &MemoryBufferMut<'buf, P> { if let MutableBuffer::Memory(buffer) = self { buffer } else { @@ -197,7 +196,7 @@ where } } - pub fn as_mut_memory(&mut self) -> &mut MemoryBufferMut<'buf, BUF> { + pub fn as_mut_memory(&mut self) -> &mut MemoryBufferMut<'buf, P> { if let MutableBuffer::Memory(buffer) = self { buffer } else { @@ -205,7 +204,7 @@ where } } - pub fn into_peripheral(self) -> PeripheralBufferMut<'buf, 'wo, BUF> { + pub fn into_peripheral(self) -> PeripheralBufferMut<'buf, 'wo, P> { if let MutableBuffer::Peripheral(buffer) = self { buffer } else { @@ -213,7 +212,7 @@ where } } - pub fn as_peripheral(&self) -> &PeripheralBufferMut<'buf, 'wo, BUF> { + pub fn as_peripheral(&self) -> &PeripheralBufferMut<'buf, 'wo, P> { if let MutableBuffer::Peripheral(buffer) = self { buffer } else { @@ -223,7 +222,7 @@ where pub fn as_mut_peripheral( &mut self, - ) -> &mut PeripheralBufferMut<'buf, 'wo, BUF> { + ) -> &mut PeripheralBufferMut<'buf, 'wo, P> { if let MutableBuffer::Peripheral(buffer) = self { buffer } else { @@ -232,13 +231,13 @@ where } } -impl<'s, BUF> AsImmutable<'s> for MutableBuffer<'_, '_, BUF> +impl<'s, P> AsImmutable<'s> for MutableBuffer<'_, '_, P> where - BUF: Payload, + P: Payload, { - type Target = ImmutableBuffer<'s, 's, BUF>; + type Target = ImmutableBuffer<'s, 's, P>; - unsafe fn as_immutable(&'s self) -> ImmutableBuffer { + unsafe fn as_immutable(&'s self) -> ImmutableBuffer

{ match self { MutableBuffer::Memory(buffer) => { ImmutableBuffer::Memory(buffer.as_immutable()) @@ -250,22 +249,22 @@ where } } -pub type MutableBufferStatic<'wo, BUF> = MutableBuffer<'static, 'wo, BUF>; +pub type MutableBufferStatic<'wo, P> = MutableBuffer<'static, 'wo, P>; #[derive(Clone, Copy)] -pub enum MemoryBuffer<'buf, BUF> +pub enum MemoryBuffer<'buf, P> where - BUF: Payload, + P: Payload, { - Fixed(FixedBuffer<'buf, BUF>), - Incremented(RegularOffsetBuffer<'buf, BUF>), + Fixed(FixedBuffer<'buf, P>), + Incremented(RegularOffsetBuffer<'buf, P>), } -impl<'buf, BUF> MemoryBuffer<'buf, BUF> +impl<'buf, P> MemoryBuffer<'buf, P> where - BUF: Payload, + P: Payload, { - pub fn fixed(self) -> FixedBuffer<'buf, BUF> { + pub fn fixed(self) -> FixedBuffer<'buf, P> { if let MemoryBuffer::Fixed(buffer) = self { buffer } else { @@ -273,7 +272,7 @@ where } } - pub fn incremented(self) -> RegularOffsetBuffer<'buf, BUF> { + pub fn incremented(self) -> RegularOffsetBuffer<'buf, P> { if let MemoryBuffer::Incremented(buffer) = self { buffer } else { @@ -282,32 +281,32 @@ where } } -impl<'s, BUF> AsImmutable<'s> for MemoryBuffer<'_, BUF> +impl<'s, P> AsImmutable<'s> for MemoryBuffer<'_, P> where - BUF: Payload, + P: Payload, { - type Target = MemoryBuffer<'s, BUF>; + type Target = MemoryBuffer<'s, P>; - unsafe fn as_immutable(&self) -> MemoryBuffer { + unsafe fn as_immutable(&self) -> MemoryBuffer

{ *self } } -pub type MemoryBufferStatic = MemoryBuffer<'static, BUF>; +pub type MemoryBufferStatic

= MemoryBuffer<'static, P>; -pub enum MemoryBufferMut<'buf, BUF> +pub enum MemoryBufferMut<'buf, P> where - BUF: Payload, + P: Payload, { - Fixed(FixedBufferMut<'buf, BUF>), - Incremented(RegularOffsetBufferMut<'buf, BUF>), + Fixed(FixedBufferMut<'buf, P>), + Incremented(RegularOffsetBufferMut<'buf, P>), } -impl<'buf, BUF> MemoryBufferMut<'buf, BUF> +impl<'buf, P> MemoryBufferMut<'buf, P> where - BUF: Payload, + P: Payload, { - pub fn into_fixed(self) -> FixedBufferMut<'buf, BUF> { + pub fn into_fixed(self) -> FixedBufferMut<'buf, P> { if let MemoryBufferMut::Fixed(buffer) = self { buffer } else { @@ -315,7 +314,7 @@ where } } - pub fn as_fixed(&self) -> &FixedBufferMut<'buf, BUF> { + pub fn as_fixed(&self) -> &FixedBufferMut<'buf, P> { if let MemoryBufferMut::Fixed(buffer) = self { buffer } else { @@ -323,7 +322,7 @@ where } } - pub fn as_mut_fixed(&mut self) -> &mut FixedBufferMut<'buf, BUF> { + pub fn as_mut_fixed(&mut self) -> &mut FixedBufferMut<'buf, P> { if let MemoryBufferMut::Fixed(buffer) = self { buffer } else { @@ -331,7 +330,7 @@ where } } - pub fn into_incremented(self) -> RegularOffsetBufferMut<'buf, BUF> { + pub fn into_incremented(self) -> RegularOffsetBufferMut<'buf, P> { if let MemoryBufferMut::Incremented(buffer) = self { buffer } else { @@ -339,7 +338,7 @@ where } } - pub fn as_incremented(&self) -> &RegularOffsetBufferMut<'buf, BUF> { + pub fn as_incremented(&self) -> &RegularOffsetBufferMut<'buf, P> { if let MemoryBufferMut::Incremented(buffer) = self { buffer } else { @@ -349,7 +348,7 @@ where pub fn as_mut_incremented( &mut self, - ) -> &mut RegularOffsetBufferMut<'buf, BUF> { + ) -> &mut RegularOffsetBufferMut<'buf, P> { if let MemoryBufferMut::Incremented(buffer) = self { buffer } else { @@ -358,13 +357,13 @@ where } } -impl<'s, BUF> AsImmutable<'s> for MemoryBufferMut<'_, BUF> +impl<'s, P> AsImmutable<'s> for MemoryBufferMut<'_, P> where - BUF: Payload, + P: Payload, { - type Target = MemoryBuffer<'s, BUF>; + type Target = MemoryBuffer<'s, P>; - unsafe fn as_immutable(&self) -> MemoryBuffer { + unsafe fn as_immutable(&self) -> MemoryBuffer

{ match self { MemoryBufferMut::Fixed(buffer) => { MemoryBuffer::Fixed(buffer.as_immutable()) @@ -376,22 +375,22 @@ where } } -pub type MemoryBufferMutStatic = MemoryBufferMut<'static, BUF>; +pub type MemoryBufferMutStatic

= MemoryBufferMut<'static, P>; #[derive(Clone, Copy)] -pub enum PeripheralBuffer<'buf, 'wo, BUF> +pub enum PeripheralBuffer<'buf, 'wo, P> where - BUF: Payload, + P: Payload, { - Fixed(FixedBuffer<'buf, BUF>), - Incremented(IncrementedBuffer<'buf, 'wo, BUF>), + Fixed(FixedBuffer<'buf, P>), + Incremented(IncrementedBuffer<'buf, 'wo, P>), } -impl<'buf, 'wo, BUF> PeripheralBuffer<'buf, 'wo, BUF> +impl<'buf, 'wo, P> PeripheralBuffer<'buf, 'wo, P> where - BUF: Payload, + P: Payload, { - pub fn fixed(self) -> FixedBuffer<'buf, BUF> { + pub fn fixed(self) -> FixedBuffer<'buf, P> { if let PeripheralBuffer::Fixed(buffer) = self { buffer } else { @@ -399,7 +398,7 @@ where } } - pub fn incremented(self) -> IncrementedBuffer<'buf, 'wo, BUF> { + pub fn incremented(self) -> IncrementedBuffer<'buf, 'wo, P> { if let PeripheralBuffer::Incremented(buffer) = self { buffer } else { @@ -408,32 +407,32 @@ where } } -impl<'s, BUF> AsImmutable<'s> for PeripheralBuffer<'_, '_, BUF> +impl<'s, P> AsImmutable<'s> for PeripheralBuffer<'_, '_, P> where - BUF: Payload, + P: Payload, { - type Target = PeripheralBuffer<'s, 's, BUF>; + type Target = PeripheralBuffer<'s, 's, P>; - unsafe fn as_immutable(&self) -> PeripheralBuffer { + unsafe fn as_immutable(&self) -> PeripheralBuffer

{ *self } } -pub type PeripheralBufferStatic<'wo, BUF> = PeripheralBuffer<'static, 'wo, BUF>; +pub type PeripheralBufferStatic<'wo, P> = PeripheralBuffer<'static, 'wo, P>; -pub enum PeripheralBufferMut<'buf, 'wo, BUF> +pub enum PeripheralBufferMut<'buf, 'wo, P> where - BUF: Payload, + P: Payload, { - Fixed(FixedBufferMut<'buf, BUF>), - Incremented(IncrementedBufferMut<'buf, 'wo, BUF>), + Fixed(FixedBufferMut<'buf, P>), + Incremented(IncrementedBufferMut<'buf, 'wo, P>), } -impl<'buf, 'wo, BUF> PeripheralBufferMut<'buf, 'wo, BUF> +impl<'buf, 'wo, P> PeripheralBufferMut<'buf, 'wo, P> where - BUF: Payload, + P: Payload, { - pub fn into_fixed(self) -> FixedBufferMut<'buf, BUF> { + pub fn into_fixed(self) -> FixedBufferMut<'buf, P> { if let PeripheralBufferMut::Fixed(buffer) = self { buffer } else { @@ -441,7 +440,7 @@ where } } - pub fn as_fixed(&self) -> &FixedBufferMut<'buf, BUF> { + pub fn as_fixed(&self) -> &FixedBufferMut<'buf, P> { if let PeripheralBufferMut::Fixed(buffer) = self { buffer } else { @@ -449,7 +448,7 @@ where } } - pub fn as_mut_fixed(&mut self) -> &mut FixedBufferMut<'buf, BUF> { + pub fn as_mut_fixed(&mut self) -> &mut FixedBufferMut<'buf, P> { if let PeripheralBufferMut::Fixed(buffer) = self { buffer } else { @@ -457,7 +456,7 @@ where } } - pub fn into_incremented(self) -> IncrementedBufferMut<'buf, 'wo, BUF> { + pub fn into_incremented(self) -> IncrementedBufferMut<'buf, 'wo, P> { if let PeripheralBufferMut::Incremented(buffer) = self { buffer } else { @@ -465,7 +464,7 @@ where } } - pub fn as_incremented(&self) -> &IncrementedBufferMut<'buf, 'wo, BUF> { + pub fn as_incremented(&self) -> &IncrementedBufferMut<'buf, 'wo, P> { if let PeripheralBufferMut::Incremented(buffer) = self { buffer } else { @@ -475,37 +474,22 @@ where pub fn as_mut_incremented( &mut self, - ) -> &mut IncrementedBufferMut<'buf, 'wo, BUF> { + ) -> &mut IncrementedBufferMut<'buf, 'wo, P> { if let PeripheralBufferMut::Incremented(buffer) = self { buffer } else { panic!("The buffer is fixed."); } } - - /// # Safety - /// - /// `PeripheralBuffer` assumes that the DMA is only reading the buffer. - /// Therefore the getters of the immutable version are as unsafe as the getters of this struct. - pub unsafe fn as_immutable(&self) -> PeripheralBuffer { - match self { - PeripheralBufferMut::Fixed(buffer) => { - PeripheralBuffer::Fixed(buffer.as_immutable()) - } - PeripheralBufferMut::Incremented(buffer) => { - PeripheralBuffer::Incremented(buffer.as_immutable()) - } - } - } } -impl<'s, BUF> AsImmutable<'s> for PeripheralBufferMut<'_, '_, BUF> +impl<'s, P> AsImmutable<'s> for PeripheralBufferMut<'_, '_, P> where - BUF: Payload, + P: Payload, { - type Target = PeripheralBuffer<'s, 's, BUF>; + type Target = PeripheralBuffer<'s, 's, P>; - unsafe fn as_immutable(&self) -> PeripheralBuffer { + unsafe fn as_immutable(&self) -> PeripheralBuffer

{ match self { PeripheralBufferMut::Fixed(buffer) => { PeripheralBuffer::Fixed(buffer.as_immutable()) @@ -517,24 +501,24 @@ where } } -pub type PeripheralBufferMutStatic<'wo, BUF> = - PeripheralBufferMut<'static, 'wo, BUF>; +pub type PeripheralBufferMutStatic<'wo, P> = + PeripheralBufferMut<'static, 'wo, P>; #[derive(Clone, Copy)] -pub enum IncrementedBuffer<'buf, 'wo, BUF> +pub enum IncrementedBuffer<'buf, 'wo, P> where - BUF: Payload, + P: Payload, { - RegularOffset(RegularOffsetBuffer<'buf, BUF>), - WordOffset(WordOffsetBuffer<'buf, 'wo, BUF>), + RegularOffset(RegularOffsetBuffer<'buf, P>), + WordOffset(WordOffsetBuffer<'buf, 'wo, P>), } #[allow(clippy::len_without_is_empty)] -impl<'buf, 'wo, BUF> IncrementedBuffer<'buf, 'wo, BUF> +impl<'buf, 'wo, P> IncrementedBuffer<'buf, 'wo, P> where - BUF: Payload, + P: Payload, { - pub fn regular_offset(self) -> RegularOffsetBuffer<'buf, BUF> { + pub fn regular_offset(self) -> RegularOffsetBuffer<'buf, P> { if let IncrementedBuffer::RegularOffset(buffer) = self { buffer } else { @@ -542,7 +526,7 @@ where } } - pub fn word_offset(self) -> WordOffsetBuffer<'buf, 'wo, BUF> { + pub fn word_offset(self) -> WordOffsetBuffer<'buf, 'wo, P> { if let IncrementedBuffer::WordOffset(buffer) = self { buffer } else { @@ -557,14 +541,14 @@ where } } - pub fn get(self, index: usize) -> BUF { + pub fn get(self, index: usize) -> P { match self { IncrementedBuffer::RegularOffset(buffer) => buffer.get(index), IncrementedBuffer::WordOffset(buffer) => buffer.get(index), } } - pub fn as_ptr(&self, index: usize) -> *const BUF { + pub fn as_ptr(&self, index: usize) -> *const P { match self { IncrementedBuffer::RegularOffset(buffer) => buffer.as_ptr(index), IncrementedBuffer::WordOffset(buffer) => buffer.as_ptr(index), @@ -572,34 +556,33 @@ where } } -impl<'s, BUF> AsImmutable<'s> for IncrementedBuffer<'_, '_, BUF> +impl<'s, P> AsImmutable<'s> for IncrementedBuffer<'_, '_, P> where - BUF: Payload, + P: Payload, { - type Target = IncrementedBuffer<'s, 's, BUF>; + type Target = IncrementedBuffer<'s, 's, P>; - unsafe fn as_immutable(&self) -> IncrementedBuffer { + unsafe fn as_immutable(&self) -> IncrementedBuffer

{ *self } } -pub type IncrementedBufferStatic<'wo, BUF> = - IncrementedBuffer<'static, 'wo, BUF>; +pub type IncrementedBufferStatic<'wo, P> = IncrementedBuffer<'static, 'wo, P>; -pub enum IncrementedBufferMut<'buf, 'wo, BUF> +pub enum IncrementedBufferMut<'buf, 'wo, P> where - BUF: Payload, + P: Payload, { - RegularOffset(RegularOffsetBufferMut<'buf, BUF>), - WordOffset(WordOffsetBufferMut<'buf, 'wo, BUF>), + RegularOffset(RegularOffsetBufferMut<'buf, P>), + WordOffset(WordOffsetBufferMut<'buf, 'wo, P>), } #[allow(clippy::len_without_is_empty)] -impl<'buf, 'wo, BUF> IncrementedBufferMut<'buf, 'wo, BUF> +impl<'buf, 'wo, P> IncrementedBufferMut<'buf, 'wo, P> where - BUF: Payload, + P: Payload, { - pub fn into_regular_offset(self) -> RegularOffsetBufferMut<'buf, BUF> { + pub fn into_regular_offset(self) -> RegularOffsetBufferMut<'buf, P> { if let IncrementedBufferMut::RegularOffset(buffer) = self { buffer } else { @@ -607,7 +590,7 @@ where } } - pub fn as_regular_offset(&self) -> &RegularOffsetBufferMut<'buf, BUF> { + pub fn as_regular_offset(&self) -> &RegularOffsetBufferMut<'buf, P> { if let IncrementedBufferMut::RegularOffset(buffer) = self { buffer } else { @@ -617,7 +600,7 @@ where pub fn as_mut_regular_offset( &mut self, - ) -> &mut RegularOffsetBufferMut<'buf, BUF> { + ) -> &mut RegularOffsetBufferMut<'buf, P> { if let IncrementedBufferMut::RegularOffset(buffer) = self { buffer } else { @@ -625,7 +608,7 @@ where } } - pub fn into_word_offset(self) -> WordOffsetBufferMut<'buf, 'wo, BUF> { + pub fn into_word_offset(self) -> WordOffsetBufferMut<'buf, 'wo, P> { if let IncrementedBufferMut::WordOffset(buffer) = self { buffer } else { @@ -633,7 +616,7 @@ where } } - pub fn as_word_offset(&self) -> &WordOffsetBufferMut<'buf, 'wo, BUF> { + pub fn as_word_offset(&self) -> &WordOffsetBufferMut<'buf, 'wo, P> { if let IncrementedBufferMut::WordOffset(buffer) = self { buffer } else { @@ -643,7 +626,7 @@ where pub fn as_mut_word_offset( &mut self, - ) -> &mut WordOffsetBufferMut<'buf, 'wo, BUF> { + ) -> &mut WordOffsetBufferMut<'buf, 'wo, P> { if let IncrementedBufferMut::WordOffset(buffer) = self { buffer } else { @@ -661,7 +644,7 @@ where /// # Safety /// /// The caller must ensure, that the DMA is currently not modifying this address. - pub unsafe fn get(&self, index: usize) -> BUF { + pub unsafe fn get(&self, index: usize) -> P { match self { IncrementedBufferMut::RegularOffset(buffer) => buffer.get(index), IncrementedBufferMut::WordOffset(buffer) => buffer.get(index), @@ -671,7 +654,7 @@ where /// # Safety /// /// The caller must ensure, that the DMA is currently not modifying this address. - pub unsafe fn set(&mut self, index: usize, payload: BUF) { + pub unsafe fn set(&mut self, index: usize, payload: P) { match self { IncrementedBufferMut::RegularOffset(buffer) => { buffer.set(index, payload) @@ -682,14 +665,14 @@ where } } - pub fn as_ptr(&self, index: usize) -> *const BUF { + pub fn as_ptr(&self, index: usize) -> *const P { match self { IncrementedBufferMut::RegularOffset(buffer) => buffer.as_ptr(index), IncrementedBufferMut::WordOffset(buffer) => buffer.as_ptr(index), } } - pub fn as_mut_ptr(&mut self, index: usize) -> *mut BUF { + pub fn as_mut_ptr(&mut self, index: usize) -> *mut P { match self { IncrementedBufferMut::RegularOffset(buffer) => { buffer.as_mut_ptr(index) @@ -701,17 +684,17 @@ where } } -impl<'s, BUF> AsImmutable<'s> for IncrementedBufferMut<'_, '_, BUF> +impl<'s, P> AsImmutable<'s> for IncrementedBufferMut<'_, '_, P> where - BUF: Payload, + P: Payload, { - type Target = IncrementedBuffer<'s, 's, BUF>; + type Target = IncrementedBuffer<'s, 's, P>; /// # Safety /// /// `IncrementedBuffer` assumes that the DMA is only reading the buffer. /// Therefore the getters of the immutable version are as unsafe as the getters of this struct. - unsafe fn as_immutable(&self) -> IncrementedBuffer { + unsafe fn as_immutable(&self) -> IncrementedBuffer

{ match self { IncrementedBufferMut::RegularOffset(buffer) => { IncrementedBuffer::RegularOffset(buffer.as_immutable()) @@ -723,121 +706,121 @@ where } } -pub type IncrementedBufferMutStatic<'wo, BUF> = - IncrementedBufferMut<'static, 'wo, BUF>; +pub type IncrementedBufferMutStatic<'wo, P> = + IncrementedBufferMut<'static, 'wo, P>; #[derive(Clone, Copy)] -pub struct FixedBuffer<'buf, BUF>(*const BUF, PhantomData<&'buf BUF>) +pub struct FixedBuffer<'buf, P>(*const P, PhantomData<&'buf P>) where - BUF: Payload; + P: Payload; -impl<'buf, BUF> FixedBuffer<'buf, BUF> +impl<'buf, P> FixedBuffer<'buf, P> where - BUF: Payload, + P: Payload, { - pub fn new(buffer: &'buf BUF) -> Self { + pub fn new(buffer: &'buf P) -> Self { FixedBuffer(buffer, PhantomData) } - pub fn get(self) -> BUF { + pub fn get(self) -> P { unsafe { self.0.read_volatile() } } - pub fn as_ptr(self) -> *const BUF { + pub fn as_ptr(self) -> *const P { self.0 } } -impl<'s, BUF> AsImmutable<'s> for FixedBuffer<'_, BUF> +impl<'s, P> AsImmutable<'s> for FixedBuffer<'_, P> where - BUF: Payload, + P: Payload, { - type Target = FixedBuffer<'s, BUF>; + type Target = FixedBuffer<'s, P>; - unsafe fn as_immutable(&self) -> FixedBuffer { + unsafe fn as_immutable(&self) -> FixedBuffer

{ *self } } -unsafe impl Send for FixedBuffer<'_, BUF> where BUF: Payload {} +unsafe impl

Send for FixedBuffer<'_, P> where P: Payload {} -unsafe impl Sync for FixedBuffer<'_, BUF> where BUF: Payload {} +unsafe impl

Sync for FixedBuffer<'_, P> where P: Payload {} -pub type FixedBufferStatic = FixedBuffer<'static, BUF>; +pub type FixedBufferStatic

= FixedBuffer<'static, P>; -pub struct FixedBufferMut<'buf, BUF>(*mut BUF, PhantomData<&'buf mut BUF>) +pub struct FixedBufferMut<'buf, P>(*mut P, PhantomData<&'buf mut P>) where - BUF: Payload; + P: Payload; -impl<'buf, BUF> FixedBufferMut<'buf, BUF> +impl<'buf, P> FixedBufferMut<'buf, P> where - BUF: Payload, + P: Payload, { - pub fn new(buffer: &'buf mut BUF) -> Self { + pub fn new(buffer: &'buf mut P) -> Self { FixedBufferMut(buffer, PhantomData) } /// # Safety /// /// - The caller must ensure, that the DMA is currently not writing this address. - pub unsafe fn get(&self) -> BUF { + pub unsafe fn get(&self) -> P { ptr::read_volatile(self.0) } /// # Safety /// /// - The caller must ensure, that the DMA is currently not writing this address. - pub unsafe fn set(&mut self, buf: BUF) { + pub unsafe fn set(&mut self, buf: P) { ptr::write_volatile(self.0, buf); } - pub fn as_ptr(&self) -> *const BUF { + pub fn as_ptr(&self) -> *const P { self.0 } - pub fn as_mut_ptr(&mut self) -> *mut BUF { + pub fn as_mut_ptr(&mut self) -> *mut P { self.0 } } -impl<'s, BUF> AsImmutable<'s> for FixedBufferMut<'_, BUF> +impl<'s, P> AsImmutable<'s> for FixedBufferMut<'_, P> where - BUF: Payload, + P: Payload, { - type Target = FixedBuffer<'s, BUF>; + type Target = FixedBuffer<'s, P>; - unsafe fn as_immutable(&self) -> FixedBuffer { + unsafe fn as_immutable(&self) -> FixedBuffer

{ FixedBuffer(self.0, PhantomData) } } -unsafe impl Send for FixedBufferMut<'_, BUF> where BUF: Payload {} +unsafe impl

Send for FixedBufferMut<'_, P> where P: Payload {} -unsafe impl Sync for FixedBufferMut<'_, BUF> where BUF: Payload {} +unsafe impl

Sync for FixedBufferMut<'_, P> where P: Payload {} -pub type FixedBufferMutStatic = FixedBufferMut<'static, BUF>; +pub type FixedBufferMutStatic

= FixedBufferMut<'static, P>; #[derive(Clone, Copy)] -pub struct RegularOffsetBuffer<'buf, BUF>(*const [BUF], PhantomData<&'buf BUF>) +pub struct RegularOffsetBuffer<'buf, P>(*const [P], PhantomData<&'buf P>) where - BUF: Payload; + P: Payload; #[allow(clippy::len_without_is_empty)] -impl<'buf, BUF> RegularOffsetBuffer<'buf, BUF> +impl<'buf, P> RegularOffsetBuffer<'buf, P> where - BUF: Payload, + P: Payload, { - pub fn new(buffer: &'buf [BUF]) -> Self { + pub fn new(buffer: &'buf [P]) -> Self { check_buffer_not_empty(buffer); RegularOffsetBuffer(buffer, PhantomData) } - pub fn get(self, index: usize) -> BUF { + pub fn get(self, index: usize) -> P { unsafe { read_volatile_slice_buffer(self.0, index) } } - pub fn as_ptr(self, index: usize) -> *const BUF { + pub fn as_ptr(self, index: usize) -> *const P { unsafe { let slice = &*self.0; &slice[index] as *const _ @@ -852,36 +835,33 @@ where } } -impl<'s, BUF> AsImmutable<'s> for RegularOffsetBuffer<'_, BUF> +impl<'s, P> AsImmutable<'s> for RegularOffsetBuffer<'_, P> where - BUF: Payload, + P: Payload, { - type Target = RegularOffsetBuffer<'s, BUF>; + type Target = RegularOffsetBuffer<'s, P>; - unsafe fn as_immutable(&self) -> RegularOffsetBuffer { + unsafe fn as_immutable(&self) -> RegularOffsetBuffer

{ *self } } -unsafe impl Send for RegularOffsetBuffer<'_, BUF> where BUF: Payload {} +unsafe impl

Send for RegularOffsetBuffer<'_, P> where P: Payload {} -unsafe impl Sync for RegularOffsetBuffer<'_, BUF> where BUF: Payload {} +unsafe impl

Sync for RegularOffsetBuffer<'_, P> where P: Payload {} -pub type RegularOffsetBufferStatic = RegularOffsetBuffer<'static, BUF>; +pub type RegularOffsetBufferStatic

= RegularOffsetBuffer<'static, P>; -pub struct RegularOffsetBufferMut<'buf, BUF>( - *mut [BUF], - PhantomData<&'buf mut BUF>, -) +pub struct RegularOffsetBufferMut<'buf, P>(*mut [P], PhantomData<&'buf mut P>) where - BUF: Payload; + P: Payload; #[allow(clippy::len_without_is_empty)] -impl<'buf, BUF> RegularOffsetBufferMut<'buf, BUF> +impl<'buf, P> RegularOffsetBufferMut<'buf, P> where - BUF: Payload, + P: Payload, { - pub fn new(buffer: &'buf mut [BUF]) -> Self { + pub fn new(buffer: &'buf mut [P]) -> Self { check_buffer_not_empty(buffer); RegularOffsetBufferMut(buffer, PhantomData) @@ -890,26 +870,26 @@ where /// # Safety /// /// - The caller must ensure, that the DMA is currently not modifying this address. - pub unsafe fn get(&self, index: usize) -> BUF { + pub unsafe fn get(&self, index: usize) -> P { read_volatile_slice_buffer(self.0, index) } /// # Safety /// /// - The caller must ensure, that the DMA is currently not modifying this address. - pub unsafe fn set(&mut self, index: usize, item: BUF) { + pub unsafe fn set(&mut self, index: usize, item: P) { let slice = &mut *self.0; ptr::write_volatile(&mut slice[index] as *mut _, item); } - pub fn as_ptr(&self, index: usize) -> *const BUF { + pub fn as_ptr(&self, index: usize) -> *const P { unsafe { let slice = &*self.0; &slice[index] as *const _ } } - pub fn as_mut_ptr(&mut self, index: usize) -> *mut BUF { + pub fn as_mut_ptr(&mut self, index: usize) -> *mut P { unsafe { let slice = &mut *self.0; &mut slice[index] as *mut _ @@ -924,49 +904,48 @@ where } } -impl<'s, BUF> AsImmutable<'s> for RegularOffsetBufferMut<'_, BUF> +impl<'s, P> AsImmutable<'s> for RegularOffsetBufferMut<'_, P> where - BUF: Payload, + P: Payload, { - type Target = RegularOffsetBuffer<'s, BUF>; + type Target = RegularOffsetBuffer<'s, P>; - unsafe fn as_immutable(&self) -> RegularOffsetBuffer { + unsafe fn as_immutable(&self) -> RegularOffsetBuffer

{ RegularOffsetBuffer(self.0, PhantomData) } } -unsafe impl Send for RegularOffsetBufferMut<'_, BUF> where BUF: Payload {} +unsafe impl

Send for RegularOffsetBufferMut<'_, P> where P: Payload {} -unsafe impl Sync for RegularOffsetBufferMut<'_, BUF> where BUF: Payload {} +unsafe impl

Sync for RegularOffsetBufferMut<'_, P> where P: Payload {} -pub type RegularOffsetBufferMutStatic = - RegularOffsetBufferMut<'static, BUF>; +pub type RegularOffsetBufferMutStatic

= RegularOffsetBufferMut<'static, P>; -unsafe fn read_volatile_slice_buffer( - slice_ptr: *const [BUF], +unsafe fn read_volatile_slice_buffer

( + slice_ptr: *const [P], index: usize, -) -> BUF +) -> P where - BUF: Payload, + P: Payload, { let slice = &*slice_ptr; ptr::read_volatile(&slice[index] as *const _) } #[derive(Clone, Copy)] -pub struct WordOffsetBuffer<'buf, 'wo, BUF>( - &'wo [*const BUF], - PhantomData<&'buf BUF>, +pub struct WordOffsetBuffer<'buf, 'wo, P>( + &'wo [*const P], + PhantomData<&'buf P>, ) where - BUF: Payload; + P: Payload; #[allow(clippy::len_without_is_empty)] -impl<'buf, 'wo, BUF> WordOffsetBuffer<'buf, 'wo, BUF> +impl<'buf, 'wo, P> WordOffsetBuffer<'buf, 'wo, P> where - BUF: Payload, + P: Payload, { - pub fn new(buffer: &'wo [&'buf BUF]) -> Self { + pub fn new(buffer: &'wo [&'buf P]) -> Self { check_buffer_not_empty(buffer); let buffer = unsafe { &*(buffer as *const _ as *const _) }; @@ -976,11 +955,11 @@ where WordOffsetBuffer(buffer, PhantomData) } - pub fn get(self, index: usize) -> BUF { + pub fn get(self, index: usize) -> P { unsafe { ptr::read_volatile(self.0[index]) } } - pub fn as_ptr(self, index: usize) -> *const BUF { + pub fn as_ptr(self, index: usize) -> *const P { self.0[index] } @@ -989,46 +968,46 @@ where } } -impl<'s, BUF> AsImmutable<'s> for WordOffsetBuffer<'_, '_, BUF> +impl<'s, P> AsImmutable<'s> for WordOffsetBuffer<'_, '_, P> where - BUF: Payload, + P: Payload, { - type Target = WordOffsetBuffer<'s, 's, BUF>; + type Target = WordOffsetBuffer<'s, 's, P>; - unsafe fn as_immutable(&self) -> WordOffsetBuffer { + unsafe fn as_immutable(&self) -> WordOffsetBuffer

{ *self } } -unsafe impl<'buf, 'wo, BUF> Send for WordOffsetBuffer<'buf, 'wo, BUF> where - BUF: Payload +unsafe impl<'buf, 'wo, P> Send for WordOffsetBuffer<'buf, 'wo, P> where + P: Payload { } -unsafe impl<'buf, 'wo, BUF> Sync for WordOffsetBuffer<'buf, 'wo, BUF> where - BUF: Payload +unsafe impl<'buf, 'wo, P> Sync for WordOffsetBuffer<'buf, 'wo, P> where + P: Payload { } -pub type WordOffsetBufferStatic<'wo, BUF> = WordOffsetBuffer<'static, 'wo, BUF>; +pub type WordOffsetBufferStatic<'wo, P> = WordOffsetBuffer<'static, 'wo, P>; -pub struct WordOffsetBufferMut<'buf, 'wo, BUF>( - &'wo mut [*mut BUF], - PhantomData<&'buf mut BUF>, +pub struct WordOffsetBufferMut<'buf, 'wo, P>( + &'wo mut [*mut P], + PhantomData<&'buf mut P>, ) where - BUF: Payload; + P: Payload; #[allow(clippy::len_without_is_empty)] -impl<'buf, 'wo, BUF> WordOffsetBufferMut<'buf, 'wo, BUF> +impl<'buf, 'wo, P> WordOffsetBufferMut<'buf, 'wo, P> where - BUF: Payload, + P: Payload, { - pub fn new(buffer: &'wo mut [&'buf mut BUF]) -> Self { + pub fn new(buffer: &'wo mut [&'buf mut P]) -> Self { check_buffer_not_empty(buffer); unsafe { - check_word_offset::(&*(buffer as *const _ as *const _)); + check_word_offset::

(&*(buffer as *const _ as *const _)); WordOffsetBufferMut(&mut *(buffer as *mut _ as *mut _), PhantomData) } @@ -1037,22 +1016,22 @@ where /// # Safety /// /// The caller must ensure, that the DMA is currently not modifying this address. - pub unsafe fn get(&self, index: usize) -> BUF { + pub unsafe fn get(&self, index: usize) -> P { ptr::read_volatile(self.0[index]) } /// # Safety /// /// The caller must ensure, that the DMA is currently not modifying this address. - pub unsafe fn set(&mut self, index: usize, item: BUF) { + pub unsafe fn set(&mut self, index: usize, item: P) { ptr::write_volatile(self.0[index], item); } - pub fn as_ptr(&self, index: usize) -> *const BUF { + pub fn as_ptr(&self, index: usize) -> *const P { self.0[index] } - pub fn as_mut_ptr(&mut self, index: usize) -> *mut BUF { + pub fn as_mut_ptr(&mut self, index: usize) -> *mut P { self.0[index] } @@ -1061,25 +1040,25 @@ where } } -impl<'s, BUF> AsImmutable<'s> for WordOffsetBufferMut<'_, '_, BUF> +impl<'s, P> AsImmutable<'s> for WordOffsetBufferMut<'_, '_, P> where - BUF: Payload, + P: Payload, { - type Target = WordOffsetBuffer<'s, 's, BUF>; + type Target = WordOffsetBuffer<'s, 's, P>; - unsafe fn as_immutable(&self) -> WordOffsetBuffer { + unsafe fn as_immutable(&self) -> WordOffsetBuffer

{ WordOffsetBuffer(&*(self.0 as *const _ as *const _), PhantomData) } } -unsafe impl Send for WordOffsetBufferMut<'_, '_, BUF> where BUF: Payload {} +unsafe impl

Send for WordOffsetBufferMut<'_, '_, P> where P: Payload {} -unsafe impl Sync for WordOffsetBufferMut<'_, '_, BUF> where BUF: Payload {} +unsafe impl

Sync for WordOffsetBufferMut<'_, '_, P> where P: Payload {} -pub type WordOffsetBufferMutStatic<'wo, BUF> = - WordOffsetBufferMut<'static, 'wo, BUF>; +pub type WordOffsetBufferMutStatic<'wo, P> = + WordOffsetBufferMut<'static, 'wo, P>; -fn check_buffer_not_empty(buffer: &[T]) { +fn check_buffer_not_empty

(buffer: &[P]) { if buffer.is_empty() { panic!("The buffer must not be empty."); } @@ -1089,9 +1068,9 @@ fn check_buffer_not_empty(buffer: &[T]) { // Secure Transfer implementations // -fn check_word_offset(buffer: &[*const BUF]) +fn check_word_offset

(buffer: &[*const P]) where - BUF: Payload, + P: Payload, { if buffer.is_empty() { return; @@ -1255,11 +1234,10 @@ pub(super) fn check_double_buffer_stream_config( debug_assert_eq!(stream.effective_buffer_mode(), BufferMode::DoubleBuffer); } -pub(super) fn check_double_buffer<'s, MemBuf, BUF>( - double_buffer: &'s [MemBuf; 2], -) where - MemBuf: AsImmutable<'s, Target = MemoryBuffer<'s, BUF>>, - BUF: Payload, +pub(super) fn check_double_buffer<'s, MemBuf, P>(double_buffer: &'s [MemBuf; 2]) +where + MemBuf: AsImmutable<'s, Target = MemoryBuffer<'s, P>>, + P: Payload, { let double_buffer = unsafe { [ @@ -1291,12 +1269,12 @@ pub(super) fn check_double_buffer<'s, MemBuf, BUF>( } } -pub(super) fn first_ptr_from_buffer<'s, ImmutBuf, BUF>( +pub(super) fn first_ptr_from_buffer<'s, ImmutBuf, P>( buffer: &'s ImmutBuf, -) -> *const BUF +) -> *const P where - ImmutBuf: AsImmutable<'s, Target = ImmutableBuffer<'s, 's, BUF>>, - BUF: Payload, + ImmutBuf: AsImmutable<'s, Target = ImmutableBuffer<'s, 's, P>>, + P: Payload, { let buffer = unsafe { buffer.as_immutable() }; From cef803e0e2bf599723a852ab8e479147bfd1c795 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ad=C3=A4?= Date: Sun, 29 Dec 2019 11:54:02 +0100 Subject: [PATCH 049/103] Renamed safe transfer buffer --- src/dma.rs | 86 ++++--- src/dma/safe_transfer.rs | 497 +++++++++++++++++++-------------------- 2 files changed, 286 insertions(+), 297 deletions(-) diff --git a/src/dma.rs b/src/dma.rs index f4a811e8..c8911392 100644 --- a/src/dma.rs +++ b/src/dma.rs @@ -26,10 +26,10 @@ use self::mux::{ }; use self::safe_transfer::{ check_double_buffer, check_double_buffer_stream_config, - configure_safe_transfer, first_ptr_from_buffer, ImmutableBuffer, - ImmutableBufferStatic, MemoryBufferMutStatic, MemoryBufferStatic, - MutableBuffer, MutableBufferStatic, Ongoing, Payload, - PeripheralBufferMutStatic, PeripheralBufferStatic, Start, TransferState, + configure_safe_transfer, first_ptr_from_buffer, BufferR, BufferRStatic, + BufferW, BufferWStatic, MemoryBufferRStatic, MemoryBufferWStatic, Ongoing, + Payload, PeripheralBufferRStatic, PeripheralBufferWStatic, Start, + TransferState, }; use self::stm32::dma1::ST; use self::stm32::dmamux1::CCR; @@ -1396,8 +1396,8 @@ where Dest: Payload, State: TransferState, { - source: ImmutableBufferStatic<'wo, Source>, - dest: MutableBufferStatic<'wo, Dest>, + source: BufferRStatic<'wo, Source>, + dest: BufferWStatic<'wo, Dest>, state: State, } @@ -1407,8 +1407,8 @@ where Dest: Payload, { pub fn new( - source: ImmutableBufferStatic<'wo, Source>, - dest: MutableBufferStatic<'wo, Dest>, + source: BufferRStatic<'wo, Source>, + dest: BufferWStatic<'wo, Dest>, ) -> Self { SafeTransfer { source, @@ -1424,11 +1424,11 @@ where Dest: Payload, State: TransferState, { - pub fn source(&self) -> ImmutableBufferStatic<'wo, Source> { + pub fn source(&self) -> BufferRStatic<'wo, Source> { self.source } - pub fn dest(&self) -> &MutableBufferStatic<'wo, Dest> { + pub fn dest(&self) -> &BufferWStatic<'wo, Dest> { &self.dest } @@ -1437,10 +1437,10 @@ where /// The caller must ensure, that the DMA is currently not modifying this address. pub unsafe fn set_dest_fixed(&mut self, payload: Dest) { match &mut self.dest { - MutableBuffer::Peripheral(buffer) => { + BufferW::Peripheral(buffer) => { buffer.as_mut_fixed().set(payload); } - MutableBuffer::Memory(buffer) => { + BufferW::Memory(buffer) => { buffer.as_mut_fixed().set(payload); } } @@ -1451,10 +1451,10 @@ where /// The caller must ensure, that the DMA is currently not modifying this address. pub unsafe fn set_dest_incremented(&mut self, index: usize, payload: Dest) { match &mut self.dest { - MutableBuffer::Peripheral(buffer) => { + BufferW::Peripheral(buffer) => { buffer.as_mut_incremented().set(index, payload); } - MutableBuffer::Memory(buffer) => { + BufferW::Memory(buffer) => { buffer.as_mut_incremented().set(index, payload); } } @@ -1462,19 +1462,17 @@ where pub fn dest_ptr_fixed(&mut self) -> *mut Dest { match &mut self.dest { - MutableBuffer::Peripheral(buffer) => { - buffer.as_mut_fixed().as_mut_ptr() - } - MutableBuffer::Memory(buffer) => buffer.as_mut_fixed().as_mut_ptr(), + BufferW::Peripheral(buffer) => buffer.as_mut_fixed().as_mut_ptr(), + BufferW::Memory(buffer) => buffer.as_mut_fixed().as_mut_ptr(), } } pub fn dest_ptr_incremented(&mut self, index: usize) -> *mut Dest { match &mut self.dest { - MutableBuffer::Peripheral(buffer) => { + BufferW::Peripheral(buffer) => { buffer.as_mut_incremented().as_mut_ptr(index) } - MutableBuffer::Memory(buffer) => { + BufferW::Memory(buffer) => { buffer.as_mut_incremented().as_mut_ptr(index) } } @@ -1564,8 +1562,8 @@ where Dest: Payload, State: TransferState, { - sources: [MemoryBufferStatic; 2], - dest: PeripheralBufferMutStatic<'wo, Dest>, + sources: [MemoryBufferRStatic; 2], + dest: PeripheralBufferWStatic<'wo, Dest>, state: State, } @@ -1575,8 +1573,8 @@ where Dest: Payload, { pub fn new( - sources: [MemoryBufferStatic; 2], - dest: PeripheralBufferMutStatic<'wo, Dest>, + sources: [MemoryBufferRStatic; 2], + dest: PeripheralBufferWStatic<'wo, Dest>, ) -> Self { check_double_buffer(&sources); @@ -1595,11 +1593,11 @@ where Dest: Payload, State: TransferState, { - pub fn sources(&self) -> [MemoryBufferStatic; 2] { + pub fn sources(&self) -> [MemoryBufferRStatic; 2] { self.sources } - pub fn dest(&self) -> &PeripheralBufferMutStatic<'wo, Dest> { + pub fn dest(&self) -> &PeripheralBufferWStatic<'wo, Dest> { &self.dest } @@ -1641,11 +1639,11 @@ where { check_double_buffer_stream_config(&stream); - let dest_buffer = MutableBuffer::Peripheral(self.dest); + let dest_buffer = BufferW::Peripheral(self.dest); configure_safe_transfer( &mut stream, - ImmutableBuffer::Memory(self.sources[0]), + BufferR::Memory(self.sources[0]), &dest_buffer, ); stream.set_buffer_mode(BufferMode::DoubleBuffer); @@ -1708,8 +1706,8 @@ where self.state.stream.set_fifo_error_interrupt(fe_intrpt); } - pub fn set_m0a(&mut self, m0a: MemoryBufferStatic) { - let ptr = first_ptr_from_buffer(&ImmutableBuffer::Memory(m0a)); + pub fn set_m0a(&mut self, m0a: MemoryBufferRStatic) { + let ptr = first_ptr_from_buffer(&BufferR::Memory(m0a)); mem::replace(&mut self.sources[0], m0a); @@ -1718,8 +1716,8 @@ where block!(self.state.stream.set_m0a(M0a(ptr as u32))).unwrap(); } - pub fn set_m1a(&mut self, m1a: MemoryBufferStatic) { - let ptr = first_ptr_from_buffer(&ImmutableBuffer::Memory(m1a)); + pub fn set_m1a(&mut self, m1a: MemoryBufferRStatic) { + let ptr = first_ptr_from_buffer(&BufferR::Memory(m1a)); mem::replace(&mut self.sources[1], m1a); @@ -1740,8 +1738,8 @@ where Dest: Payload, State: TransferState, { - source: PeripheralBufferStatic<'wo, Source>, - dests: [MemoryBufferMutStatic; 2], + source: PeripheralBufferRStatic<'wo, Source>, + dests: [MemoryBufferWStatic; 2], state: State, } @@ -1751,8 +1749,8 @@ where Dest: Payload, { pub fn new( - source: PeripheralBufferStatic<'wo, Source>, - dests: [MemoryBufferMutStatic; 2], + source: PeripheralBufferRStatic<'wo, Source>, + dests: [MemoryBufferWStatic; 2], ) -> Self { check_double_buffer(&dests); @@ -1771,11 +1769,11 @@ where Dest: Payload, State: TransferState, { - pub fn source(&self) -> PeripheralBufferStatic<'wo, Source> { + pub fn source(&self) -> PeripheralBufferRStatic<'wo, Source> { self.source } - pub fn dest(&self) -> &[MemoryBufferMutStatic; 2] { + pub fn dest(&self) -> &[MemoryBufferWStatic; 2] { &self.dests } @@ -1848,11 +1846,11 @@ where check_double_buffer_stream_config(&stream); let [dest_buffer_0, dest_buffer_1] = self.dests; - let dest_buffer_0 = MutableBuffer::Memory(dest_buffer_0); + let dest_buffer_0 = BufferW::Memory(dest_buffer_0); configure_safe_transfer( &mut stream, - ImmutableBuffer::Peripheral(self.source), + BufferR::Peripheral(self.source), &dest_buffer_0, ); stream.set_buffer_mode(BufferMode::DoubleBuffer); @@ -1915,8 +1913,8 @@ where self.state.stream.set_fifo_error_interrupt(fe_intrpt); } - pub fn set_m0a(&mut self, m0a: MemoryBufferMutStatic) { - let m0a = MutableBuffer::Memory(m0a); + pub fn set_m0a(&mut self, m0a: MemoryBufferWStatic) { + let m0a = BufferW::Memory(m0a); let ptr = first_ptr_from_buffer(&m0a); let m0a = m0a.into_memory(); @@ -1927,8 +1925,8 @@ where block!(self.state.stream.set_m0a(M0a(ptr as u32))).unwrap(); } - pub fn set_m1a(&mut self, m1a: MemoryBufferMutStatic) { - let m1a = MutableBuffer::Memory(m1a); + pub fn set_m1a(&mut self, m1a: MemoryBufferWStatic) { + let m1a = BufferW::Memory(m1a); let ptr = first_ptr_from_buffer(&m1a); let m1a = m1a.into_memory(); diff --git a/src/dma/safe_transfer.rs b/src/dma/safe_transfer.rs index 1fbc3d46..cfa46802 100644 --- a/src/dma/safe_transfer.rs +++ b/src/dma/safe_transfer.rs @@ -126,28 +126,28 @@ pub trait AsImmutable<'s> { } #[derive(Clone, Copy)] -pub enum ImmutableBuffer<'buf, 'wo, P> +pub enum BufferR<'buf, 'wo, P> where P: Payload, { - Memory(MemoryBuffer<'buf, P>), - Peripheral(PeripheralBuffer<'buf, 'wo, P>), + Memory(MemoryBufferR<'buf, P>), + Peripheral(PeripheralBufferR<'buf, 'wo, P>), } -impl<'buf, 'wo, P> ImmutableBuffer<'buf, 'wo, P> +impl<'buf, 'wo, P> BufferR<'buf, 'wo, P> where P: Payload, { - pub fn memory(self) -> MemoryBuffer<'buf, P> { - if let ImmutableBuffer::Memory(buffer) = self { + pub fn memory(self) -> MemoryBufferR<'buf, P> { + if let BufferR::Memory(buffer) = self { buffer } else { panic!("The buffer is a peripheral buffer."); } } - pub fn peripheral(self) -> PeripheralBuffer<'buf, 'wo, P> { - if let ImmutableBuffer::Peripheral(buffer) = self { + pub fn peripheral(self) -> PeripheralBufferR<'buf, 'wo, P> { + if let BufferR::Peripheral(buffer) = self { buffer } else { panic!("The buffer is a memory buffer."); @@ -155,65 +155,65 @@ where } } -impl<'s, P> AsImmutable<'s> for ImmutableBuffer<'_, '_, P> +impl<'s, P> AsImmutable<'s> for BufferR<'_, '_, P> where P: Payload, { - type Target = ImmutableBuffer<'s, 's, P>; + type Target = BufferR<'s, 's, P>; - unsafe fn as_immutable(&self) -> ImmutableBuffer

{ + unsafe fn as_immutable(&self) -> BufferR

{ *self } } -pub type ImmutableBufferStatic<'wo, P> = ImmutableBuffer<'static, 'wo, P>; +pub type BufferRStatic<'wo, P> = BufferR<'static, 'wo, P>; -pub enum MutableBuffer<'buf, 'wo, P> +pub enum BufferW<'buf, 'wo, P> where P: Payload, { - Memory(MemoryBufferMut<'buf, P>), - Peripheral(PeripheralBufferMut<'buf, 'wo, P>), + Memory(MemoryBufferW<'buf, P>), + Peripheral(PeripheralBufferW<'buf, 'wo, P>), } -impl<'buf, 'wo, P> MutableBuffer<'buf, 'wo, P> +impl<'buf, 'wo, P> BufferW<'buf, 'wo, P> where P: Payload, { - pub fn into_memory(self) -> MemoryBufferMut<'buf, P> { - if let MutableBuffer::Memory(buffer) = self { + pub fn into_memory(self) -> MemoryBufferW<'buf, P> { + if let BufferW::Memory(buffer) = self { buffer } else { panic!("The buffer is a peripheral buffer."); } } - pub fn as_memory(&self) -> &MemoryBufferMut<'buf, P> { - if let MutableBuffer::Memory(buffer) = self { + pub fn as_memory(&self) -> &MemoryBufferW<'buf, P> { + if let BufferW::Memory(buffer) = self { buffer } else { panic!("The buffer is a peripheral buffer."); } } - pub fn as_mut_memory(&mut self) -> &mut MemoryBufferMut<'buf, P> { - if let MutableBuffer::Memory(buffer) = self { + pub fn as_mut_memory(&mut self) -> &mut MemoryBufferW<'buf, P> { + if let BufferW::Memory(buffer) = self { buffer } else { panic!("The buffer is a peripheral buffer."); } } - pub fn into_peripheral(self) -> PeripheralBufferMut<'buf, 'wo, P> { - if let MutableBuffer::Peripheral(buffer) = self { + pub fn into_peripheral(self) -> PeripheralBufferW<'buf, 'wo, P> { + if let BufferW::Peripheral(buffer) = self { buffer } else { panic!("The buffer is a memory buffer."); } } - pub fn as_peripheral(&self) -> &PeripheralBufferMut<'buf, 'wo, P> { - if let MutableBuffer::Peripheral(buffer) = self { + pub fn as_peripheral(&self) -> &PeripheralBufferW<'buf, 'wo, P> { + if let BufferW::Peripheral(buffer) = self { buffer } else { panic!("The buffer is a memory buffer."); @@ -222,8 +222,8 @@ where pub fn as_mut_peripheral( &mut self, - ) -> &mut PeripheralBufferMut<'buf, 'wo, P> { - if let MutableBuffer::Peripheral(buffer) = self { + ) -> &mut PeripheralBufferW<'buf, 'wo, P> { + if let BufferW::Peripheral(buffer) = self { buffer } else { panic!("The buffer is a memory buffer."); @@ -231,49 +231,47 @@ where } } -impl<'s, P> AsImmutable<'s> for MutableBuffer<'_, '_, P> +impl<'s, P> AsImmutable<'s> for BufferW<'_, '_, P> where P: Payload, { - type Target = ImmutableBuffer<'s, 's, P>; + type Target = BufferR<'s, 's, P>; - unsafe fn as_immutable(&'s self) -> ImmutableBuffer

{ + unsafe fn as_immutable(&'s self) -> BufferR

{ match self { - MutableBuffer::Memory(buffer) => { - ImmutableBuffer::Memory(buffer.as_immutable()) - } - MutableBuffer::Peripheral(buffer) => { - ImmutableBuffer::Peripheral(buffer.as_immutable()) + BufferW::Memory(buffer) => BufferR::Memory(buffer.as_immutable()), + BufferW::Peripheral(buffer) => { + BufferR::Peripheral(buffer.as_immutable()) } } } } -pub type MutableBufferStatic<'wo, P> = MutableBuffer<'static, 'wo, P>; +pub type BufferWStatic<'wo, P> = BufferW<'static, 'wo, P>; #[derive(Clone, Copy)] -pub enum MemoryBuffer<'buf, P> +pub enum MemoryBufferR<'buf, P> where P: Payload, { - Fixed(FixedBuffer<'buf, P>), - Incremented(RegularOffsetBuffer<'buf, P>), + Fixed(FixedBufferR<'buf, P>), + Incremented(RegularOffsetBufferR<'buf, P>), } -impl<'buf, P> MemoryBuffer<'buf, P> +impl<'buf, P> MemoryBufferR<'buf, P> where P: Payload, { - pub fn fixed(self) -> FixedBuffer<'buf, P> { - if let MemoryBuffer::Fixed(buffer) = self { + pub fn fixed(self) -> FixedBufferR<'buf, P> { + if let MemoryBufferR::Fixed(buffer) = self { buffer } else { panic!("The buffer is incremented."); } } - pub fn incremented(self) -> RegularOffsetBuffer<'buf, P> { - if let MemoryBuffer::Incremented(buffer) = self { + pub fn incremented(self) -> RegularOffsetBufferR<'buf, P> { + if let MemoryBufferR::Incremented(buffer) = self { buffer } else { panic!("The buffer is fixed."); @@ -281,75 +279,73 @@ where } } -impl<'s, P> AsImmutable<'s> for MemoryBuffer<'_, P> +impl<'s, P> AsImmutable<'s> for MemoryBufferR<'_, P> where P: Payload, { - type Target = MemoryBuffer<'s, P>; + type Target = MemoryBufferR<'s, P>; - unsafe fn as_immutable(&self) -> MemoryBuffer

{ + unsafe fn as_immutable(&self) -> MemoryBufferR

{ *self } } -pub type MemoryBufferStatic

= MemoryBuffer<'static, P>; +pub type MemoryBufferRStatic

= MemoryBufferR<'static, P>; -pub enum MemoryBufferMut<'buf, P> +pub enum MemoryBufferW<'buf, P> where P: Payload, { - Fixed(FixedBufferMut<'buf, P>), - Incremented(RegularOffsetBufferMut<'buf, P>), + Fixed(FixedBufferW<'buf, P>), + Incremented(RegularOffsetBufferW<'buf, P>), } -impl<'buf, P> MemoryBufferMut<'buf, P> +impl<'buf, P> MemoryBufferW<'buf, P> where P: Payload, { - pub fn into_fixed(self) -> FixedBufferMut<'buf, P> { - if let MemoryBufferMut::Fixed(buffer) = self { + pub fn into_fixed(self) -> FixedBufferW<'buf, P> { + if let MemoryBufferW::Fixed(buffer) = self { buffer } else { panic!("The buffer is incremented."); } } - pub fn as_fixed(&self) -> &FixedBufferMut<'buf, P> { - if let MemoryBufferMut::Fixed(buffer) = self { + pub fn as_fixed(&self) -> &FixedBufferW<'buf, P> { + if let MemoryBufferW::Fixed(buffer) = self { buffer } else { panic!("The buffer is incremented."); } } - pub fn as_mut_fixed(&mut self) -> &mut FixedBufferMut<'buf, P> { - if let MemoryBufferMut::Fixed(buffer) = self { + pub fn as_mut_fixed(&mut self) -> &mut FixedBufferW<'buf, P> { + if let MemoryBufferW::Fixed(buffer) = self { buffer } else { panic!("The buffer is incremented."); } } - pub fn into_incremented(self) -> RegularOffsetBufferMut<'buf, P> { - if let MemoryBufferMut::Incremented(buffer) = self { + pub fn into_incremented(self) -> RegularOffsetBufferW<'buf, P> { + if let MemoryBufferW::Incremented(buffer) = self { buffer } else { panic!("The buffer is fixed."); } } - pub fn as_incremented(&self) -> &RegularOffsetBufferMut<'buf, P> { - if let MemoryBufferMut::Incremented(buffer) = self { + pub fn as_incremented(&self) -> &RegularOffsetBufferW<'buf, P> { + if let MemoryBufferW::Incremented(buffer) = self { buffer } else { panic!("The buffer is fixed."); } } - pub fn as_mut_incremented( - &mut self, - ) -> &mut RegularOffsetBufferMut<'buf, P> { - if let MemoryBufferMut::Incremented(buffer) = self { + pub fn as_mut_incremented(&mut self) -> &mut RegularOffsetBufferW<'buf, P> { + if let MemoryBufferW::Incremented(buffer) = self { buffer } else { panic!("The buffer is fixed."); @@ -357,49 +353,49 @@ where } } -impl<'s, P> AsImmutable<'s> for MemoryBufferMut<'_, P> +impl<'s, P> AsImmutable<'s> for MemoryBufferW<'_, P> where P: Payload, { - type Target = MemoryBuffer<'s, P>; + type Target = MemoryBufferR<'s, P>; - unsafe fn as_immutable(&self) -> MemoryBuffer

{ + unsafe fn as_immutable(&self) -> MemoryBufferR

{ match self { - MemoryBufferMut::Fixed(buffer) => { - MemoryBuffer::Fixed(buffer.as_immutable()) + MemoryBufferW::Fixed(buffer) => { + MemoryBufferR::Fixed(buffer.as_immutable()) } - MemoryBufferMut::Incremented(buffer) => { - MemoryBuffer::Incremented(buffer.as_immutable()) + MemoryBufferW::Incremented(buffer) => { + MemoryBufferR::Incremented(buffer.as_immutable()) } } } } -pub type MemoryBufferMutStatic

= MemoryBufferMut<'static, P>; +pub type MemoryBufferWStatic

= MemoryBufferW<'static, P>; #[derive(Clone, Copy)] -pub enum PeripheralBuffer<'buf, 'wo, P> +pub enum PeripheralBufferR<'buf, 'wo, P> where P: Payload, { - Fixed(FixedBuffer<'buf, P>), - Incremented(IncrementedBuffer<'buf, 'wo, P>), + Fixed(FixedBufferR<'buf, P>), + Incremented(IncrementedBufferR<'buf, 'wo, P>), } -impl<'buf, 'wo, P> PeripheralBuffer<'buf, 'wo, P> +impl<'buf, 'wo, P> PeripheralBufferR<'buf, 'wo, P> where P: Payload, { - pub fn fixed(self) -> FixedBuffer<'buf, P> { - if let PeripheralBuffer::Fixed(buffer) = self { + pub fn fixed(self) -> FixedBufferR<'buf, P> { + if let PeripheralBufferR::Fixed(buffer) = self { buffer } else { panic!("The buffer is incremented."); } } - pub fn incremented(self) -> IncrementedBuffer<'buf, 'wo, P> { - if let PeripheralBuffer::Incremented(buffer) = self { + pub fn incremented(self) -> IncrementedBufferR<'buf, 'wo, P> { + if let PeripheralBufferR::Incremented(buffer) = self { buffer } else { panic!("The buffer is fixed."); @@ -407,65 +403,65 @@ where } } -impl<'s, P> AsImmutable<'s> for PeripheralBuffer<'_, '_, P> +impl<'s, P> AsImmutable<'s> for PeripheralBufferR<'_, '_, P> where P: Payload, { - type Target = PeripheralBuffer<'s, 's, P>; + type Target = PeripheralBufferR<'s, 's, P>; - unsafe fn as_immutable(&self) -> PeripheralBuffer

{ + unsafe fn as_immutable(&self) -> PeripheralBufferR

{ *self } } -pub type PeripheralBufferStatic<'wo, P> = PeripheralBuffer<'static, 'wo, P>; +pub type PeripheralBufferRStatic<'wo, P> = PeripheralBufferR<'static, 'wo, P>; -pub enum PeripheralBufferMut<'buf, 'wo, P> +pub enum PeripheralBufferW<'buf, 'wo, P> where P: Payload, { - Fixed(FixedBufferMut<'buf, P>), - Incremented(IncrementedBufferMut<'buf, 'wo, P>), + Fixed(FixedBufferW<'buf, P>), + Incremented(IncrementedBufferW<'buf, 'wo, P>), } -impl<'buf, 'wo, P> PeripheralBufferMut<'buf, 'wo, P> +impl<'buf, 'wo, P> PeripheralBufferW<'buf, 'wo, P> where P: Payload, { - pub fn into_fixed(self) -> FixedBufferMut<'buf, P> { - if let PeripheralBufferMut::Fixed(buffer) = self { + pub fn into_fixed(self) -> FixedBufferW<'buf, P> { + if let PeripheralBufferW::Fixed(buffer) = self { buffer } else { panic!("The buffer is incremented."); } } - pub fn as_fixed(&self) -> &FixedBufferMut<'buf, P> { - if let PeripheralBufferMut::Fixed(buffer) = self { + pub fn as_fixed(&self) -> &FixedBufferW<'buf, P> { + if let PeripheralBufferW::Fixed(buffer) = self { buffer } else { panic!("The buffer is incremented."); } } - pub fn as_mut_fixed(&mut self) -> &mut FixedBufferMut<'buf, P> { - if let PeripheralBufferMut::Fixed(buffer) = self { + pub fn as_mut_fixed(&mut self) -> &mut FixedBufferW<'buf, P> { + if let PeripheralBufferW::Fixed(buffer) = self { buffer } else { panic!("The buffer is incremented."); } } - pub fn into_incremented(self) -> IncrementedBufferMut<'buf, 'wo, P> { - if let PeripheralBufferMut::Incremented(buffer) = self { + pub fn into_incremented(self) -> IncrementedBufferW<'buf, 'wo, P> { + if let PeripheralBufferW::Incremented(buffer) = self { buffer } else { panic!("The buffer is fixed."); } } - pub fn as_incremented(&self) -> &IncrementedBufferMut<'buf, 'wo, P> { - if let PeripheralBufferMut::Incremented(buffer) = self { + pub fn as_incremented(&self) -> &IncrementedBufferW<'buf, 'wo, P> { + if let PeripheralBufferW::Incremented(buffer) = self { buffer } else { panic!("The buffer is fixed."); @@ -474,8 +470,8 @@ where pub fn as_mut_incremented( &mut self, - ) -> &mut IncrementedBufferMut<'buf, 'wo, P> { - if let PeripheralBufferMut::Incremented(buffer) = self { + ) -> &mut IncrementedBufferW<'buf, 'wo, P> { + if let PeripheralBufferW::Incremented(buffer) = self { buffer } else { panic!("The buffer is fixed."); @@ -483,51 +479,50 @@ where } } -impl<'s, P> AsImmutable<'s> for PeripheralBufferMut<'_, '_, P> +impl<'s, P> AsImmutable<'s> for PeripheralBufferW<'_, '_, P> where P: Payload, { - type Target = PeripheralBuffer<'s, 's, P>; + type Target = PeripheralBufferR<'s, 's, P>; - unsafe fn as_immutable(&self) -> PeripheralBuffer

{ + unsafe fn as_immutable(&self) -> PeripheralBufferR

{ match self { - PeripheralBufferMut::Fixed(buffer) => { - PeripheralBuffer::Fixed(buffer.as_immutable()) + PeripheralBufferW::Fixed(buffer) => { + PeripheralBufferR::Fixed(buffer.as_immutable()) } - PeripheralBufferMut::Incremented(buffer) => { - PeripheralBuffer::Incremented(buffer.as_immutable()) + PeripheralBufferW::Incremented(buffer) => { + PeripheralBufferR::Incremented(buffer.as_immutable()) } } } } -pub type PeripheralBufferMutStatic<'wo, P> = - PeripheralBufferMut<'static, 'wo, P>; +pub type PeripheralBufferWStatic<'wo, P> = PeripheralBufferW<'static, 'wo, P>; #[derive(Clone, Copy)] -pub enum IncrementedBuffer<'buf, 'wo, P> +pub enum IncrementedBufferR<'buf, 'wo, P> where P: Payload, { - RegularOffset(RegularOffsetBuffer<'buf, P>), - WordOffset(WordOffsetBuffer<'buf, 'wo, P>), + RegularOffset(RegularOffsetBufferR<'buf, P>), + WordOffset(WordOffsetBufferR<'buf, 'wo, P>), } #[allow(clippy::len_without_is_empty)] -impl<'buf, 'wo, P> IncrementedBuffer<'buf, 'wo, P> +impl<'buf, 'wo, P> IncrementedBufferR<'buf, 'wo, P> where P: Payload, { - pub fn regular_offset(self) -> RegularOffsetBuffer<'buf, P> { - if let IncrementedBuffer::RegularOffset(buffer) = self { + pub fn regular_offset(self) -> RegularOffsetBufferR<'buf, P> { + if let IncrementedBufferR::RegularOffset(buffer) = self { buffer } else { panic!("The buffer has word offset."); } } - pub fn word_offset(self) -> WordOffsetBuffer<'buf, 'wo, P> { - if let IncrementedBuffer::WordOffset(buffer) = self { + pub fn word_offset(self) -> WordOffsetBufferR<'buf, 'wo, P> { + if let IncrementedBufferR::WordOffset(buffer) = self { buffer } else { panic!("The buffer has regular offset."); @@ -536,62 +531,62 @@ where pub fn len(self) -> usize { match self { - IncrementedBuffer::RegularOffset(buffer) => buffer.len(), - IncrementedBuffer::WordOffset(buffer) => buffer.len(), + IncrementedBufferR::RegularOffset(buffer) => buffer.len(), + IncrementedBufferR::WordOffset(buffer) => buffer.len(), } } pub fn get(self, index: usize) -> P { match self { - IncrementedBuffer::RegularOffset(buffer) => buffer.get(index), - IncrementedBuffer::WordOffset(buffer) => buffer.get(index), + IncrementedBufferR::RegularOffset(buffer) => buffer.get(index), + IncrementedBufferR::WordOffset(buffer) => buffer.get(index), } } pub fn as_ptr(&self, index: usize) -> *const P { match self { - IncrementedBuffer::RegularOffset(buffer) => buffer.as_ptr(index), - IncrementedBuffer::WordOffset(buffer) => buffer.as_ptr(index), + IncrementedBufferR::RegularOffset(buffer) => buffer.as_ptr(index), + IncrementedBufferR::WordOffset(buffer) => buffer.as_ptr(index), } } } -impl<'s, P> AsImmutable<'s> for IncrementedBuffer<'_, '_, P> +impl<'s, P> AsImmutable<'s> for IncrementedBufferR<'_, '_, P> where P: Payload, { - type Target = IncrementedBuffer<'s, 's, P>; + type Target = IncrementedBufferR<'s, 's, P>; - unsafe fn as_immutable(&self) -> IncrementedBuffer

{ + unsafe fn as_immutable(&self) -> IncrementedBufferR

{ *self } } -pub type IncrementedBufferStatic<'wo, P> = IncrementedBuffer<'static, 'wo, P>; +pub type IncrementedBufferRStatic<'wo, P> = IncrementedBufferR<'static, 'wo, P>; -pub enum IncrementedBufferMut<'buf, 'wo, P> +pub enum IncrementedBufferW<'buf, 'wo, P> where P: Payload, { - RegularOffset(RegularOffsetBufferMut<'buf, P>), - WordOffset(WordOffsetBufferMut<'buf, 'wo, P>), + RegularOffset(RegularOffsetBufferW<'buf, P>), + WordOffset(WordOffsetBufferW<'buf, 'wo, P>), } #[allow(clippy::len_without_is_empty)] -impl<'buf, 'wo, P> IncrementedBufferMut<'buf, 'wo, P> +impl<'buf, 'wo, P> IncrementedBufferW<'buf, 'wo, P> where P: Payload, { - pub fn into_regular_offset(self) -> RegularOffsetBufferMut<'buf, P> { - if let IncrementedBufferMut::RegularOffset(buffer) = self { + pub fn into_regular_offset(self) -> RegularOffsetBufferW<'buf, P> { + if let IncrementedBufferW::RegularOffset(buffer) = self { buffer } else { panic!("The buffer has word offset."); } } - pub fn as_regular_offset(&self) -> &RegularOffsetBufferMut<'buf, P> { - if let IncrementedBufferMut::RegularOffset(buffer) = self { + pub fn as_regular_offset(&self) -> &RegularOffsetBufferW<'buf, P> { + if let IncrementedBufferW::RegularOffset(buffer) = self { buffer } else { panic!("The buffer has word offset."); @@ -600,24 +595,24 @@ where pub fn as_mut_regular_offset( &mut self, - ) -> &mut RegularOffsetBufferMut<'buf, P> { - if let IncrementedBufferMut::RegularOffset(buffer) = self { + ) -> &mut RegularOffsetBufferW<'buf, P> { + if let IncrementedBufferW::RegularOffset(buffer) = self { buffer } else { panic!("The buffer has word offset."); } } - pub fn into_word_offset(self) -> WordOffsetBufferMut<'buf, 'wo, P> { - if let IncrementedBufferMut::WordOffset(buffer) = self { + pub fn into_word_offset(self) -> WordOffsetBufferW<'buf, 'wo, P> { + if let IncrementedBufferW::WordOffset(buffer) = self { buffer } else { panic!("The buffer has regular offset."); } } - pub fn as_word_offset(&self) -> &WordOffsetBufferMut<'buf, 'wo, P> { - if let IncrementedBufferMut::WordOffset(buffer) = self { + pub fn as_word_offset(&self) -> &WordOffsetBufferW<'buf, 'wo, P> { + if let IncrementedBufferW::WordOffset(buffer) = self { buffer } else { panic!("The buffer has regular offset."); @@ -626,8 +621,8 @@ where pub fn as_mut_word_offset( &mut self, - ) -> &mut WordOffsetBufferMut<'buf, 'wo, P> { - if let IncrementedBufferMut::WordOffset(buffer) = self { + ) -> &mut WordOffsetBufferW<'buf, 'wo, P> { + if let IncrementedBufferW::WordOffset(buffer) = self { buffer } else { panic!("The buffer has regular offset."); @@ -636,8 +631,8 @@ where pub fn len(&self) -> usize { match self { - IncrementedBufferMut::RegularOffset(buffer) => buffer.len(), - IncrementedBufferMut::WordOffset(buffer) => buffer.len(), + IncrementedBufferW::RegularOffset(buffer) => buffer.len(), + IncrementedBufferW::WordOffset(buffer) => buffer.len(), } } @@ -646,8 +641,8 @@ where /// The caller must ensure, that the DMA is currently not modifying this address. pub unsafe fn get(&self, index: usize) -> P { match self { - IncrementedBufferMut::RegularOffset(buffer) => buffer.get(index), - IncrementedBufferMut::WordOffset(buffer) => buffer.get(index), + IncrementedBufferW::RegularOffset(buffer) => buffer.get(index), + IncrementedBufferW::WordOffset(buffer) => buffer.get(index), } } @@ -656,10 +651,10 @@ where /// The caller must ensure, that the DMA is currently not modifying this address. pub unsafe fn set(&mut self, index: usize, payload: P) { match self { - IncrementedBufferMut::RegularOffset(buffer) => { + IncrementedBufferW::RegularOffset(buffer) => { buffer.set(index, payload) } - IncrementedBufferMut::WordOffset(buffer) => { + IncrementedBufferW::WordOffset(buffer) => { buffer.set(index, payload) } } @@ -667,59 +662,56 @@ where pub fn as_ptr(&self, index: usize) -> *const P { match self { - IncrementedBufferMut::RegularOffset(buffer) => buffer.as_ptr(index), - IncrementedBufferMut::WordOffset(buffer) => buffer.as_ptr(index), + IncrementedBufferW::RegularOffset(buffer) => buffer.as_ptr(index), + IncrementedBufferW::WordOffset(buffer) => buffer.as_ptr(index), } } pub fn as_mut_ptr(&mut self, index: usize) -> *mut P { match self { - IncrementedBufferMut::RegularOffset(buffer) => { - buffer.as_mut_ptr(index) - } - IncrementedBufferMut::WordOffset(buffer) => { + IncrementedBufferW::RegularOffset(buffer) => { buffer.as_mut_ptr(index) } + IncrementedBufferW::WordOffset(buffer) => buffer.as_mut_ptr(index), } } } -impl<'s, P> AsImmutable<'s> for IncrementedBufferMut<'_, '_, P> +impl<'s, P> AsImmutable<'s> for IncrementedBufferW<'_, '_, P> where P: Payload, { - type Target = IncrementedBuffer<'s, 's, P>; + type Target = IncrementedBufferR<'s, 's, P>; /// # Safety /// /// `IncrementedBuffer` assumes that the DMA is only reading the buffer. /// Therefore the getters of the immutable version are as unsafe as the getters of this struct. - unsafe fn as_immutable(&self) -> IncrementedBuffer

{ + unsafe fn as_immutable(&self) -> IncrementedBufferR

{ match self { - IncrementedBufferMut::RegularOffset(buffer) => { - IncrementedBuffer::RegularOffset(buffer.as_immutable()) + IncrementedBufferW::RegularOffset(buffer) => { + IncrementedBufferR::RegularOffset(buffer.as_immutable()) } - IncrementedBufferMut::WordOffset(buffer) => { - IncrementedBuffer::WordOffset(buffer.as_immutable()) + IncrementedBufferW::WordOffset(buffer) => { + IncrementedBufferR::WordOffset(buffer.as_immutable()) } } } } -pub type IncrementedBufferMutStatic<'wo, P> = - IncrementedBufferMut<'static, 'wo, P>; +pub type IncrementedBufferWStatic<'wo, P> = IncrementedBufferW<'static, 'wo, P>; #[derive(Clone, Copy)] -pub struct FixedBuffer<'buf, P>(*const P, PhantomData<&'buf P>) +pub struct FixedBufferR<'buf, P>(*const P, PhantomData<&'buf P>) where P: Payload; -impl<'buf, P> FixedBuffer<'buf, P> +impl<'buf, P> FixedBufferR<'buf, P> where P: Payload, { pub fn new(buffer: &'buf P) -> Self { - FixedBuffer(buffer, PhantomData) + FixedBufferR(buffer, PhantomData) } pub fn get(self) -> P { @@ -731,33 +723,33 @@ where } } -impl<'s, P> AsImmutable<'s> for FixedBuffer<'_, P> +impl<'s, P> AsImmutable<'s> for FixedBufferR<'_, P> where P: Payload, { - type Target = FixedBuffer<'s, P>; + type Target = FixedBufferR<'s, P>; - unsafe fn as_immutable(&self) -> FixedBuffer

{ + unsafe fn as_immutable(&self) -> FixedBufferR

{ *self } } -unsafe impl

Send for FixedBuffer<'_, P> where P: Payload {} +unsafe impl

Send for FixedBufferR<'_, P> where P: Payload {} -unsafe impl

Sync for FixedBuffer<'_, P> where P: Payload {} +unsafe impl

Sync for FixedBufferR<'_, P> where P: Payload {} -pub type FixedBufferStatic

= FixedBuffer<'static, P>; +pub type FixedBufferRStatic

= FixedBufferR<'static, P>; -pub struct FixedBufferMut<'buf, P>(*mut P, PhantomData<&'buf mut P>) +pub struct FixedBufferW<'buf, P>(*mut P, PhantomData<&'buf mut P>) where P: Payload; -impl<'buf, P> FixedBufferMut<'buf, P> +impl<'buf, P> FixedBufferW<'buf, P> where P: Payload, { pub fn new(buffer: &'buf mut P) -> Self { - FixedBufferMut(buffer, PhantomData) + FixedBufferW(buffer, PhantomData) } /// # Safety @@ -783,37 +775,37 @@ where } } -impl<'s, P> AsImmutable<'s> for FixedBufferMut<'_, P> +impl<'s, P> AsImmutable<'s> for FixedBufferW<'_, P> where P: Payload, { - type Target = FixedBuffer<'s, P>; + type Target = FixedBufferR<'s, P>; - unsafe fn as_immutable(&self) -> FixedBuffer

{ - FixedBuffer(self.0, PhantomData) + unsafe fn as_immutable(&self) -> FixedBufferR

{ + FixedBufferR(self.0, PhantomData) } } -unsafe impl

Send for FixedBufferMut<'_, P> where P: Payload {} +unsafe impl

Send for FixedBufferW<'_, P> where P: Payload {} -unsafe impl

Sync for FixedBufferMut<'_, P> where P: Payload {} +unsafe impl

Sync for FixedBufferW<'_, P> where P: Payload {} -pub type FixedBufferMutStatic

= FixedBufferMut<'static, P>; +pub type FixedBufferWStatic

= FixedBufferW<'static, P>; #[derive(Clone, Copy)] -pub struct RegularOffsetBuffer<'buf, P>(*const [P], PhantomData<&'buf P>) +pub struct RegularOffsetBufferR<'buf, P>(*const [P], PhantomData<&'buf P>) where P: Payload; #[allow(clippy::len_without_is_empty)] -impl<'buf, P> RegularOffsetBuffer<'buf, P> +impl<'buf, P> RegularOffsetBufferR<'buf, P> where P: Payload, { pub fn new(buffer: &'buf [P]) -> Self { check_buffer_not_empty(buffer); - RegularOffsetBuffer(buffer, PhantomData) + RegularOffsetBufferR(buffer, PhantomData) } pub fn get(self, index: usize) -> P { @@ -835,36 +827,36 @@ where } } -impl<'s, P> AsImmutable<'s> for RegularOffsetBuffer<'_, P> +impl<'s, P> AsImmutable<'s> for RegularOffsetBufferR<'_, P> where P: Payload, { - type Target = RegularOffsetBuffer<'s, P>; + type Target = RegularOffsetBufferR<'s, P>; - unsafe fn as_immutable(&self) -> RegularOffsetBuffer

{ + unsafe fn as_immutable(&self) -> RegularOffsetBufferR

{ *self } } -unsafe impl

Send for RegularOffsetBuffer<'_, P> where P: Payload {} +unsafe impl

Send for RegularOffsetBufferR<'_, P> where P: Payload {} -unsafe impl

Sync for RegularOffsetBuffer<'_, P> where P: Payload {} +unsafe impl

Sync for RegularOffsetBufferR<'_, P> where P: Payload {} -pub type RegularOffsetBufferStatic

= RegularOffsetBuffer<'static, P>; +pub type RegularOffsetBufferRStatic

= RegularOffsetBufferR<'static, P>; -pub struct RegularOffsetBufferMut<'buf, P>(*mut [P], PhantomData<&'buf mut P>) +pub struct RegularOffsetBufferW<'buf, P>(*mut [P], PhantomData<&'buf mut P>) where P: Payload; #[allow(clippy::len_without_is_empty)] -impl<'buf, P> RegularOffsetBufferMut<'buf, P> +impl<'buf, P> RegularOffsetBufferW<'buf, P> where P: Payload, { pub fn new(buffer: &'buf mut [P]) -> Self { check_buffer_not_empty(buffer); - RegularOffsetBufferMut(buffer, PhantomData) + RegularOffsetBufferW(buffer, PhantomData) } /// # Safety @@ -904,22 +896,22 @@ where } } -impl<'s, P> AsImmutable<'s> for RegularOffsetBufferMut<'_, P> +impl<'s, P> AsImmutable<'s> for RegularOffsetBufferW<'_, P> where P: Payload, { - type Target = RegularOffsetBuffer<'s, P>; + type Target = RegularOffsetBufferR<'s, P>; - unsafe fn as_immutable(&self) -> RegularOffsetBuffer

{ - RegularOffsetBuffer(self.0, PhantomData) + unsafe fn as_immutable(&self) -> RegularOffsetBufferR

{ + RegularOffsetBufferR(self.0, PhantomData) } } -unsafe impl

Send for RegularOffsetBufferMut<'_, P> where P: Payload {} +unsafe impl

Send for RegularOffsetBufferW<'_, P> where P: Payload {} -unsafe impl

Sync for RegularOffsetBufferMut<'_, P> where P: Payload {} +unsafe impl

Sync for RegularOffsetBufferW<'_, P> where P: Payload {} -pub type RegularOffsetBufferMutStatic

= RegularOffsetBufferMut<'static, P>; +pub type RegularOffsetBufferWStatic

= RegularOffsetBufferW<'static, P>; unsafe fn read_volatile_slice_buffer

( slice_ptr: *const [P], @@ -933,7 +925,7 @@ where } #[derive(Clone, Copy)] -pub struct WordOffsetBuffer<'buf, 'wo, P>( +pub struct WordOffsetBufferR<'buf, 'wo, P>( &'wo [*const P], PhantomData<&'buf P>, ) @@ -941,7 +933,7 @@ where P: Payload; #[allow(clippy::len_without_is_empty)] -impl<'buf, 'wo, P> WordOffsetBuffer<'buf, 'wo, P> +impl<'buf, 'wo, P> WordOffsetBufferR<'buf, 'wo, P> where P: Payload, { @@ -952,7 +944,7 @@ where check_word_offset(buffer); - WordOffsetBuffer(buffer, PhantomData) + WordOffsetBufferR(buffer, PhantomData) } pub fn get(self, index: usize) -> P { @@ -968,30 +960,30 @@ where } } -impl<'s, P> AsImmutable<'s> for WordOffsetBuffer<'_, '_, P> +impl<'s, P> AsImmutable<'s> for WordOffsetBufferR<'_, '_, P> where P: Payload, { - type Target = WordOffsetBuffer<'s, 's, P>; + type Target = WordOffsetBufferR<'s, 's, P>; - unsafe fn as_immutable(&self) -> WordOffsetBuffer

{ + unsafe fn as_immutable(&self) -> WordOffsetBufferR

{ *self } } -unsafe impl<'buf, 'wo, P> Send for WordOffsetBuffer<'buf, 'wo, P> where +unsafe impl<'buf, 'wo, P> Send for WordOffsetBufferR<'buf, 'wo, P> where P: Payload { } -unsafe impl<'buf, 'wo, P> Sync for WordOffsetBuffer<'buf, 'wo, P> where +unsafe impl<'buf, 'wo, P> Sync for WordOffsetBufferR<'buf, 'wo, P> where P: Payload { } -pub type WordOffsetBufferStatic<'wo, P> = WordOffsetBuffer<'static, 'wo, P>; +pub type WordOffsetBufferRStatic<'wo, P> = WordOffsetBufferR<'static, 'wo, P>; -pub struct WordOffsetBufferMut<'buf, 'wo, P>( +pub struct WordOffsetBufferW<'buf, 'wo, P>( &'wo mut [*mut P], PhantomData<&'buf mut P>, ) @@ -999,7 +991,7 @@ where P: Payload; #[allow(clippy::len_without_is_empty)] -impl<'buf, 'wo, P> WordOffsetBufferMut<'buf, 'wo, P> +impl<'buf, 'wo, P> WordOffsetBufferW<'buf, 'wo, P> where P: Payload, { @@ -1009,7 +1001,7 @@ where unsafe { check_word_offset::

(&*(buffer as *const _ as *const _)); - WordOffsetBufferMut(&mut *(buffer as *mut _ as *mut _), PhantomData) + WordOffsetBufferW(&mut *(buffer as *mut _ as *mut _), PhantomData) } } @@ -1040,23 +1032,22 @@ where } } -impl<'s, P> AsImmutable<'s> for WordOffsetBufferMut<'_, '_, P> +impl<'s, P> AsImmutable<'s> for WordOffsetBufferW<'_, '_, P> where P: Payload, { - type Target = WordOffsetBuffer<'s, 's, P>; + type Target = WordOffsetBufferR<'s, 's, P>; - unsafe fn as_immutable(&self) -> WordOffsetBuffer

{ - WordOffsetBuffer(&*(self.0 as *const _ as *const _), PhantomData) + unsafe fn as_immutable(&self) -> WordOffsetBufferR

{ + WordOffsetBufferR(&*(self.0 as *const _ as *const _), PhantomData) } } -unsafe impl

Send for WordOffsetBufferMut<'_, '_, P> where P: Payload {} +unsafe impl

Send for WordOffsetBufferW<'_, '_, P> where P: Payload {} -unsafe impl

Sync for WordOffsetBufferMut<'_, '_, P> where P: Payload {} +unsafe impl

Sync for WordOffsetBufferW<'_, '_, P> where P: Payload {} -pub type WordOffsetBufferMutStatic<'wo, P> = - WordOffsetBufferMut<'static, 'wo, P>; +pub type WordOffsetBufferWStatic<'wo, P> = WordOffsetBufferW<'static, 'wo, P>; fn check_buffer_not_empty

(buffer: &[P]) { if buffer.is_empty() { @@ -1101,8 +1092,8 @@ where /// - `Ndt` pub(super) fn configure_safe_transfer( stream: &mut Stream, - source: ImmutableBuffer, - dest: &MutableBuffer, + source: BufferR, + dest: &BufferW, ) where CXX: ChannelId, DMA: DMATrait, @@ -1126,8 +1117,8 @@ pub(super) fn configure_safe_transfer( fn configure_buffers( stream: &mut Stream, - peripheral: PeripheralBuffer, - memory: MemoryBuffer, + peripheral: PeripheralBufferR, + memory: MemoryBufferR, ) where CXX: ChannelId, DMA: DMATrait, @@ -1145,17 +1136,17 @@ fn configure_buffers( stream.set_m_size(m_size.into()); match peripheral { - PeripheralBuffer::Fixed(buffer) => { + PeripheralBufferR::Fixed(buffer) => { stream.set_pa(Pa(buffer.as_ptr() as u32)); stream.set_pinc(Pinc::Fixed); } - PeripheralBuffer::Incremented(buffer) => match buffer { - IncrementedBuffer::RegularOffset(buffer) => { + PeripheralBufferR::Incremented(buffer) => match buffer { + IncrementedBufferR::RegularOffset(buffer) => { stream.set_pa(Pa(buffer.as_ptr(0) as u32)); stream.set_pinc(Pinc::Incremented); stream.set_pincos(Pincos::PSize); } - IncrementedBuffer::WordOffset(buffer) => { + IncrementedBufferR::WordOffset(buffer) => { stream.set_pa(Pa(buffer.as_ptr(0) as u32)); stream.set_pinc(Pinc::Incremented); stream.set_pincos(Pincos::Word); @@ -1164,11 +1155,11 @@ fn configure_buffers( } match memory { - MemoryBuffer::Fixed(buffer) => { + MemoryBufferR::Fixed(buffer) => { stream.set_m0a(M0a(buffer.as_ptr() as u32)); stream.set_minc(Minc::Fixed); } - MemoryBuffer::Incremented(buffer) => { + MemoryBufferR::Incremented(buffer) => { stream.set_m0a(M0a(buffer.as_ptr(0) as u32)); stream.set_minc(Minc::Incremented); } @@ -1179,8 +1170,8 @@ fn configure_buffers( fn configure_ndt( stream: &mut Stream, - peripheral: PeripheralBuffer, - memory: MemoryBuffer, + peripheral: PeripheralBufferR, + memory: MemoryBufferR, ) where CXX: ChannelId, DMA: DMATrait, @@ -1188,12 +1179,12 @@ fn configure_ndt( Memory: Payload, { match peripheral { - PeripheralBuffer::Fixed(_) => { + PeripheralBufferR::Fixed(_) => { match memory { - MemoryBuffer::Fixed(_) => { + MemoryBufferR::Fixed(_) => { // NDT must be configured in advance } - MemoryBuffer::Incremented(buffer) => { + MemoryBufferR::Incremented(buffer) => { let p_size: usize = PayloadSize::from_payload::().into(); let m_size: usize = @@ -1210,7 +1201,7 @@ fn configure_ndt( } } } - PeripheralBuffer::Incremented(buffer) => { + PeripheralBufferR::Incremented(buffer) => { let ndt = u16::try_from(buffer.len()).unwrap(); stream.set_ndt(Ndt(ndt)); } @@ -1236,7 +1227,7 @@ pub(super) fn check_double_buffer_stream_config( pub(super) fn check_double_buffer<'s, MemBuf, P>(double_buffer: &'s [MemBuf; 2]) where - MemBuf: AsImmutable<'s, Target = MemoryBuffer<'s, P>>, + MemBuf: AsImmutable<'s, Target = MemoryBufferR<'s, P>>, P: Payload, { let double_buffer = unsafe { @@ -1246,13 +1237,13 @@ where ] }; match double_buffer[0] { - MemoryBuffer::Fixed(_) => { - if let MemoryBuffer::Incremented(_) = double_buffer[1] { + MemoryBufferR::Fixed(_) => { + if let MemoryBufferR::Incremented(_) = double_buffer[1] { panic!("Invalid double buffer config: First buffer `Fixed`, second buffer `Incremented`."); } } - MemoryBuffer::Incremented(buffer_0) => { - if let MemoryBuffer::Fixed(_) = double_buffer[1] { + MemoryBufferR::Incremented(buffer_0) => { + if let MemoryBufferR::Fixed(_) = double_buffer[1] { panic!("Invalid double buffer config: First buffer `Incremented`, second buffer `Fixed`."); } @@ -1273,19 +1264,19 @@ pub(super) fn first_ptr_from_buffer<'s, ImmutBuf, P>( buffer: &'s ImmutBuf, ) -> *const P where - ImmutBuf: AsImmutable<'s, Target = ImmutableBuffer<'s, 's, P>>, + ImmutBuf: AsImmutable<'s, Target = BufferR<'s, 's, P>>, P: Payload, { let buffer = unsafe { buffer.as_immutable() }; match buffer { - ImmutableBuffer::Peripheral(buffer) => match buffer { - PeripheralBuffer::Fixed(buffer) => buffer.as_ptr(), - PeripheralBuffer::Incremented(buffer) => buffer.as_ptr(0), + BufferR::Peripheral(buffer) => match buffer { + PeripheralBufferR::Fixed(buffer) => buffer.as_ptr(), + PeripheralBufferR::Incremented(buffer) => buffer.as_ptr(0), }, - ImmutableBuffer::Memory(buffer) => match buffer { - MemoryBuffer::Fixed(buffer) => buffer.as_ptr(), - MemoryBuffer::Incremented(buffer) => buffer.as_ptr(0), + BufferR::Memory(buffer) => match buffer { + MemoryBufferR::Fixed(buffer) => buffer.as_ptr(), + MemoryBufferR::Incremented(buffer) => buffer.as_ptr(0), }, } } From 35419b43fdffad81d7fb0939669f1bbd0413e0d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ad=C3=A4?= Date: Wed, 1 Jan 2020 12:26:55 +0100 Subject: [PATCH 050/103] wrapping enums for R/W buffers --- src/dma/safe_transfer.rs | 593 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 593 insertions(+) diff --git a/src/dma/safe_transfer.rs b/src/dma/safe_transfer.rs index cfa46802..bc0b9ec6 100644 --- a/src/dma/safe_transfer.rs +++ b/src/dma/safe_transfer.rs @@ -125,6 +125,67 @@ pub trait AsImmutable<'s> { unsafe fn as_immutable(&'s self) -> Self::Target; } +pub enum Buffer<'buf, 'wo, P> +where + P: Payload, +{ + Peripheral(PeripheralBuffer<'buf, 'wo, P>), + Memory(MemoryBuffer<'buf, P>), +} + +impl<'buf, 'wo, P> Buffer<'buf, 'wo, P> +where + P: Payload, +{ + pub fn into_peripheral(self) -> PeripheralBuffer<'buf, 'wo, P> { + if let Buffer::Peripheral(buffer) = self { + buffer + } else { + panic!("The buffer is a memory buffer."); + } + } + + pub fn as_peripheral(&self) -> &PeripheralBuffer<'buf, 'wo, P> { + if let Buffer::Peripheral(buffer) = self { + buffer + } else { + panic!("The buffer is a memory buffer."); + } + } + + pub fn as_mut_peripheral(&mut self) -> &mut PeripheralBuffer<'buf, 'wo, P> { + if let Buffer::Peripheral(buffer) = self { + buffer + } else { + panic!("The buffer is a memory buffer."); + } + } + + pub fn into_memory(self) -> MemoryBuffer<'buf, P> { + if let Buffer::Memory(buffer) = self { + buffer + } else { + panic!("The buffer is a peripheral puffer."); + } + } + + pub fn as_memory(&self) -> &MemoryBuffer<'buf, P> { + if let Buffer::Memory(buffer) = self { + buffer + } else { + panic!("The buffer is a peripheral puffer."); + } + } + + pub fn as_mut_memory(&mut self) -> &mut MemoryBuffer<'buf, P> { + if let Buffer::Memory(buffer) = self { + buffer + } else { + panic!("The buffer is a peripheral puffer."); + } + } +} + #[derive(Clone, Copy)] pub enum BufferR<'buf, 'wo, P> where @@ -166,6 +227,18 @@ where } } +impl<'buf, 'wo, P> From> for Buffer<'buf, 'wo, P> +where + P: Payload, +{ + fn from(buffer: BufferR<'buf, 'wo, P>) -> Self { + match buffer { + BufferR::Peripheral(buffer) => Buffer::Peripheral(buffer.into()), + BufferR::Memory(buffer) => Buffer::Memory(buffer.into()), + } + } +} + pub type BufferRStatic<'wo, P> = BufferR<'static, 'wo, P>; pub enum BufferW<'buf, 'wo, P> @@ -247,8 +320,81 @@ where } } +impl<'buf, 'wo, P> From> for Buffer<'buf, 'wo, P> +where + P: Payload, +{ + fn from(buffer: BufferW<'buf, 'wo, P>) -> Self { + match buffer { + BufferW::Peripheral(buffer) => Buffer::Peripheral(buffer.into()), + BufferW::Memory(buffer) => Buffer::Memory(buffer.into()), + } + } +} + pub type BufferWStatic<'wo, P> = BufferW<'static, 'wo, P>; +pub enum MemoryBuffer<'buf, P> +where + P: Payload, +{ + Fixed(FixedBuffer<'buf, P>), + Incremented(RegularOffsetBuffer<'buf, P>), +} + +impl<'buf, P> MemoryBuffer<'buf, P> +where + P: Payload, +{ + pub fn into_fixed(self) -> FixedBuffer<'buf, P> { + if let MemoryBuffer::Fixed(buffer) = self { + buffer + } else { + panic!("The buffer is incremented."); + } + } + + pub fn as_fixed(&self) -> &FixedBuffer<'buf, P> { + if let MemoryBuffer::Fixed(buffer) = self { + buffer + } else { + panic!("The buffer is incremented."); + } + } + + pub fn as_mut_fixed(&mut self) -> &mut FixedBuffer<'buf, P> { + if let MemoryBuffer::Fixed(buffer) = self { + buffer + } else { + panic!("The buffer is incremented."); + } + } + + pub fn into_incremented(self) -> RegularOffsetBuffer<'buf, P> { + if let MemoryBuffer::Incremented(buffer) = self { + buffer + } else { + panic!("The buffer is fixed."); + } + } + + pub fn as_incremented(&self) -> &RegularOffsetBuffer<'buf, P> { + if let MemoryBuffer::Incremented(buffer) = self { + buffer + } else { + panic!("The buffer is fixed."); + } + } + + pub fn as_mut_incremented(&mut self) -> &mut RegularOffsetBuffer<'buf, P> { + if let MemoryBuffer::Incremented(buffer) = self { + buffer + } else { + panic!("The buffer is fixed."); + } + } +} + #[derive(Clone, Copy)] pub enum MemoryBufferR<'buf, P> where @@ -290,6 +436,20 @@ where } } +impl<'buf, P> From> for MemoryBuffer<'buf, P> +where + P: Payload, +{ + fn from(buffer: MemoryBufferR<'buf, P>) -> Self { + match buffer { + MemoryBufferR::Fixed(buffer) => MemoryBuffer::Fixed(buffer.into()), + MemoryBufferR::Incremented(buffer) => { + MemoryBuffer::Incremented(buffer.into()) + } + } + } +} + pub type MemoryBufferRStatic

= MemoryBufferR<'static, P>; pub enum MemoryBufferW<'buf, P> @@ -371,8 +531,85 @@ where } } +impl<'buf, P> From> for MemoryBuffer<'buf, P> +where + P: Payload, +{ + fn from(buffer: MemoryBufferW<'buf, P>) -> Self { + match buffer { + MemoryBufferW::Fixed(buffer) => MemoryBuffer::Fixed(buffer.into()), + MemoryBufferW::Incremented(buffer) => { + MemoryBuffer::Incremented(buffer.into()) + } + } + } +} + pub type MemoryBufferWStatic

= MemoryBufferW<'static, P>; +pub enum PeripheralBuffer<'buf, 'wo, P> +where + P: Payload, +{ + Fixed(FixedBuffer<'buf, P>), + Incremented(IncrementedBuffer<'buf, 'wo, P>), +} + +impl<'buf, 'wo, P> PeripheralBuffer<'buf, 'wo, P> +where + P: Payload, +{ + pub fn into_fixed(self) -> FixedBuffer<'buf, P> { + if let PeripheralBuffer::Fixed(buffer) = self { + buffer + } else { + panic!("The buffer is incremented."); + } + } + + pub fn as_fixed(&self) -> &FixedBuffer<'buf, P> { + if let PeripheralBuffer::Fixed(buffer) = self { + buffer + } else { + panic!("The buffer is incremented."); + } + } + + pub fn as_mut_fixed(&mut self) -> &mut FixedBuffer<'buf, P> { + if let PeripheralBuffer::Fixed(buffer) = self { + buffer + } else { + panic!("The buffer is incremented."); + } + } + + pub fn into_incremented(self) -> IncrementedBuffer<'buf, 'wo, P> { + if let PeripheralBuffer::Incremented(buffer) = self { + buffer + } else { + panic!("The buffer is fixed."); + } + } + + pub fn as_incremented(&self) -> &IncrementedBuffer<'buf, 'wo, P> { + if let PeripheralBuffer::Incremented(buffer) = self { + buffer + } else { + panic!("The buffer is fixed."); + } + } + + pub fn as_mut_incremented( + &mut self, + ) -> &mut IncrementedBuffer<'buf, 'wo, P> { + if let PeripheralBuffer::Incremented(buffer) = self { + buffer + } else { + panic!("The buffer is fixed."); + } + } +} + #[derive(Clone, Copy)] pub enum PeripheralBufferR<'buf, 'wo, P> where @@ -414,6 +651,23 @@ where } } +impl<'buf, 'wo, P> From> + for PeripheralBuffer<'buf, 'wo, P> +where + P: Payload, +{ + fn from(buffer: PeripheralBufferR<'buf, 'wo, P>) -> Self { + match buffer { + PeripheralBufferR::Fixed(buffer) => { + PeripheralBuffer::Fixed(buffer.into()) + } + PeripheralBufferR::Incremented(buffer) => { + PeripheralBuffer::Incremented(buffer.into()) + } + } + } +} + pub type PeripheralBufferRStatic<'wo, P> = PeripheralBufferR<'static, 'wo, P>; pub enum PeripheralBufferW<'buf, 'wo, P> @@ -497,8 +751,111 @@ where } } +impl<'buf, 'wo, P> From> + for PeripheralBuffer<'buf, 'wo, P> +where + P: Payload, +{ + fn from(buffer: PeripheralBufferW<'buf, 'wo, P>) -> Self { + match buffer { + PeripheralBufferW::Fixed(buffer) => { + PeripheralBuffer::Fixed(buffer.into()) + } + PeripheralBufferW::Incremented(buffer) => { + PeripheralBuffer::Incremented(buffer.into()) + } + } + } +} + pub type PeripheralBufferWStatic<'wo, P> = PeripheralBufferW<'static, 'wo, P>; +pub enum IncrementedBuffer<'buf, 'wo, P> +where + P: Payload, +{ + RegularOffset(RegularOffsetBuffer<'buf, P>), + WordOffset(WordOffsetBuffer<'buf, 'wo, P>), +} + +impl<'buf, 'wo, P> IncrementedBuffer<'buf, 'wo, P> +where + P: Payload, +{ + pub fn into_regular_offset(self) -> RegularOffsetBuffer<'buf, P> { + if let IncrementedBuffer::RegularOffset(buffer) = self { + buffer + } else { + panic!("The buffer has word offset."); + } + } + + pub fn as_regular_offset(&self) -> &RegularOffsetBuffer<'buf, P> { + if let IncrementedBuffer::RegularOffset(buffer) = self { + buffer + } else { + panic!("The buffer has word offset."); + } + } + + pub fn as_mut_regular_offset( + &mut self, + ) -> &mut RegularOffsetBuffer<'buf, P> { + if let IncrementedBuffer::RegularOffset(buffer) = self { + buffer + } else { + panic!("The buffer has word offset."); + } + } + + pub fn into_word_offset(self) -> WordOffsetBuffer<'buf, 'wo, P> { + if let IncrementedBuffer::WordOffset(buffer) = self { + buffer + } else { + panic!("The buffer has regular offset."); + } + } + + pub fn as_word_offset(&self) -> &WordOffsetBuffer<'buf, 'wo, P> { + if let IncrementedBuffer::WordOffset(buffer) = self { + buffer + } else { + panic!("The buffer has regular offset."); + } + } + + pub fn as_mut_word_offset( + &mut self, + ) -> &mut WordOffsetBuffer<'buf, 'wo, P> { + if let IncrementedBuffer::WordOffset(buffer) = self { + buffer + } else { + panic!("The buffer has regular offset."); + } + } + + pub fn len(self) -> usize { + match self { + IncrementedBuffer::RegularOffset(buffer) => buffer.len(), + IncrementedBuffer::WordOffset(buffer) => buffer.len(), + } + } + + pub unsafe fn get(self, index: usize) -> P { + match self { + IncrementedBuffer::RegularOffset(buffer) => buffer.get(index), + IncrementedBuffer::WordOffset(buffer) => buffer.get(index), + } + } + + pub fn as_ptr(&self, index: usize) -> *const P { + match self { + IncrementedBuffer::RegularOffset(buffer) => buffer.as_ptr(index), + IncrementedBuffer::WordOffset(buffer) => buffer.as_ptr(index), + } + } +} + #[derive(Clone, Copy)] pub enum IncrementedBufferR<'buf, 'wo, P> where @@ -562,6 +919,23 @@ where } } +impl<'buf, 'wo, P> From> + for IncrementedBuffer<'buf, 'wo, P> +where + P: Payload, +{ + fn from(buffer: IncrementedBufferR<'buf, 'wo, P>) -> Self { + match buffer { + IncrementedBufferR::RegularOffset(buffer) => { + IncrementedBuffer::RegularOffset(buffer.into()) + } + IncrementedBufferR::WordOffset(buffer) => { + IncrementedBuffer::WordOffset(buffer.into()) + } + } + } +} + pub type IncrementedBufferRStatic<'wo, P> = IncrementedBufferR<'static, 'wo, P>; pub enum IncrementedBufferW<'buf, 'wo, P> @@ -699,8 +1073,33 @@ where } } +impl<'buf, 'wo, P> From> + for IncrementedBuffer<'buf, 'wo, P> +where + P: Payload, +{ + fn from(buffer: IncrementedBufferW<'buf, 'wo, P>) -> Self { + match buffer { + IncrementedBufferW::RegularOffset(buffer) => { + IncrementedBuffer::RegularOffset(buffer.into()) + } + IncrementedBufferW::WordOffset(buffer) => { + IncrementedBuffer::WordOffset(buffer.into()) + } + } + } +} + pub type IncrementedBufferWStatic<'wo, P> = IncrementedBufferW<'static, 'wo, P>; +pub enum FixedBuffer<'buf, P> +where + P: Payload, +{ + Read(FixedBufferR<'buf, P>), + Write(FixedBufferW<'buf, P>), +} + #[derive(Clone, Copy)] pub struct FixedBufferR<'buf, P>(*const P, PhantomData<&'buf P>) where @@ -734,6 +1133,15 @@ where } } +impl<'buf, P> From> for FixedBuffer<'buf, P> +where + P: Payload, +{ + fn from(buffer: FixedBufferR<'buf, P>) -> Self { + FixedBuffer::Read(buffer) + } +} + unsafe impl

Send for FixedBufferR<'_, P> where P: Payload {} unsafe impl

Sync for FixedBufferR<'_, P> where P: Payload {} @@ -786,12 +1194,89 @@ where } } +impl<'buf, P> From> for FixedBuffer<'buf, P> +where + P: Payload, +{ + fn from(buffer: FixedBufferW<'buf, P>) -> Self { + FixedBuffer::Write(buffer) + } +} + unsafe impl

Send for FixedBufferW<'_, P> where P: Payload {} unsafe impl

Sync for FixedBufferW<'_, P> where P: Payload {} pub type FixedBufferWStatic

= FixedBufferW<'static, P>; +pub enum RegularOffsetBuffer<'buf, P> +where + P: Payload, +{ + Read(RegularOffsetBufferR<'buf, P>), + Write(RegularOffsetBufferW<'buf, P>), +} + +impl<'buf, P> RegularOffsetBuffer<'buf, P> +where + P: Payload, +{ + pub fn as_read(&self) -> RegularOffsetBufferR<'buf, P> { + if let &RegularOffsetBuffer::Read(buffer) = self { + buffer + } else { + panic!("The buffer is a write buffer."); + } + } + + pub fn into_write(self) -> RegularOffsetBufferW<'buf, P> { + if let RegularOffsetBuffer::Write(buffer) = self { + buffer + } else { + panic!("The buffer is a read buffer."); + } + } + + pub fn as_write(&self) -> &RegularOffsetBufferW<'buf, P> { + if let RegularOffsetBuffer::Write(buffer) = self { + buffer + } else { + panic!("The buffer is a read buffer."); + } + } + + pub fn as_mut_write(&mut self) -> &mut RegularOffsetBufferW<'buf, P> { + if let RegularOffsetBuffer::Write(buffer) = self { + buffer + } else { + panic!("The buffer is a read buffer."); + } + } + + // Methods both variants implement + + pub unsafe fn get(&self, index: usize) -> P { + match self { + RegularOffsetBuffer::Read(buffer) => buffer.get(index), + RegularOffsetBuffer::Write(buffer) => buffer.get(index), + } + } + + pub fn as_ptr(&self, index: usize) -> *const P { + match self { + RegularOffsetBuffer::Read(buffer) => buffer.as_ptr(index), + RegularOffsetBuffer::Write(buffer) => buffer.as_ptr(index), + } + } + + pub fn len(&self) -> usize { + match self { + RegularOffsetBuffer::Read(buffer) => buffer.len(), + RegularOffsetBuffer::Write(buffer) => buffer.len(), + } + } +} + #[derive(Clone, Copy)] pub struct RegularOffsetBufferR<'buf, P>(*const [P], PhantomData<&'buf P>) where @@ -838,6 +1323,16 @@ where } } +impl<'buf, P> From> + for RegularOffsetBuffer<'buf, P> +where + P: Payload, +{ + fn from(buffer: RegularOffsetBufferR<'buf, P>) -> Self { + RegularOffsetBuffer::Read(buffer) + } +} + unsafe impl

Send for RegularOffsetBufferR<'_, P> where P: Payload {} unsafe impl

Sync for RegularOffsetBufferR<'_, P> where P: Payload {} @@ -907,6 +1402,16 @@ where } } +impl<'buf, P> From> + for RegularOffsetBuffer<'buf, P> +where + P: Payload, +{ + fn from(buffer: RegularOffsetBufferW<'buf, P>) -> Self { + RegularOffsetBuffer::Write(buffer) + } +} + unsafe impl

Send for RegularOffsetBufferW<'_, P> where P: Payload {} unsafe impl

Sync for RegularOffsetBufferW<'_, P> where P: Payload {} @@ -924,6 +1429,74 @@ where ptr::read_volatile(&slice[index] as *const _) } +pub enum WordOffsetBuffer<'buf, 'wo, P> +where + P: Payload, +{ + Read(WordOffsetBufferR<'buf, 'wo, P>), + Write(WordOffsetBufferW<'buf, 'wo, P>), +} + +impl<'buf, 'wo, P> WordOffsetBuffer<'buf, 'wo, P> +where + P: Payload, +{ + pub fn as_read(&self) -> WordOffsetBufferR<'buf, 'wo, P> { + if let &WordOffsetBuffer::Read(buffer) = self { + buffer + } else { + panic!("The buffer is a write buffer."); + } + } + + pub fn into_write(self) -> WordOffsetBufferW<'buf, 'wo, P> { + if let WordOffsetBuffer::Write(buffer) = self { + buffer + } else { + panic!("The buffer is a read buffer."); + } + } + + pub fn as_write(&self) -> &WordOffsetBufferW<'buf, 'wo, P> { + if let WordOffsetBuffer::Write(buffer) = self { + buffer + } else { + panic!("The buffer is a read buffer."); + } + } + + pub fn as_mut_write(&mut self) -> &mut WordOffsetBufferW<'buf, 'wo, P> { + if let WordOffsetBuffer::Write(buffer) = self { + buffer + } else { + panic!("The buffer is a read buffer."); + } + } + + // Methods both variants implement + + pub unsafe fn get(&self, index: usize) -> P { + match self { + WordOffsetBuffer::Read(buffer) => buffer.get(index), + WordOffsetBuffer::Write(buffer) => buffer.get(index), + } + } + + pub fn as_ptr(&self, index: usize) -> *const P { + match self { + WordOffsetBuffer::Read(buffer) => buffer.as_ptr(index), + WordOffsetBuffer::Write(buffer) => buffer.as_ptr(index), + } + } + + pub fn len(&self) -> usize { + match self { + WordOffsetBuffer::Read(buffer) => buffer.len(), + WordOffsetBuffer::Write(buffer) => buffer.len(), + } + } +} + #[derive(Clone, Copy)] pub struct WordOffsetBufferR<'buf, 'wo, P>( &'wo [*const P], @@ -971,6 +1544,16 @@ where } } +impl<'buf, 'wo, P> From> + for WordOffsetBuffer<'buf, 'wo, P> +where + P: Payload, +{ + fn from(buffer: WordOffsetBufferR<'buf, 'wo, P>) -> Self { + WordOffsetBuffer::Read(buffer) + } +} + unsafe impl<'buf, 'wo, P> Send for WordOffsetBufferR<'buf, 'wo, P> where P: Payload { @@ -1043,6 +1626,16 @@ where } } +impl<'buf, 'wo, P> From> + for WordOffsetBuffer<'buf, 'wo, P> +where + P: Payload, +{ + fn from(buffer: WordOffsetBufferW<'buf, 'wo, P>) -> Self { + WordOffsetBuffer::Write(buffer) + } +} + unsafe impl

Send for WordOffsetBufferW<'_, '_, P> where P: Payload {} unsafe impl

Sync for WordOffsetBufferW<'_, '_, P> where P: Payload {} From 10bd944c4a5c8c9ccc398e78824669f5f7bce6aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ad=C3=A4?= Date: Thu, 9 Jan 2020 00:38:06 +0100 Subject: [PATCH 051/103] Reworked safe transfer --- src/dma.rs | 502 +++++---------- src/dma/safe_transfer.rs | 1284 ++++++++++++-------------------------- 2 files changed, 545 insertions(+), 1241 deletions(-) diff --git a/src/dma.rs b/src/dma.rs index c8911392..642e07f3 100644 --- a/src/dma.rs +++ b/src/dma.rs @@ -25,11 +25,10 @@ use self::mux::{ SyncEnabled, SyncId, SyncOverrunInterrupt, SyncPolarity, }; use self::safe_transfer::{ - check_double_buffer, check_double_buffer_stream_config, - configure_safe_transfer, first_ptr_from_buffer, BufferR, BufferRStatic, - BufferW, BufferWStatic, MemoryBufferRStatic, MemoryBufferWStatic, Ongoing, - Payload, PeripheralBufferRStatic, PeripheralBufferWStatic, Start, - TransferState, + check_buffer, check_double_buffer, configure_safe_transfer, mut_ptr_memory, + mut_ptr_peripheral, set_memory_impl, set_peripheral_impl, DoubleBuffer, + MemoryBufferStatic, Ongoing, Payload, PayloadPort, PeripheralBufferStatic, + PointerPort, Start, TransferState, }; use self::stm32::dma1::ST; use self::stm32::dmamux1::CCR; @@ -513,22 +512,13 @@ where } pub fn effective_circular_mode(&self) -> CircularMode { - if !self.circular_mode_possible() { - CircularMode::Disabled - } else if self.buffer_mode() == BufferMode::DoubleBuffer { + if self.buffer_mode() == BufferMode::DoubleBuffer { CircularMode::Enabled } else { self.circular_mode() } } - fn circular_mode_possible(&self) -> bool { - // `effective_flow_controller` not needed because `flow_controller` gets only forced to - // `DMA`, if `transfer_dir` is `M2M`, which is already covered in first case. - self.transfer_direction() != TransferDirection::M2M - && self.flow_controller() == FlowController::Dma - } - pub fn effective_m_size(&self) -> MSize { if self.transfer_mode() == TransferMode::Direct { match self.p_size() { @@ -541,14 +531,6 @@ where } } - pub fn effective_buffer_mode(&self) -> BufferMode { - if !self.circular_mode_possible() { - BufferMode::Regular - } else { - self.buffer_mode() - } - } - pub fn effective_pincos(&self) -> Option { if self.pinc() == Pinc::Fixed { return None; @@ -626,16 +608,9 @@ where /// # Safety /// /// Aliasing rules aren't enforced - pub unsafe fn enable(mut self) -> Stream { + pub unsafe fn enable(self) -> Stream { self.check_config(); - // To avoid TransferErrorInterrupt because of invalid configuration - self.set_buffer_mode(self.effective_buffer_mode()); - // Only in this case we need to force this value **by software** - if self.transfer_direction() == TransferDirection::M2M { - self.set_circular_mode(CircularMode::Disabled); - } - self.enable_unchecked() } @@ -652,7 +627,7 @@ where } fn check_config(&self) { - if self.circular_mode() == CircularMode::Enabled { + if self.effective_circular_mode() == CircularMode::Enabled { self.check_config_circular(); } @@ -664,6 +639,14 @@ where } fn check_config_circular(&self) { + // Check for clashing config values + if self.transfer_direction() == TransferDirection::M2M + || self.flow_controller() == FlowController::Peripheral + { + panic!("For circular streams, the transfer direction must not be `M2M` and the FlowController must not be `Peripheral`."); + } + + // Check invariants if self.transfer_mode() == TransferMode::Fifo { let ndt = self.ndt().value() as usize; let m_burst = self.m_burst().into_num(); @@ -1390,91 +1373,82 @@ where { } -pub struct SafeTransfer<'wo, Source, Dest, State> +pub struct SafeTransfer<'wo, Peripheral, Memory, State> where - Source: Payload, - Dest: Payload, + Peripheral: Payload, + Memory: Payload, State: TransferState, { - source: BufferRStatic<'wo, Source>, - dest: BufferWStatic<'wo, Dest>, + peripheral: PeripheralBufferStatic<'wo, Peripheral>, + memory: MemoryBufferStatic, state: State, } -impl<'wo, Source, Dest> SafeTransfer<'wo, Source, Dest, Start> +impl<'wo, Peripheral, Memory> SafeTransfer<'wo, Peripheral, Memory, Start> where - Source: Payload, - Dest: Payload, + Peripheral: Payload, + Memory: Payload, { pub fn new( - source: BufferRStatic<'wo, Source>, - dest: BufferWStatic<'wo, Dest>, + peripheral: PeripheralBufferStatic<'wo, Peripheral>, + memory: MemoryBufferStatic, ) -> Self { + check_buffer(&peripheral, &memory); + SafeTransfer { - source, - dest, + peripheral, + memory, state: Start, } } } -impl<'wo, Source, Dest, State> SafeTransfer<'wo, Source, Dest, State> +impl<'wo, Peripheral, Memory, State> + SafeTransfer<'wo, Peripheral, Memory, State> where - Source: Payload, - Dest: Payload, + Peripheral: Payload, + Memory: Payload, State: TransferState, { - pub fn source(&self) -> BufferRStatic<'wo, Source> { - self.source + pub fn peripheral(&self) -> &PeripheralBufferStatic<'wo, Peripheral> { + &self.peripheral } - pub fn dest(&self) -> &BufferWStatic<'wo, Dest> { - &self.dest + pub fn memory(&self) -> &MemoryBufferStatic { + &self.memory } /// # Safety /// /// The caller must ensure, that the DMA is currently not modifying this address. - pub unsafe fn set_dest_fixed(&mut self, payload: Dest) { - match &mut self.dest { - BufferW::Peripheral(buffer) => { - buffer.as_mut_fixed().set(payload); - } - BufferW::Memory(buffer) => { - buffer.as_mut_fixed().set(payload); - } + pub unsafe fn set_dest( + &mut self, + index: Option, + payload: PayloadPort, + ) { + if self.peripheral.is_write() { + set_peripheral_impl( + &mut self.peripheral, + index, + payload.peripheral(), + ); + } else { + set_memory_impl(&mut self.memory, index, payload.memory()); } } - /// # Safety - /// - /// The caller must ensure, that the DMA is currently not modifying this address. - pub unsafe fn set_dest_incremented(&mut self, index: usize, payload: Dest) { - match &mut self.dest { - BufferW::Peripheral(buffer) => { - buffer.as_mut_incremented().set(index, payload); - } - BufferW::Memory(buffer) => { - buffer.as_mut_incremented().set(index, payload); - } - } - } + pub fn dest_ptr( + &mut self, + index: Option, + ) -> PointerPort { + if self.peripheral.is_write() { + let ptr = mut_ptr_peripheral(&mut self.peripheral, index); - pub fn dest_ptr_fixed(&mut self) -> *mut Dest { - match &mut self.dest { - BufferW::Peripheral(buffer) => buffer.as_mut_fixed().as_mut_ptr(), - BufferW::Memory(buffer) => buffer.as_mut_fixed().as_mut_ptr(), - } - } + PointerPort::Peripheral(ptr) + } else { + let ptr = mut_ptr_memory(&mut self.memory, index); - pub fn dest_ptr_incremented(&mut self, index: usize) -> *mut Dest { - match &mut self.dest { - BufferW::Peripheral(buffer) => { - buffer.as_mut_incremented().as_mut_ptr(index) - } - BufferW::Memory(buffer) => { - buffer.as_mut_incremented().as_mut_ptr(index) - } + PointerPort::Memory(ptr) } } } @@ -1492,12 +1466,12 @@ where CXX: ChannelId, DMA: DMATrait, { - configure_safe_transfer(&mut stream, self.source, &self.dest); + configure_safe_transfer(&mut stream, &self.peripheral, &self.memory); stream.set_buffer_mode(BufferMode::Regular); SafeTransfer { - source: self.source, - dest: self.dest, + peripheral: self.peripheral, + memory: self.memory, state: Ongoing { stream: unsafe { stream.enable() }, }, @@ -1556,310 +1530,120 @@ where } /// Safe Transfer with Double Buffer as Source -pub struct SafeTransferDoubleBufferR<'wo, Source, Dest, State> +pub struct SafeTransferDoubleBuffer<'wo, Peripheral, Memory, State> where - Source: Payload, - Dest: Payload, + Peripheral: Payload, + Memory: Payload, State: TransferState, { - sources: [MemoryBufferRStatic; 2], - dest: PeripheralBufferWStatic<'wo, Dest>, + peripheral: PeripheralBufferStatic<'wo, Peripheral>, + memories: [MemoryBufferStatic; 2], state: State, } -impl<'wo, Source, Dest> SafeTransferDoubleBufferR<'wo, Source, Dest, Start> +impl<'wo, Peripheral, Memory> + SafeTransferDoubleBuffer<'wo, Peripheral, Memory, Start> where - Source: Payload, - Dest: Payload, + Peripheral: Payload, + Memory: Payload, { pub fn new( - sources: [MemoryBufferRStatic; 2], - dest: PeripheralBufferWStatic<'wo, Dest>, + peripheral: PeripheralBufferStatic<'wo, Peripheral>, + memories: [MemoryBufferStatic; 2], ) -> Self { - check_double_buffer(&sources); + check_buffer(&peripheral, &memories[0]); + check_double_buffer(&memories); - SafeTransferDoubleBufferR { - sources, - dest, + SafeTransferDoubleBuffer { + peripheral, + memories, state: Start, } } } -impl<'wo, Source, Dest, State> - SafeTransferDoubleBufferR<'wo, Source, Dest, State> +impl<'wo, Peripheral, Memory, State> + SafeTransferDoubleBuffer<'wo, Peripheral, Memory, State> where - Source: Payload, - Dest: Payload, + Peripheral: Payload, + Memory: Payload, State: TransferState, { - pub fn sources(&self) -> [MemoryBufferRStatic; 2] { - self.sources - } - - pub fn dest(&self) -> &PeripheralBufferWStatic<'wo, Dest> { - &self.dest - } - - /// # Safety - /// - /// The caller must ensure, that the DMA is currently not modifying this address. - pub unsafe fn set_dest_fixed(&mut self, payload: Dest) { - self.dest.as_mut_fixed().set(payload); - } - - /// # Safety - /// - /// The caller must ensure, that the DMA is currently not modifying this address. - pub unsafe fn set_dest_incremented(&mut self, index: usize, payload: Dest) { - self.dest.as_mut_incremented().set(index, payload); - } - - pub fn dest_ptr_fixed(&mut self) -> *mut Dest { - self.dest.as_mut_fixed().as_mut_ptr() - } - - pub fn dest_ptr_incremented(&mut self, index: usize) -> *mut Dest { - self.dest.as_mut_incremented().as_mut_ptr(index) - } -} - -impl<'wo, Source, Dest> SafeTransferDoubleBufferR<'wo, Source, Dest, Start> -where - Source: Payload, - Dest: Payload, -{ - pub fn start( - self, - mut stream: Stream, - ) -> SafeTransferDoubleBufferR<'wo, Source, Dest, Ongoing> - where - CXX: ChannelId, - DMA: DMATrait, - { - check_double_buffer_stream_config(&stream); - - let dest_buffer = BufferW::Peripheral(self.dest); - - configure_safe_transfer( - &mut stream, - BufferR::Memory(self.sources[0]), - &dest_buffer, - ); - stream.set_buffer_mode(BufferMode::DoubleBuffer); - - let dest_buffer = dest_buffer.into_peripheral(); - - SafeTransferDoubleBufferR { - sources: self.sources, - dest: dest_buffer, - state: Ongoing { - stream: unsafe { stream.enable() }, - }, - } - } -} - -impl - SafeTransferDoubleBufferR<'_, Source, Dest, Ongoing> -where - Source: Payload, - Dest: Payload, - CXX: ChannelId, - DMA: DMATrait, -{ - pub fn stream(&self) -> &Stream { - &self.state.stream - } - - pub fn set_transfer_complete_interrupt( - &mut self, - tc_intrpt: TransferCompleteInterrupt, - ) { - self.state.stream.set_transfer_complete_interrupt(tc_intrpt); - } - - pub fn set_half_transfer_interrupt( - &mut self, - ht_intrpt: HalfTransferInterrupt, - ) { - self.state.stream.set_half_transfer_interrupt(ht_intrpt); + pub fn peripheral(&self) -> &PeripheralBufferStatic<'wo, Peripheral> { + &self.peripheral } - pub fn set_transfer_error_interrupt( - &mut self, - te_intrpt: TransferErrorInterrupt, - ) { - self.state.stream.set_transfer_error_interrupt(te_intrpt); + pub fn memories(&self) -> &[MemoryBufferStatic; 2] { + &self.memories } - pub fn set_direct_mode_error_interrupt( + pub unsafe fn set_dest( &mut self, - dme_intrpt: DirectModeErrorInterrupt, + index: Option, + double_buffer: Option, + payload: PayloadPort, ) { - self.state - .stream - .set_direct_mode_error_interrupt(dme_intrpt); - } - - pub fn set_fifo_error_interrupt(&mut self, fe_intrpt: FifoErrorInterrupt) { - self.state.stream.set_fifo_error_interrupt(fe_intrpt); - } - - pub fn set_m0a(&mut self, m0a: MemoryBufferRStatic) { - let ptr = first_ptr_from_buffer(&BufferR::Memory(m0a)); - - mem::replace(&mut self.sources[0], m0a); - - check_double_buffer(&self.sources); - - block!(self.state.stream.set_m0a(M0a(ptr as u32))).unwrap(); - } - - pub fn set_m1a(&mut self, m1a: MemoryBufferRStatic) { - let ptr = first_ptr_from_buffer(&BufferR::Memory(m1a)); - - mem::replace(&mut self.sources[1], m1a); - - check_double_buffer(&self.sources); - - block!(self.state.stream.set_m1a(M1a(ptr as u32))).unwrap(); - } - - pub fn stop(self) -> Stream { - self.state.stream.disable().await_disabled() - } -} - -/// Safe Transfer with Double Buffer as Destination -pub struct SafeTransferDoubleBufferW<'wo, Source, Dest, State> -where - Source: Payload, - Dest: Payload, - State: TransferState, -{ - source: PeripheralBufferRStatic<'wo, Source>, - dests: [MemoryBufferWStatic; 2], - state: State, -} - -impl<'wo, Source, Dest> SafeTransferDoubleBufferW<'wo, Source, Dest, Start> -where - Source: Payload, - Dest: Payload, -{ - pub fn new( - source: PeripheralBufferRStatic<'wo, Source>, - dests: [MemoryBufferWStatic; 2], - ) -> Self { - check_double_buffer(&dests); - - SafeTransferDoubleBufferW { - source, - dests, - state: Start, + if self.peripheral.is_write() { + set_peripheral_impl( + &mut self.peripheral, + index, + payload.peripheral(), + ); + } else { + set_memory_impl( + &mut self.memories[double_buffer.unwrap().index()], + index, + payload.memory(), + ); } } -} - -impl<'wo, Source, Dest, State> - SafeTransferDoubleBufferW<'wo, Source, Dest, State> -where - Source: Payload, - Dest: Payload, - State: TransferState, -{ - pub fn source(&self) -> PeripheralBufferRStatic<'wo, Source> { - self.source - } - pub fn dest(&self) -> &[MemoryBufferWStatic; 2] { - &self.dests - } - - /// # Safety - /// - /// The caller must ensure, that the DMA is currently not modifying this address. - pub unsafe fn set_dest_fixed_m0a(&mut self, payload: Dest) { - self.dests[0].as_mut_fixed().set(payload); - } - - /// # Safety - /// - /// The caller must ensure, that the DMA is currently not modifying this address. - pub unsafe fn set_dest_fixed_m1a(&mut self, payload: Dest) { - self.dests[1].as_mut_fixed().set(payload); - } - - /// # Safety - /// - /// The caller must ensure, that the DMA is currently not modifying this address. - pub unsafe fn set_dest_incremented_m0a( + pub fn dest_ptr( &mut self, - index: usize, - payload: Dest, - ) { - self.dests[0].as_mut_incremented().set(index, payload); - } - - /// # Safety - /// - /// The caller must ensure, that the DMA is currently not modifying this address. - pub unsafe fn set_dest_incremented_m1a( - &mut self, - index: usize, - payload: Dest, - ) { - self.dests[1].as_mut_incremented().set(index, payload); - } - - pub fn dest_ptr_fixed_m0a(&mut self) -> *mut Dest { - self.dests[0].as_mut_fixed().as_mut_ptr() - } - - pub fn dest_ptr_fixed_m1a(&mut self) -> *mut Dest { - self.dests[1].as_mut_fixed().as_mut_ptr() - } + index: Option, + double_buffer: Option, + ) -> PointerPort { + if self.peripheral.is_write() { + let ptr = mut_ptr_peripheral(&mut self.peripheral, index); - pub fn dest_ptr_incremented_m0a(&mut self, index: usize) -> *mut Dest { - self.dests[0].as_mut_incremented().as_mut_ptr(index) - } + PointerPort::Peripheral(ptr) + } else { + let ptr = mut_ptr_memory( + &mut self.memories[double_buffer.unwrap().index()], + index, + ); - pub fn dest_ptr_incremented_m1a(&mut self, index: usize) -> *mut Dest { - self.dests[1].as_mut_incremented().as_mut_ptr(index) + PointerPort::Memory(ptr) + } } } -impl<'wo, Source, Dest> SafeTransferDoubleBufferW<'wo, Source, Dest, Start> +impl<'wo, Peripheral, Memory> + SafeTransferDoubleBuffer<'wo, Peripheral, Memory, Start> where - Source: Payload, - Dest: Payload, + Peripheral: Payload, + Memory: Payload, { pub fn start( self, mut stream: Stream, - ) -> SafeTransferDoubleBufferW<'wo, Source, Dest, Ongoing> + ) -> SafeTransferDoubleBuffer<'wo, Peripheral, Memory, Ongoing> where CXX: ChannelId, DMA: DMATrait, { - check_double_buffer_stream_config(&stream); - - let [dest_buffer_0, dest_buffer_1] = self.dests; - let dest_buffer_0 = BufferW::Memory(dest_buffer_0); + stream.set_buffer_mode(BufferMode::DoubleBuffer); + stream.set_m1a(M1a(self.memories[1].as_ptr(Some(0)) as u32)); configure_safe_transfer( &mut stream, - BufferR::Peripheral(self.source), - &dest_buffer_0, + &self.peripheral, + &self.memories[0], ); - stream.set_buffer_mode(BufferMode::DoubleBuffer); - let dest_buffer_0 = dest_buffer_0.into_memory(); - - SafeTransferDoubleBufferW { - source: self.source, - dests: [dest_buffer_0, dest_buffer_1], + SafeTransferDoubleBuffer { + peripheral: self.peripheral, + memories: self.memories, state: Ongoing { stream: unsafe { stream.enable() }, }, @@ -1867,11 +1651,11 @@ where } } -impl - SafeTransferDoubleBufferW<'_, Source, Dest, Ongoing> +impl + SafeTransferDoubleBuffer<'_, Peripheral, Memory, Ongoing> where - Source: Payload, - Dest: Payload, + Peripheral: Payload, + Memory: Payload, CXX: ChannelId, DMA: DMATrait, { @@ -1913,26 +1697,22 @@ where self.state.stream.set_fifo_error_interrupt(fe_intrpt); } - pub fn set_m0a(&mut self, m0a: MemoryBufferWStatic) { - let m0a = BufferW::Memory(m0a); - let ptr = first_ptr_from_buffer(&m0a); - let m0a = m0a.into_memory(); + pub fn set_m0a(&mut self, m0a: MemoryBufferStatic) { + let ptr = m0a.as_ptr(Some(0)); - mem::replace(&mut self.dests[0], m0a); + mem::replace(&mut self.memories[0], m0a); - check_double_buffer(&self.dests); + check_double_buffer(&self.memories); block!(self.state.stream.set_m0a(M0a(ptr as u32))).unwrap(); } - pub fn set_m1a(&mut self, m1a: MemoryBufferWStatic) { - let m1a = BufferW::Memory(m1a); - let ptr = first_ptr_from_buffer(&m1a); - let m1a = m1a.into_memory(); + pub fn set_m1a(&mut self, m1a: MemoryBufferStatic) { + let ptr = m1a.as_ptr(Some(0)); - mem::replace(&mut self.dests[1], m1a); + mem::replace(&mut self.memories[1], m1a); - check_double_buffer(&self.dests); + check_double_buffer(&self.memories); block!(self.state.stream.set_m1a(M1a(ptr as u32))).unwrap(); } diff --git a/src/dma/safe_transfer.rs b/src/dma/safe_transfer.rs index bc0b9ec6..83605c24 100644 --- a/src/dma/safe_transfer.rs +++ b/src/dma/safe_transfer.rs @@ -1,8 +1,7 @@ use super::channel::ChannelId; use super::stream::{ - BufferMode, Disabled, Enabled, FlowController, IsrCleared, IsrUncleared, - M0a, MSize, Minc, Ndt, PSize, Pa, Pinc, Pincos, TransferDirection, - TransferMode, + CircularMode, Disabled, Enabled, IsrCleared, IsrUncleared, M0a, MSize, + Minc, Ndt, PSize, Pa, Pinc, Pincos, TransferDirection, TransferMode, }; use super::{DMATrait, Stream}; use core::convert::{TryFrom, TryInto}; @@ -114,15 +113,45 @@ unsafe impl Payload for i32 {} unsafe impl Payload for f32 {} -pub trait AsImmutable<'s> { - type Target: 's; +#[derive(Clone, Copy)] +pub enum PayloadPort +where + Peripheral: Payload, + Memory: Payload, +{ + Peripheral(Peripheral), + Memory(Memory), +} - /// # Safety - /// - /// All unsafe methods of `Self` remain unsafe. - /// - /// If `Self` was already immutable, this is safe. - unsafe fn as_immutable(&'s self) -> Self::Target; +impl PayloadPort +where + Peripheral: Payload, + Memory: Payload, +{ + pub fn peripheral(self) -> Peripheral { + if let PayloadPort::Peripheral(p) = self { + p + } else { + panic!("Tried to unwrap memory port as peripheral port."); + } + } + + pub fn memory(self) -> Memory { + if let PayloadPort::Memory(m) = self { + m + } else { + panic!("Tried to unwrap peripheral port as memory port."); + } + } +} + +pub enum PointerPort +where + Peripheral: Payload, + Memory: Payload, +{ + Peripheral(*mut Peripheral), + Memory(*mut Memory), } pub enum Buffer<'buf, 'wo, P> @@ -137,6 +166,22 @@ impl<'buf, 'wo, P> Buffer<'buf, 'wo, P> where P: Payload, { + pub fn is_peripheral(&self) -> bool { + if let Buffer::Peripheral(_) = self { + true + } else { + false + } + } + + pub fn is_memory(&self) -> bool { + if let Buffer::Memory(_) = self { + true + } else { + false + } + } + pub fn into_peripheral(self) -> PeripheralBuffer<'buf, 'wo, P> { if let Buffer::Peripheral(buffer) = self { buffer @@ -184,155 +229,51 @@ where panic!("The buffer is a peripheral puffer."); } } -} - -#[derive(Clone, Copy)] -pub enum BufferR<'buf, 'wo, P> -where - P: Payload, -{ - Memory(MemoryBufferR<'buf, P>), - Peripheral(PeripheralBufferR<'buf, 'wo, P>), -} - -impl<'buf, 'wo, P> BufferR<'buf, 'wo, P> -where - P: Payload, -{ - pub fn memory(self) -> MemoryBufferR<'buf, P> { - if let BufferR::Memory(buffer) = self { - buffer - } else { - panic!("The buffer is a peripheral buffer."); - } - } - - pub fn peripheral(self) -> PeripheralBufferR<'buf, 'wo, P> { - if let BufferR::Peripheral(buffer) = self { - buffer - } else { - panic!("The buffer is a memory buffer."); - } - } -} - -impl<'s, P> AsImmutable<'s> for BufferR<'_, '_, P> -where - P: Payload, -{ - type Target = BufferR<'s, 's, P>; - - unsafe fn as_immutable(&self) -> BufferR

{ - *self - } -} - -impl<'buf, 'wo, P> From> for Buffer<'buf, 'wo, P> -where - P: Payload, -{ - fn from(buffer: BufferR<'buf, 'wo, P>) -> Self { - match buffer { - BufferR::Peripheral(buffer) => Buffer::Peripheral(buffer.into()), - BufferR::Memory(buffer) => Buffer::Memory(buffer.into()), - } - } -} - -pub type BufferRStatic<'wo, P> = BufferR<'static, 'wo, P>; - -pub enum BufferW<'buf, 'wo, P> -where - P: Payload, -{ - Memory(MemoryBufferW<'buf, P>), - Peripheral(PeripheralBufferW<'buf, 'wo, P>), -} - -impl<'buf, 'wo, P> BufferW<'buf, 'wo, P> -where - P: Payload, -{ - pub fn into_memory(self) -> MemoryBufferW<'buf, P> { - if let BufferW::Memory(buffer) = self { - buffer - } else { - panic!("The buffer is a peripheral buffer."); - } - } - pub fn as_memory(&self) -> &MemoryBufferW<'buf, P> { - if let BufferW::Memory(buffer) = self { - buffer - } else { - panic!("The buffer is a peripheral buffer."); - } - } - - pub fn as_mut_memory(&mut self) -> &mut MemoryBufferW<'buf, P> { - if let BufferW::Memory(buffer) = self { - buffer - } else { - panic!("The buffer is a peripheral buffer."); + pub unsafe fn get(&self, index: Option) -> P { + match self { + Buffer::Peripheral(buffer) => buffer.get(index), + Buffer::Memory(buffer) => buffer.get(index), } } - pub fn into_peripheral(self) -> PeripheralBufferW<'buf, 'wo, P> { - if let BufferW::Peripheral(buffer) = self { - buffer - } else { - panic!("The buffer is a memory buffer."); + pub fn as_ptr(&self, index: Option) -> *const P { + match self { + Buffer::Peripheral(buffer) => buffer.as_ptr(index), + Buffer::Memory(buffer) => buffer.as_ptr(index), } } - pub fn as_peripheral(&self) -> &PeripheralBufferW<'buf, 'wo, P> { - if let BufferW::Peripheral(buffer) = self { - buffer - } else { - panic!("The buffer is a memory buffer."); + pub fn is_read(&self) -> bool { + match self { + Buffer::Peripheral(buffer) => buffer.is_read(), + Buffer::Memory(buffer) => buffer.is_read(), } } - pub fn as_mut_peripheral( - &mut self, - ) -> &mut PeripheralBufferW<'buf, 'wo, P> { - if let BufferW::Peripheral(buffer) = self { - buffer - } else { - panic!("The buffer is a memory buffer."); + pub fn is_write(&self) -> bool { + match self { + Buffer::Peripheral(buffer) => buffer.is_write(), + Buffer::Memory(buffer) => buffer.is_write(), } } -} -impl<'s, P> AsImmutable<'s> for BufferW<'_, '_, P> -where - P: Payload, -{ - type Target = BufferR<'s, 's, P>; - - unsafe fn as_immutable(&'s self) -> BufferR

{ + pub fn is_fixed(&self) -> bool { match self { - BufferW::Memory(buffer) => BufferR::Memory(buffer.as_immutable()), - BufferW::Peripheral(buffer) => { - BufferR::Peripheral(buffer.as_immutable()) - } + Buffer::Peripheral(buffer) => buffer.is_fixed(), + Buffer::Memory(buffer) => buffer.is_fixed(), } } -} -impl<'buf, 'wo, P> From> for Buffer<'buf, 'wo, P> -where - P: Payload, -{ - fn from(buffer: BufferW<'buf, 'wo, P>) -> Self { - match buffer { - BufferW::Peripheral(buffer) => Buffer::Peripheral(buffer.into()), - BufferW::Memory(buffer) => Buffer::Memory(buffer.into()), + pub fn is_incremented(&self) -> bool { + match self { + Buffer::Peripheral(buffer) => buffer.is_incremented(), + Buffer::Memory(buffer) => buffer.is_incremented(), } } } -pub type BufferWStatic<'wo, P> = BufferW<'static, 'wo, P>; +pub type BufferStatic<'wo, P> = Buffer<'static, 'wo, P>; pub enum MemoryBuffer<'buf, P> where @@ -346,6 +287,22 @@ impl<'buf, P> MemoryBuffer<'buf, P> where P: Payload, { + pub fn is_fixed(&self) -> bool { + if let MemoryBuffer::Fixed(_) = self { + true + } else { + false + } + } + + pub fn is_incremented(&self) -> bool { + if let MemoryBuffer::Incremented(_) = self { + true + } else { + false + } + } + pub fn into_fixed(self) -> FixedBuffer<'buf, P> { if let MemoryBuffer::Fixed(buffer) = self { buffer @@ -393,172 +350,66 @@ where panic!("The buffer is fixed."); } } -} - -#[derive(Clone, Copy)] -pub enum MemoryBufferR<'buf, P> -where - P: Payload, -{ - Fixed(FixedBufferR<'buf, P>), - Incremented(RegularOffsetBufferR<'buf, P>), -} -impl<'buf, P> MemoryBufferR<'buf, P> -where - P: Payload, -{ - pub fn fixed(self) -> FixedBufferR<'buf, P> { - if let MemoryBufferR::Fixed(buffer) = self { - buffer - } else { - panic!("The buffer is incremented."); + pub unsafe fn get(&self, index: Option) -> P { + match self { + MemoryBuffer::Fixed(buffer) => buffer.get(), + MemoryBuffer::Incremented(buffer) => buffer.get(index.unwrap()), } } - pub fn incremented(self) -> RegularOffsetBufferR<'buf, P> { - if let MemoryBufferR::Incremented(buffer) = self { - buffer - } else { - panic!("The buffer is fixed."); + pub fn as_ptr(&self, index: Option) -> *const P { + match self { + MemoryBuffer::Fixed(buffer) => buffer.as_ptr(), + MemoryBuffer::Incremented(buffer) => buffer.as_ptr(index.unwrap()), } } -} - -impl<'s, P> AsImmutable<'s> for MemoryBufferR<'_, P> -where - P: Payload, -{ - type Target = MemoryBufferR<'s, P>; - unsafe fn as_immutable(&self) -> MemoryBufferR

{ - *self + pub fn is_read(&self) -> bool { + match self { + MemoryBuffer::Fixed(buffer) => buffer.is_read(), + MemoryBuffer::Incremented(buffer) => buffer.is_read(), + } } -} -impl<'buf, P> From> for MemoryBuffer<'buf, P> -where - P: Payload, -{ - fn from(buffer: MemoryBufferR<'buf, P>) -> Self { - match buffer { - MemoryBufferR::Fixed(buffer) => MemoryBuffer::Fixed(buffer.into()), - MemoryBufferR::Incremented(buffer) => { - MemoryBuffer::Incremented(buffer.into()) - } + pub fn is_write(&self) -> bool { + match self { + MemoryBuffer::Fixed(buffer) => buffer.is_write(), + MemoryBuffer::Incremented(buffer) => buffer.is_write(), } } } -pub type MemoryBufferRStatic

= MemoryBufferR<'static, P>; +pub type MemoryBufferStatic

= MemoryBuffer<'static, P>; -pub enum MemoryBufferW<'buf, P> +pub enum PeripheralBuffer<'buf, 'wo, P> where P: Payload, { - Fixed(FixedBufferW<'buf, P>), - Incremented(RegularOffsetBufferW<'buf, P>), + Fixed(FixedBuffer<'buf, P>), + Incremented(IncrementedBuffer<'buf, 'wo, P>), } -impl<'buf, P> MemoryBufferW<'buf, P> +impl<'buf, 'wo, P> PeripheralBuffer<'buf, 'wo, P> where P: Payload, { - pub fn into_fixed(self) -> FixedBufferW<'buf, P> { - if let MemoryBufferW::Fixed(buffer) = self { - buffer + pub fn is_fixed(&self) -> bool { + if let PeripheralBuffer::Fixed(_) = self { + true } else { - panic!("The buffer is incremented."); + false } } - pub fn as_fixed(&self) -> &FixedBufferW<'buf, P> { - if let MemoryBufferW::Fixed(buffer) = self { - buffer + pub fn is_incremented(&self) -> bool { + if let PeripheralBuffer::Incremented(_) = self { + true } else { - panic!("The buffer is incremented."); + false } } - pub fn as_mut_fixed(&mut self) -> &mut FixedBufferW<'buf, P> { - if let MemoryBufferW::Fixed(buffer) = self { - buffer - } else { - panic!("The buffer is incremented."); - } - } - - pub fn into_incremented(self) -> RegularOffsetBufferW<'buf, P> { - if let MemoryBufferW::Incremented(buffer) = self { - buffer - } else { - panic!("The buffer is fixed."); - } - } - - pub fn as_incremented(&self) -> &RegularOffsetBufferW<'buf, P> { - if let MemoryBufferW::Incremented(buffer) = self { - buffer - } else { - panic!("The buffer is fixed."); - } - } - - pub fn as_mut_incremented(&mut self) -> &mut RegularOffsetBufferW<'buf, P> { - if let MemoryBufferW::Incremented(buffer) = self { - buffer - } else { - panic!("The buffer is fixed."); - } - } -} - -impl<'s, P> AsImmutable<'s> for MemoryBufferW<'_, P> -where - P: Payload, -{ - type Target = MemoryBufferR<'s, P>; - - unsafe fn as_immutable(&self) -> MemoryBufferR

{ - match self { - MemoryBufferW::Fixed(buffer) => { - MemoryBufferR::Fixed(buffer.as_immutable()) - } - MemoryBufferW::Incremented(buffer) => { - MemoryBufferR::Incremented(buffer.as_immutable()) - } - } - } -} - -impl<'buf, P> From> for MemoryBuffer<'buf, P> -where - P: Payload, -{ - fn from(buffer: MemoryBufferW<'buf, P>) -> Self { - match buffer { - MemoryBufferW::Fixed(buffer) => MemoryBuffer::Fixed(buffer.into()), - MemoryBufferW::Incremented(buffer) => { - MemoryBuffer::Incremented(buffer.into()) - } - } - } -} - -pub type MemoryBufferWStatic

= MemoryBufferW<'static, P>; - -pub enum PeripheralBuffer<'buf, 'wo, P> -where - P: Payload, -{ - Fixed(FixedBuffer<'buf, P>), - Incremented(IncrementedBuffer<'buf, 'wo, P>), -} - -impl<'buf, 'wo, P> PeripheralBuffer<'buf, 'wo, P> -where - P: Payload, -{ pub fn into_fixed(self) -> FixedBuffer<'buf, P> { if let PeripheralBuffer::Fixed(buffer) = self { buffer @@ -608,167 +459,39 @@ where panic!("The buffer is fixed."); } } -} - -#[derive(Clone, Copy)] -pub enum PeripheralBufferR<'buf, 'wo, P> -where - P: Payload, -{ - Fixed(FixedBufferR<'buf, P>), - Incremented(IncrementedBufferR<'buf, 'wo, P>), -} - -impl<'buf, 'wo, P> PeripheralBufferR<'buf, 'wo, P> -where - P: Payload, -{ - pub fn fixed(self) -> FixedBufferR<'buf, P> { - if let PeripheralBufferR::Fixed(buffer) = self { - buffer - } else { - panic!("The buffer is incremented."); - } - } - pub fn incremented(self) -> IncrementedBufferR<'buf, 'wo, P> { - if let PeripheralBufferR::Incremented(buffer) = self { - buffer - } else { - panic!("The buffer is fixed."); + pub unsafe fn get(&self, index: Option) -> P { + match self { + PeripheralBuffer::Fixed(buffer) => buffer.get(), + PeripheralBuffer::Incremented(buffer) => buffer.get(index.unwrap()), } } -} - -impl<'s, P> AsImmutable<'s> for PeripheralBufferR<'_, '_, P> -where - P: Payload, -{ - type Target = PeripheralBufferR<'s, 's, P>; - - unsafe fn as_immutable(&self) -> PeripheralBufferR

{ - *self - } -} -impl<'buf, 'wo, P> From> - for PeripheralBuffer<'buf, 'wo, P> -where - P: Payload, -{ - fn from(buffer: PeripheralBufferR<'buf, 'wo, P>) -> Self { - match buffer { - PeripheralBufferR::Fixed(buffer) => { - PeripheralBuffer::Fixed(buffer.into()) - } - PeripheralBufferR::Incremented(buffer) => { - PeripheralBuffer::Incremented(buffer.into()) + pub fn as_ptr(&self, index: Option) -> *const P { + match self { + PeripheralBuffer::Fixed(buffer) => buffer.as_ptr(), + PeripheralBuffer::Incremented(buffer) => { + buffer.as_ptr(index.unwrap()) } } } -} - -pub type PeripheralBufferRStatic<'wo, P> = PeripheralBufferR<'static, 'wo, P>; - -pub enum PeripheralBufferW<'buf, 'wo, P> -where - P: Payload, -{ - Fixed(FixedBufferW<'buf, P>), - Incremented(IncrementedBufferW<'buf, 'wo, P>), -} - -impl<'buf, 'wo, P> PeripheralBufferW<'buf, 'wo, P> -where - P: Payload, -{ - pub fn into_fixed(self) -> FixedBufferW<'buf, P> { - if let PeripheralBufferW::Fixed(buffer) = self { - buffer - } else { - panic!("The buffer is incremented."); - } - } - - pub fn as_fixed(&self) -> &FixedBufferW<'buf, P> { - if let PeripheralBufferW::Fixed(buffer) = self { - buffer - } else { - panic!("The buffer is incremented."); - } - } - - pub fn as_mut_fixed(&mut self) -> &mut FixedBufferW<'buf, P> { - if let PeripheralBufferW::Fixed(buffer) = self { - buffer - } else { - panic!("The buffer is incremented."); - } - } - - pub fn into_incremented(self) -> IncrementedBufferW<'buf, 'wo, P> { - if let PeripheralBufferW::Incremented(buffer) = self { - buffer - } else { - panic!("The buffer is fixed."); - } - } - - pub fn as_incremented(&self) -> &IncrementedBufferW<'buf, 'wo, P> { - if let PeripheralBufferW::Incremented(buffer) = self { - buffer - } else { - panic!("The buffer is fixed."); - } - } - pub fn as_mut_incremented( - &mut self, - ) -> &mut IncrementedBufferW<'buf, 'wo, P> { - if let PeripheralBufferW::Incremented(buffer) = self { - buffer - } else { - panic!("The buffer is fixed."); - } - } -} - -impl<'s, P> AsImmutable<'s> for PeripheralBufferW<'_, '_, P> -where - P: Payload, -{ - type Target = PeripheralBufferR<'s, 's, P>; - - unsafe fn as_immutable(&self) -> PeripheralBufferR

{ + pub fn is_read(&self) -> bool { match self { - PeripheralBufferW::Fixed(buffer) => { - PeripheralBufferR::Fixed(buffer.as_immutable()) - } - PeripheralBufferW::Incremented(buffer) => { - PeripheralBufferR::Incremented(buffer.as_immutable()) - } + PeripheralBuffer::Fixed(buffer) => buffer.is_read(), + PeripheralBuffer::Incremented(buffer) => buffer.is_read(), } } -} -impl<'buf, 'wo, P> From> - for PeripheralBuffer<'buf, 'wo, P> -where - P: Payload, -{ - fn from(buffer: PeripheralBufferW<'buf, 'wo, P>) -> Self { - match buffer { - PeripheralBufferW::Fixed(buffer) => { - PeripheralBuffer::Fixed(buffer.into()) - } - PeripheralBufferW::Incremented(buffer) => { - PeripheralBuffer::Incremented(buffer.into()) - } + pub fn is_write(&self) -> bool { + match self { + PeripheralBuffer::Fixed(buffer) => buffer.is_write(), + PeripheralBuffer::Incremented(buffer) => buffer.is_write(), } } } -pub type PeripheralBufferWStatic<'wo, P> = PeripheralBufferW<'static, 'wo, P>; +pub type PeripheralBufferStatic<'wo, P> = PeripheralBuffer<'static, 'wo, P>; pub enum IncrementedBuffer<'buf, 'wo, P> where @@ -782,185 +505,32 @@ impl<'buf, 'wo, P> IncrementedBuffer<'buf, 'wo, P> where P: Payload, { - pub fn into_regular_offset(self) -> RegularOffsetBuffer<'buf, P> { - if let IncrementedBuffer::RegularOffset(buffer) = self { - buffer - } else { - panic!("The buffer has word offset."); - } - } - - pub fn as_regular_offset(&self) -> &RegularOffsetBuffer<'buf, P> { - if let IncrementedBuffer::RegularOffset(buffer) = self { - buffer + pub fn is_regular_offset(&self) -> bool { + if let IncrementedBuffer::RegularOffset(_) = self { + true } else { - panic!("The buffer has word offset."); + false } } - pub fn as_mut_regular_offset( - &mut self, - ) -> &mut RegularOffsetBuffer<'buf, P> { - if let IncrementedBuffer::RegularOffset(buffer) = self { - buffer + pub fn is_word_offset(&self) -> bool { + if let IncrementedBuffer::WordOffset(_) = self { + true } else { - panic!("The buffer has word offset."); + false } - } - - pub fn into_word_offset(self) -> WordOffsetBuffer<'buf, 'wo, P> { - if let IncrementedBuffer::WordOffset(buffer) = self { - buffer - } else { - panic!("The buffer has regular offset."); - } - } - - pub fn as_word_offset(&self) -> &WordOffsetBuffer<'buf, 'wo, P> { - if let IncrementedBuffer::WordOffset(buffer) = self { - buffer - } else { - panic!("The buffer has regular offset."); - } - } - - pub fn as_mut_word_offset( - &mut self, - ) -> &mut WordOffsetBuffer<'buf, 'wo, P> { - if let IncrementedBuffer::WordOffset(buffer) = self { - buffer - } else { - panic!("The buffer has regular offset."); - } - } - - pub fn len(self) -> usize { - match self { - IncrementedBuffer::RegularOffset(buffer) => buffer.len(), - IncrementedBuffer::WordOffset(buffer) => buffer.len(), - } - } - - pub unsafe fn get(self, index: usize) -> P { - match self { - IncrementedBuffer::RegularOffset(buffer) => buffer.get(index), - IncrementedBuffer::WordOffset(buffer) => buffer.get(index), - } - } - - pub fn as_ptr(&self, index: usize) -> *const P { - match self { - IncrementedBuffer::RegularOffset(buffer) => buffer.as_ptr(index), - IncrementedBuffer::WordOffset(buffer) => buffer.as_ptr(index), - } - } -} - -#[derive(Clone, Copy)] -pub enum IncrementedBufferR<'buf, 'wo, P> -where - P: Payload, -{ - RegularOffset(RegularOffsetBufferR<'buf, P>), - WordOffset(WordOffsetBufferR<'buf, 'wo, P>), -} - -#[allow(clippy::len_without_is_empty)] -impl<'buf, 'wo, P> IncrementedBufferR<'buf, 'wo, P> -where - P: Payload, -{ - pub fn regular_offset(self) -> RegularOffsetBufferR<'buf, P> { - if let IncrementedBufferR::RegularOffset(buffer) = self { - buffer - } else { - panic!("The buffer has word offset."); - } - } - - pub fn word_offset(self) -> WordOffsetBufferR<'buf, 'wo, P> { - if let IncrementedBufferR::WordOffset(buffer) = self { - buffer - } else { - panic!("The buffer has regular offset."); - } - } - - pub fn len(self) -> usize { - match self { - IncrementedBufferR::RegularOffset(buffer) => buffer.len(), - IncrementedBufferR::WordOffset(buffer) => buffer.len(), - } - } - - pub fn get(self, index: usize) -> P { - match self { - IncrementedBufferR::RegularOffset(buffer) => buffer.get(index), - IncrementedBufferR::WordOffset(buffer) => buffer.get(index), - } - } - - pub fn as_ptr(&self, index: usize) -> *const P { - match self { - IncrementedBufferR::RegularOffset(buffer) => buffer.as_ptr(index), - IncrementedBufferR::WordOffset(buffer) => buffer.as_ptr(index), - } - } -} - -impl<'s, P> AsImmutable<'s> for IncrementedBufferR<'_, '_, P> -where - P: Payload, -{ - type Target = IncrementedBufferR<'s, 's, P>; - - unsafe fn as_immutable(&self) -> IncrementedBufferR

{ - *self - } -} - -impl<'buf, 'wo, P> From> - for IncrementedBuffer<'buf, 'wo, P> -where - P: Payload, -{ - fn from(buffer: IncrementedBufferR<'buf, 'wo, P>) -> Self { - match buffer { - IncrementedBufferR::RegularOffset(buffer) => { - IncrementedBuffer::RegularOffset(buffer.into()) - } - IncrementedBufferR::WordOffset(buffer) => { - IncrementedBuffer::WordOffset(buffer.into()) - } - } - } -} - -pub type IncrementedBufferRStatic<'wo, P> = IncrementedBufferR<'static, 'wo, P>; - -pub enum IncrementedBufferW<'buf, 'wo, P> -where - P: Payload, -{ - RegularOffset(RegularOffsetBufferW<'buf, P>), - WordOffset(WordOffsetBufferW<'buf, 'wo, P>), -} - -#[allow(clippy::len_without_is_empty)] -impl<'buf, 'wo, P> IncrementedBufferW<'buf, 'wo, P> -where - P: Payload, -{ - pub fn into_regular_offset(self) -> RegularOffsetBufferW<'buf, P> { - if let IncrementedBufferW::RegularOffset(buffer) = self { + } + + pub fn into_regular_offset(self) -> RegularOffsetBuffer<'buf, P> { + if let IncrementedBuffer::RegularOffset(buffer) = self { buffer } else { panic!("The buffer has word offset."); } } - pub fn as_regular_offset(&self) -> &RegularOffsetBufferW<'buf, P> { - if let IncrementedBufferW::RegularOffset(buffer) = self { + pub fn as_regular_offset(&self) -> &RegularOffsetBuffer<'buf, P> { + if let IncrementedBuffer::RegularOffset(buffer) = self { buffer } else { panic!("The buffer has word offset."); @@ -969,24 +539,24 @@ where pub fn as_mut_regular_offset( &mut self, - ) -> &mut RegularOffsetBufferW<'buf, P> { - if let IncrementedBufferW::RegularOffset(buffer) = self { + ) -> &mut RegularOffsetBuffer<'buf, P> { + if let IncrementedBuffer::RegularOffset(buffer) = self { buffer } else { panic!("The buffer has word offset."); } } - pub fn into_word_offset(self) -> WordOffsetBufferW<'buf, 'wo, P> { - if let IncrementedBufferW::WordOffset(buffer) = self { + pub fn into_word_offset(self) -> WordOffsetBuffer<'buf, 'wo, P> { + if let IncrementedBuffer::WordOffset(buffer) = self { buffer } else { panic!("The buffer has regular offset."); } } - pub fn as_word_offset(&self) -> &WordOffsetBufferW<'buf, 'wo, P> { - if let IncrementedBufferW::WordOffset(buffer) = self { + pub fn as_word_offset(&self) -> &WordOffsetBuffer<'buf, 'wo, P> { + if let IncrementedBuffer::WordOffset(buffer) = self { buffer } else { panic!("The buffer has regular offset."); @@ -995,8 +565,8 @@ where pub fn as_mut_word_offset( &mut self, - ) -> &mut WordOffsetBufferW<'buf, 'wo, P> { - if let IncrementedBufferW::WordOffset(buffer) = self { + ) -> &mut WordOffsetBuffer<'buf, 'wo, P> { + if let IncrementedBuffer::WordOffset(buffer) = self { buffer } else { panic!("The buffer has regular offset."); @@ -1005,101 +575,117 @@ where pub fn len(&self) -> usize { match self { - IncrementedBufferW::RegularOffset(buffer) => buffer.len(), - IncrementedBufferW::WordOffset(buffer) => buffer.len(), + IncrementedBuffer::RegularOffset(buffer) => buffer.len(), + IncrementedBuffer::WordOffset(buffer) => buffer.len(), } } - /// # Safety - /// - /// The caller must ensure, that the DMA is currently not modifying this address. pub unsafe fn get(&self, index: usize) -> P { match self { - IncrementedBufferW::RegularOffset(buffer) => buffer.get(index), - IncrementedBufferW::WordOffset(buffer) => buffer.get(index), + IncrementedBuffer::RegularOffset(buffer) => buffer.get(index), + IncrementedBuffer::WordOffset(buffer) => buffer.get(index), } } - /// # Safety - /// - /// The caller must ensure, that the DMA is currently not modifying this address. - pub unsafe fn set(&mut self, index: usize, payload: P) { + pub fn as_ptr(&self, index: usize) -> *const P { match self { - IncrementedBufferW::RegularOffset(buffer) => { - buffer.set(index, payload) - } - IncrementedBufferW::WordOffset(buffer) => { - buffer.set(index, payload) - } + IncrementedBuffer::RegularOffset(buffer) => buffer.as_ptr(index), + IncrementedBuffer::WordOffset(buffer) => buffer.as_ptr(index), } } - pub fn as_ptr(&self, index: usize) -> *const P { + pub fn is_read(&self) -> bool { match self { - IncrementedBufferW::RegularOffset(buffer) => buffer.as_ptr(index), - IncrementedBufferW::WordOffset(buffer) => buffer.as_ptr(index), + IncrementedBuffer::RegularOffset(buffer) => buffer.is_read(), + IncrementedBuffer::WordOffset(buffer) => buffer.is_read(), } } - pub fn as_mut_ptr(&mut self, index: usize) -> *mut P { + pub fn is_write(&self) -> bool { match self { - IncrementedBufferW::RegularOffset(buffer) => { - buffer.as_mut_ptr(index) - } - IncrementedBufferW::WordOffset(buffer) => buffer.as_mut_ptr(index), + IncrementedBuffer::RegularOffset(buffer) => buffer.is_write(), + IncrementedBuffer::WordOffset(buffer) => buffer.is_write(), } } } -impl<'s, P> AsImmutable<'s> for IncrementedBufferW<'_, '_, P> +pub type IncrementedBufferStatic<'wo, P> = IncrementedBuffer<'static, 'wo, P>; + +pub enum FixedBuffer<'buf, P> where P: Payload, { - type Target = IncrementedBufferR<'s, 's, P>; - - /// # Safety - /// - /// `IncrementedBuffer` assumes that the DMA is only reading the buffer. - /// Therefore the getters of the immutable version are as unsafe as the getters of this struct. - unsafe fn as_immutable(&self) -> IncrementedBufferR

{ - match self { - IncrementedBufferW::RegularOffset(buffer) => { - IncrementedBufferR::RegularOffset(buffer.as_immutable()) - } - IncrementedBufferW::WordOffset(buffer) => { - IncrementedBufferR::WordOffset(buffer.as_immutable()) - } - } - } + Read(FixedBufferR<'buf, P>), + Write(FixedBufferW<'buf, P>), } -impl<'buf, 'wo, P> From> - for IncrementedBuffer<'buf, 'wo, P> +impl<'buf, P> FixedBuffer<'buf, P> where P: Payload, { - fn from(buffer: IncrementedBufferW<'buf, 'wo, P>) -> Self { - match buffer { - IncrementedBufferW::RegularOffset(buffer) => { - IncrementedBuffer::RegularOffset(buffer.into()) - } - IncrementedBufferW::WordOffset(buffer) => { - IncrementedBuffer::WordOffset(buffer.into()) - } + pub fn is_read(&self) -> bool { + match self { + FixedBuffer::Read(_) => true, + FixedBuffer::Write(_) => false, } } -} -pub type IncrementedBufferWStatic<'wo, P> = IncrementedBufferW<'static, 'wo, P>; + pub fn is_write(&self) -> bool { + match self { + FixedBuffer::Write(_) => true, + FixedBuffer::Read(_) => false, + } + } -pub enum FixedBuffer<'buf, P> -where - P: Payload, -{ - Read(FixedBufferR<'buf, P>), - Write(FixedBufferW<'buf, P>), + pub fn as_read(&self) -> FixedBufferR<'buf, P> { + if let &FixedBuffer::Read(buffer) = self { + buffer + } else { + panic!("The buffer is a write buffer."); + } + } + + pub fn into_write(self) -> FixedBufferW<'buf, P> { + if let FixedBuffer::Write(buffer) = self { + buffer + } else { + panic!("The buffer is a read buffer."); + } + } + + pub fn as_write(&self) -> &FixedBufferW<'buf, P> { + if let FixedBuffer::Write(buffer) = self { + buffer + } else { + panic!("The buffer is a read buffer."); + } + } + + pub fn as_mut_write(&mut self) -> &mut FixedBufferW<'buf, P> { + if let FixedBuffer::Write(buffer) = self { + buffer + } else { + panic!("The buffer is a read buffer."); + } + } + + pub unsafe fn get(&self) -> P { + match self { + FixedBuffer::Read(buffer) => buffer.get(), + FixedBuffer::Write(buffer) => buffer.get(), + } + } + + pub fn as_ptr(&self) -> *const P { + match self { + FixedBuffer::Read(buffer) => buffer.as_ptr(), + FixedBuffer::Write(buffer) => buffer.as_ptr(), + } + } } +pub type FixedBufferStatic

= FixedBuffer<'static, P>; + #[derive(Clone, Copy)] pub struct FixedBufferR<'buf, P>(*const P, PhantomData<&'buf P>) where @@ -1122,26 +708,6 @@ where } } -impl<'s, P> AsImmutable<'s> for FixedBufferR<'_, P> -where - P: Payload, -{ - type Target = FixedBufferR<'s, P>; - - unsafe fn as_immutable(&self) -> FixedBufferR

{ - *self - } -} - -impl<'buf, P> From> for FixedBuffer<'buf, P> -where - P: Payload, -{ - fn from(buffer: FixedBufferR<'buf, P>) -> Self { - FixedBuffer::Read(buffer) - } -} - unsafe impl

Send for FixedBufferR<'_, P> where P: Payload {} unsafe impl

Sync for FixedBufferR<'_, P> where P: Payload {} @@ -1183,26 +749,6 @@ where } } -impl<'s, P> AsImmutable<'s> for FixedBufferW<'_, P> -where - P: Payload, -{ - type Target = FixedBufferR<'s, P>; - - unsafe fn as_immutable(&self) -> FixedBufferR

{ - FixedBufferR(self.0, PhantomData) - } -} - -impl<'buf, P> From> for FixedBuffer<'buf, P> -where - P: Payload, -{ - fn from(buffer: FixedBufferW<'buf, P>) -> Self { - FixedBuffer::Write(buffer) - } -} - unsafe impl

Send for FixedBufferW<'_, P> where P: Payload {} unsafe impl

Sync for FixedBufferW<'_, P> where P: Payload {} @@ -1221,6 +767,20 @@ impl<'buf, P> RegularOffsetBuffer<'buf, P> where P: Payload, { + pub fn is_read(&self) -> bool { + match self { + RegularOffsetBuffer::Read(_) => true, + RegularOffsetBuffer::Write(_) => false, + } + } + + pub fn is_write(&self) -> bool { + match self { + RegularOffsetBuffer::Write(_) => true, + RegularOffsetBuffer::Read(_) => false, + } + } + pub fn as_read(&self) -> RegularOffsetBufferR<'buf, P> { if let &RegularOffsetBuffer::Read(buffer) = self { buffer @@ -1277,6 +837,8 @@ where } } +pub type RegularOffsetBufferStatic

= RegularOffsetBuffer<'static, P>; + #[derive(Clone, Copy)] pub struct RegularOffsetBufferR<'buf, P>(*const [P], PhantomData<&'buf P>) where @@ -1312,27 +874,6 @@ where } } -impl<'s, P> AsImmutable<'s> for RegularOffsetBufferR<'_, P> -where - P: Payload, -{ - type Target = RegularOffsetBufferR<'s, P>; - - unsafe fn as_immutable(&self) -> RegularOffsetBufferR

{ - *self - } -} - -impl<'buf, P> From> - for RegularOffsetBuffer<'buf, P> -where - P: Payload, -{ - fn from(buffer: RegularOffsetBufferR<'buf, P>) -> Self { - RegularOffsetBuffer::Read(buffer) - } -} - unsafe impl

Send for RegularOffsetBufferR<'_, P> where P: Payload {} unsafe impl

Sync for RegularOffsetBufferR<'_, P> where P: Payload {} @@ -1391,27 +932,6 @@ where } } -impl<'s, P> AsImmutable<'s> for RegularOffsetBufferW<'_, P> -where - P: Payload, -{ - type Target = RegularOffsetBufferR<'s, P>; - - unsafe fn as_immutable(&self) -> RegularOffsetBufferR

{ - RegularOffsetBufferR(self.0, PhantomData) - } -} - -impl<'buf, P> From> - for RegularOffsetBuffer<'buf, P> -where - P: Payload, -{ - fn from(buffer: RegularOffsetBufferW<'buf, P>) -> Self { - RegularOffsetBuffer::Write(buffer) - } -} - unsafe impl

Send for RegularOffsetBufferW<'_, P> where P: Payload {} unsafe impl

Sync for RegularOffsetBufferW<'_, P> where P: Payload {} @@ -1441,6 +961,20 @@ impl<'buf, 'wo, P> WordOffsetBuffer<'buf, 'wo, P> where P: Payload, { + pub fn is_read(&self) -> bool { + match self { + WordOffsetBuffer::Read(_) => true, + WordOffsetBuffer::Write(_) => false, + } + } + + pub fn is_write(&self) -> bool { + match self { + WordOffsetBuffer::Write(_) => true, + WordOffsetBuffer::Read(_) => false, + } + } + pub fn as_read(&self) -> WordOffsetBufferR<'buf, 'wo, P> { if let &WordOffsetBuffer::Read(buffer) = self { buffer @@ -1473,8 +1007,6 @@ where } } - // Methods both variants implement - pub unsafe fn get(&self, index: usize) -> P { match self { WordOffsetBuffer::Read(buffer) => buffer.get(index), @@ -1497,6 +1029,8 @@ where } } +pub type WordOffsetBufferStatic<'wo, P> = WordOffsetBuffer<'static, 'wo, P>; + #[derive(Clone, Copy)] pub struct WordOffsetBufferR<'buf, 'wo, P>( &'wo [*const P], @@ -1533,27 +1067,6 @@ where } } -impl<'s, P> AsImmutable<'s> for WordOffsetBufferR<'_, '_, P> -where - P: Payload, -{ - type Target = WordOffsetBufferR<'s, 's, P>; - - unsafe fn as_immutable(&self) -> WordOffsetBufferR

{ - *self - } -} - -impl<'buf, 'wo, P> From> - for WordOffsetBuffer<'buf, 'wo, P> -where - P: Payload, -{ - fn from(buffer: WordOffsetBufferR<'buf, 'wo, P>) -> Self { - WordOffsetBuffer::Read(buffer) - } -} - unsafe impl<'buf, 'wo, P> Send for WordOffsetBufferR<'buf, 'wo, P> where P: Payload { @@ -1615,27 +1128,6 @@ where } } -impl<'s, P> AsImmutable<'s> for WordOffsetBufferW<'_, '_, P> -where - P: Payload, -{ - type Target = WordOffsetBufferR<'s, 's, P>; - - unsafe fn as_immutable(&self) -> WordOffsetBufferR

{ - WordOffsetBufferR(&*(self.0 as *const _ as *const _), PhantomData) - } -} - -impl<'buf, 'wo, P> From> - for WordOffsetBuffer<'buf, 'wo, P> -where - P: Payload, -{ - fn from(buffer: WordOffsetBufferW<'buf, 'wo, P>) -> Self { - WordOffsetBuffer::Write(buffer) - } -} - unsafe impl

Send for WordOffsetBufferW<'_, '_, P> where P: Payload {} unsafe impl

Sync for WordOffsetBufferW<'_, '_, P> where P: Payload {} @@ -1674,44 +1166,10 @@ where } } -/// Configures the buffers of the transfer. -/// -/// **Note**: Configures the following values: -/// -/// - `PSize`, `Msize` -/// - `Pa`, `M0a` -/// - `Pinc`, `Minc` -/// - `Pincos` -/// - `Ndt` -pub(super) fn configure_safe_transfer( - stream: &mut Stream, - source: BufferR, - dest: &BufferW, -) where - CXX: ChannelId, - DMA: DMATrait, - Source: Payload, - Dest: Payload, -{ - // Note(safety): Safe as the transfer has not started yet. - let dest = unsafe { dest.as_immutable() }; - match stream.transfer_direction() { - TransferDirection::P2M => { - configure_buffers(stream, source.peripheral(), dest.memory()); - } - TransferDirection::M2P => { - configure_buffers(stream, dest.peripheral(), source.memory()); - } - TransferDirection::M2M => { - configure_buffers(stream, source.peripheral(), dest.memory()); - } - } -} - -fn configure_buffers( +pub(super) fn configure_safe_transfer( stream: &mut Stream, - peripheral: PeripheralBufferR, - memory: MemoryBufferR, + peripheral: &PeripheralBuffer, + memory: &MemoryBuffer, ) where CXX: ChannelId, DMA: DMATrait, @@ -1729,17 +1187,17 @@ fn configure_buffers( stream.set_m_size(m_size.into()); match peripheral { - PeripheralBufferR::Fixed(buffer) => { + PeripheralBuffer::Fixed(buffer) => { stream.set_pa(Pa(buffer.as_ptr() as u32)); stream.set_pinc(Pinc::Fixed); } - PeripheralBufferR::Incremented(buffer) => match buffer { - IncrementedBufferR::RegularOffset(buffer) => { + PeripheralBuffer::Incremented(buffer) => match buffer { + IncrementedBuffer::RegularOffset(buffer) => { stream.set_pa(Pa(buffer.as_ptr(0) as u32)); stream.set_pinc(Pinc::Incremented); stream.set_pincos(Pincos::PSize); } - IncrementedBufferR::WordOffset(buffer) => { + IncrementedBuffer::WordOffset(buffer) => { stream.set_pa(Pa(buffer.as_ptr(0) as u32)); stream.set_pinc(Pinc::Incremented); stream.set_pincos(Pincos::Word); @@ -1748,23 +1206,35 @@ fn configure_buffers( } match memory { - MemoryBufferR::Fixed(buffer) => { + MemoryBuffer::Fixed(buffer) => { stream.set_m0a(M0a(buffer.as_ptr() as u32)); stream.set_minc(Minc::Fixed); } - MemoryBufferR::Incremented(buffer) => { + MemoryBuffer::Incremented(buffer) => { stream.set_m0a(M0a(buffer.as_ptr(0) as u32)); stream.set_minc(Minc::Incremented); } } + if stream.effective_circular_mode() == CircularMode::Enabled { + if peripheral.is_write() { + stream.set_transfer_direction(TransferDirection::M2P); + } else { + stream.set_transfer_direction(TransferDirection::P2M); + } + } else if peripheral.is_write() { + stream.set_transfer_direction(TransferDirection::M2P); + } else if stream.transfer_direction() == TransferDirection::M2P { + panic!("If memory is the destination, the stream transfer direction must be configured in advance to either `P2M` or `M2M`."); + } + configure_ndt(stream, peripheral, memory); } fn configure_ndt( stream: &mut Stream, - peripheral: PeripheralBufferR, - memory: MemoryBufferR, + peripheral: &PeripheralBuffer, + memory: &MemoryBuffer, ) where CXX: ChannelId, DMA: DMATrait, @@ -1772,12 +1242,12 @@ fn configure_ndt( Memory: Payload, { match peripheral { - PeripheralBufferR::Fixed(_) => { + PeripheralBuffer::Fixed(_) => { match memory { - MemoryBufferR::Fixed(_) => { + MemoryBuffer::Fixed(_) => { // NDT must be configured in advance } - MemoryBufferR::Incremented(buffer) => { + MemoryBuffer::Incremented(buffer) => { let p_size: usize = PayloadSize::from_payload::().into(); let m_size: usize = @@ -1794,82 +1264,136 @@ fn configure_ndt( } } } - PeripheralBufferR::Incremented(buffer) => { + PeripheralBuffer::Incremented(buffer) => { let ndt = u16::try_from(buffer.len()).unwrap(); stream.set_ndt(Ndt(ndt)); } } } -pub(super) fn check_double_buffer_stream_config( - stream: &Stream, +pub(super) fn check_buffer( + peripheral: &PeripheralBuffer, + memory: &MemoryBuffer, ) where - CXX: ChannelId, - DMA: DMATrait, + Peripheral: Payload, + Memory: Payload, { - if stream.transfer_direction() == TransferDirection::M2M { - panic!("The stream direction must not be `M2M` when configuring double buffer streams."); + if peripheral.is_write() == memory.is_write() { + panic!("One buffer mut be read, one must be write."); } +} + +pub(super) fn check_double_buffer( + double_buffer: &[MemoryBuffer; 2], +) where + Memory: Payload, +{ + if double_buffer[0].is_fixed() { + if double_buffer[1].is_incremented() { + panic!("Invalid double buffer config: First buffer `Fixed`, second buffer `Incremented`."); + } + } else { + if double_buffer[1].is_fixed() { + panic!("Invalid double buffer config: First buffer `Incremented`, second buffer `Fixed`."); + } + + let len_0 = double_buffer[0].as_incremented().len(); + let len_1 = double_buffer[1].as_incremented().len(); - if stream.effective_flow_controller() == FlowController::Peripheral { - panic!("The flow controller must not be `Peripheral` when configuring double buffer streams."); + if len_0 != len_1 { + panic!( + "Invalid double buffer config: len_0 ({}) != len_1({})", + len_0, len_1 + ); + } } - debug_assert_eq!(stream.effective_buffer_mode(), BufferMode::DoubleBuffer); + if double_buffer[0].is_write() != double_buffer[1].is_write() { + panic!("Both buffers must be either both read or write."); + } } -pub(super) fn check_double_buffer<'s, MemBuf, P>(double_buffer: &'s [MemBuf; 2]) -where - MemBuf: AsImmutable<'s, Target = MemoryBufferR<'s, P>>, - P: Payload, +pub(super) unsafe fn set_peripheral_impl( + peripheral: &mut PeripheralBuffer, + index: Option, + payload: Peripheral, +) where + Peripheral: Payload, { - let double_buffer = unsafe { - [ - double_buffer[0].as_immutable(), - double_buffer[1].as_immutable(), - ] - }; - match double_buffer[0] { - MemoryBufferR::Fixed(_) => { - if let MemoryBufferR::Incremented(_) = double_buffer[1] { - panic!("Invalid double buffer config: First buffer `Fixed`, second buffer `Incremented`."); + match peripheral { + PeripheralBuffer::Fixed(buffer) => buffer.as_mut_write().set(payload), + PeripheralBuffer::Incremented(buffer) => match buffer { + IncrementedBuffer::RegularOffset(buffer) => { + buffer.as_mut_write().set(index.unwrap(), payload) } - } - MemoryBufferR::Incremented(buffer_0) => { - if let MemoryBufferR::Fixed(_) = double_buffer[1] { - panic!("Invalid double buffer config: First buffer `Incremented`, second buffer `Fixed`."); + IncrementedBuffer::WordOffset(buffer) => { + buffer.as_mut_write().set(index.unwrap(), payload) } + }, + } +} - let len_0 = buffer_0.len(); - let len_1 = double_buffer[1].incremented().len(); +pub(super) unsafe fn set_memory_impl( + memory: &mut MemoryBuffer, + index: Option, + payload: Memory, +) where + Memory: Payload, +{ + match memory { + MemoryBuffer::Fixed(buffer) => buffer.as_mut_write().set(payload), + MemoryBuffer::Incremented(buffer) => { + buffer.as_mut_write().set(index.unwrap(), payload) + } + } +} - if len_0 != len_1 { - panic!( - "Invalid double buffer config: len_0 ({}) != len_1({})", - len_0, len_1 - ); +pub(super) fn mut_ptr_peripheral( + peripheral: &mut PeripheralBuffer, + index: Option, +) -> *mut Peripheral +where + Peripheral: Payload, +{ + match peripheral { + PeripheralBuffer::Fixed(buffer) => buffer.as_mut_write().as_mut_ptr(), + PeripheralBuffer::Incremented(buffer) => match buffer { + IncrementedBuffer::RegularOffset(buffer) => { + buffer.as_mut_write().as_mut_ptr(index.unwrap()) } - } + IncrementedBuffer::WordOffset(buffer) => { + buffer.as_mut_write().as_mut_ptr(index.unwrap()) + } + }, } } -pub(super) fn first_ptr_from_buffer<'s, ImmutBuf, P>( - buffer: &'s ImmutBuf, -) -> *const P +pub(super) fn mut_ptr_memory( + memory: &mut MemoryBuffer, + index: Option, +) -> *mut Memory where - ImmutBuf: AsImmutable<'s, Target = BufferR<'s, 's, P>>, - P: Payload, + Memory: Payload, { - let buffer = unsafe { buffer.as_immutable() }; + match memory { + MemoryBuffer::Fixed(buffer) => buffer.as_mut_write().as_mut_ptr(), + MemoryBuffer::Incremented(buffer) => { + buffer.as_mut_write().as_mut_ptr(index.unwrap()) + } + } +} - match buffer { - BufferR::Peripheral(buffer) => match buffer { - PeripheralBufferR::Fixed(buffer) => buffer.as_ptr(), - PeripheralBufferR::Incremented(buffer) => buffer.as_ptr(0), - }, - BufferR::Memory(buffer) => match buffer { - MemoryBufferR::Fixed(buffer) => buffer.as_ptr(), - MemoryBufferR::Incremented(buffer) => buffer.as_ptr(0), - }, +#[derive(Clone, Copy)] +pub enum DoubleBuffer { + First, + Second, +} + +impl DoubleBuffer { + pub fn index(self) -> usize { + match self { + DoubleBuffer::First => 0, + DoubleBuffer::Second => 1, + } } } From c7b618b89a9421d6faf760c05de3b269913763cb Mon Sep 17 00:00:00 2001 From: Richard Meadows <962920+richardeoin@users.noreply.github.com> Date: Sat, 7 Mar 2020 19:03:04 +0100 Subject: [PATCH 052/103] Move dma.rs into the dma directory This keeps dma functionality together, and clarifies that this file is the central point for DMA documentation --- src/{dma.rs => dma/mod.rs} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/{dma.rs => dma/mod.rs} (100%) diff --git a/src/dma.rs b/src/dma/mod.rs similarity index 100% rename from src/dma.rs rename to src/dma/mod.rs From f496187fddc196cd987d917e13c1a45c846abeb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ad=C3=A4?= Date: Sun, 8 Mar 2020 12:43:17 +0100 Subject: [PATCH 053/103] Added dma feature gate --- Cargo.toml | 1 + src/lib.rs | 5 ++++- src/prelude.rs | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index a903c6b0..cfd94a3f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -44,6 +44,7 @@ device-selected = [] revision_v = [] singlecore = [] dualcore = [] +dma = [] cm4 = [] cm7 = [] rt = ["stm32h7/rt"] diff --git a/src/lib.rs b/src/lib.rs index 16192c09..b84ef61f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -22,6 +22,9 @@ compile_error!( " ); +#[cfg(all(feature = "dma", not(feature = "stm32h743")))] +compile_error!("The DMA module is currently only available for stm32h743"); + pub use embedded_hal as hal; pub use nb; @@ -69,7 +72,7 @@ pub use crate::stm32::interrupt; pub mod adc; #[cfg(feature = "device-selected")] pub mod delay; -#[cfg(feature = "stm32h743")] +#[cfg(all(feature = "device-selected", feature = "dma"))] pub mod dma; #[cfg(feature = "device-selected")] pub mod flash; diff --git a/src/prelude.rs b/src/prelude.rs index dd95b165..79a471ee 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -3,7 +3,7 @@ pub use embedded_hal::prelude::*; pub use crate::adc::AdcExt as _stm32h7xx_hal_adc_AdcExt; pub use crate::delay::DelayExt as _stm32h7xx_hal_delay_DelayExt; -#[cfg(feature = "stm32h743")] +#[cfg(feature = "dma")] pub use crate::dma::DmaExt as _stm32h7xx_hal_dma_DmaExt; pub use crate::flash::FlashExt as _stm32h7xx_hal_flash_FlashExt; pub use crate::gpio::GpioExt as _stm32h7xx_hal_gpio_GpioExt; From 838e3fc4fec84b426b2a6dbf172f29a524115a56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ad=C3=A4?= Date: Sun, 8 Mar 2020 13:33:44 +0100 Subject: [PATCH 054/103] switching to mod.rs style from 2018-style --- src/dma/{mux.rs => mux/mod.rs} | 40 +++++++++++++++++----------------- 1 file changed, 20 insertions(+), 20 deletions(-) rename src/dma/{mux.rs => mux/mod.rs} (97%) diff --git a/src/dma/mux.rs b/src/dma/mux/mod.rs similarity index 97% rename from src/dma/mux.rs rename to src/dma/mux/mod.rs index 5c5830d5..ccd7f565 100644 --- a/src/dma/mux.rs +++ b/src/dma/mux/mod.rs @@ -258,9 +258,9 @@ impl MuxShared { pub struct OverrunError; pub struct RequestGenerator -where - GXX: GenId, - ED: GenED, + where + GXX: GenId, + ED: GenED, { /// This field *must not* be mutated using shared references rb: &'static RGCR, @@ -268,8 +268,8 @@ where } impl RequestGenerator -where - GXX: GenId, + where + GXX: GenId, { pub(super) fn after_reset(rb: &'static RGCR) -> Self { RequestGenerator { @@ -280,9 +280,9 @@ where } impl RequestGenerator -where - GXX: GenId, - ED: GenED, + where + GXX: GenId, + ED: GenED, { pub fn id(&self) -> usize { GXX::ID @@ -322,8 +322,8 @@ where } fn transmute(self) -> RequestGenerator - where - NewED: GenED, + where + NewED: GenED, { RequestGenerator { rb: self.rb, @@ -333,8 +333,8 @@ where } impl RequestGenerator -where - GXX: GenId, + where + GXX: GenId, { pub fn set_gnbreq(&mut self, gnbreq: GNbReq) { self.rb.modify(|_, w| w.gnbreq().bits(gnbreq.into())); @@ -348,8 +348,8 @@ where } impl RequestGenerator -where - GXX: GenId, + where + GXX: GenId, { pub fn disable(self) -> RequestGenerator { self.rb.modify(|_, w| w.ge().clear_bit()); @@ -359,9 +359,9 @@ where } impl RequestGenerator -where - GXX: GenId, - ED: GenED, + where + GXX: GenId, + ED: GenED, { pub fn check_isr( &self, @@ -403,8 +403,8 @@ where } unsafe impl Sync for RequestGenerator -where - GXX: GenId, - ED: GenED, + where + GXX: GenId, + ED: GenED, { } From cf724cf5e1933b97aaaedb9a02f453479bde6370 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ad=C3=A4?= Date: Sun, 8 Mar 2020 18:25:31 +0100 Subject: [PATCH 055/103] Added some documentation --- src/dma/channel.rs | 2 + src/dma/macros.rs | 2 + src/dma/mod.rs | 186 ++++++++++++++++++++++++++++++++++++- src/dma/mux/mod.rs | 2 + src/dma/mux/request_gen.rs | 2 + src/dma/mux/shared.rs | 2 + src/dma/safe_transfer.rs | 2 + src/dma/stream.rs | 2 + 8 files changed, 197 insertions(+), 3 deletions(-) diff --git a/src/dma/channel.rs b/src/dma/channel.rs index decab70a..88f06e92 100644 --- a/src/dma/channel.rs +++ b/src/dma/channel.rs @@ -1,3 +1,5 @@ +//! DMA Channels + use super::stm32::{DMA1, DMA2}; use super::DMATrait; diff --git a/src/dma/macros.rs b/src/dma/macros.rs index da2e2fc5..80704ded 100644 --- a/src/dma/macros.rs +++ b/src/dma/macros.rs @@ -1,3 +1,5 @@ +//! Macros + macro_rules! type_state { ($trait:ident, $($type_state:ident),*) => { pub unsafe trait $trait: core::fmt::Debug + PartialEq + Eq + Clone + Copy + Send + Sync {} diff --git a/src/dma/mod.rs b/src/dma/mod.rs index 642e07f3..313dbd5b 100644 --- a/src/dma/mod.rs +++ b/src/dma/mod.rs @@ -1,3 +1,5 @@ +//! DMA + // TODO: Remove when merging. #![warn(clippy::all)] @@ -51,10 +53,12 @@ use core::mem; use stm32h7::stm32h743 as stm32; use stm32h7::stm32h743::DMAMUX1; +/// Marker Trait for DMA peripherals pub unsafe trait DMATrait: Send {} unsafe impl DMATrait for DMA1 {} unsafe impl DMATrait for DMA2 {} +/// DMA Channel pub struct Channel where CXX: ChannelId, @@ -80,6 +84,7 @@ where SyncED: SyncEDTrait, EgED: EgEDTrait, { + /// Exposes the stream as owned value in a closure pub fn stream_owned( self, op: F, @@ -99,6 +104,7 @@ where } } + /// Exposes the mux as owned value in a closure pub fn mux_owned( self, op: F, @@ -120,6 +126,7 @@ where } } +/// DMA Stream pub struct Stream where CXX: ChannelId, @@ -138,6 +145,9 @@ where CXX: ChannelId, DMA: DMATrait, { + /// Creates an instance of a Stream in initial state. + /// + /// Should only be called after RCC-Reset of the DMA. fn after_reset(rb: &'static ST) -> Self { Stream { rb, @@ -154,18 +164,22 @@ where ED: EDTrait, IsrState: IsrStateTrait, { + /// Returns the id of the Stream pub fn id(&self) -> usize { CXX::STREAM_ID } + /// Performs a *volatile* read of the stream enable bit pub fn is_enabled(&self) -> bool { self.rb.cr.read().en().bit_is_set() } + /// Returns the Transfer Complete Interrupt config flag pub fn transfer_complete_interrupt(&self) -> TransferCompleteInterrupt { self.rb.cr.read().tcie().bit().into() } + /// Sets the Transfer Complete Interrupt config flag pub fn set_transfer_complete_interrupt( &mut self, tc_intrpt: TransferCompleteInterrupt, @@ -173,10 +187,12 @@ where self.rb.cr.modify(|_, w| w.tcie().bit(tc_intrpt.into())); } + /// Returns the Half Transfer Interrupt config flag pub fn half_transfer_interrupt(&self) -> HalfTransferInterrupt { self.rb.cr.read().htie().bit().into() } + /// Sets the Half Transfer Interrupt config flag pub fn set_half_transfer_interrupt( &mut self, ht_intrpt: HalfTransferInterrupt, @@ -184,10 +200,12 @@ where self.rb.cr.modify(|_, w| w.htie().bit(ht_intrpt.into())); } + /// Returns the Transfer Error Interrupt config flag pub fn transfer_error_interrupt(&self) -> TransferErrorInterrupt { self.rb.cr.read().teie().bit().into() } + /// Sets the Transfer Error Interrupt config flag pub fn set_transfer_error_interrupt( &mut self, te_intrpt: TransferErrorInterrupt, @@ -195,10 +213,12 @@ where self.rb.cr.modify(|_, w| w.teie().bit(te_intrpt.into())); } + /// Returns the Direct Mode Error Interrupt config flag pub fn direct_mode_error_interrupt(&self) -> DirectModeErrorInterrupt { self.rb.cr.read().dmeie().bit().into() } + /// Sets the Direct Mode Error Interrupt config flag pub fn set_direct_mode_error_interrupt( &mut self, dme_intrpt: DirectModeErrorInterrupt, @@ -206,26 +226,33 @@ where self.rb.cr.modify(|_, w| w.dmeie().bit(dme_intrpt.into())); } + /// Returns the Fifo Error Interrupt config flag pub fn fifo_error_interrupt(&self) -> FifoErrorInterrupt { self.rb.fcr.read().feie().bit().into() } + /// Sets the Fifo Error Interrupt config flag pub fn set_fifo_error_interrupt(&mut self, fe_intrpt: FifoErrorInterrupt) { self.rb.fcr.modify(|_, w| w.feie().bit(fe_intrpt.into())); } + /// Returns the Flow Controller + /// /// **Note** (for disabled streams): /// This config value gets forced to `Dma`, if `transfer_direction` is `M2M`. /// - /// This invariant is covered in `effective_flow_controller` (defined for disabled streams). + /// This invariant are covered in `effective_flow_controller` (defined for disabled streams). pub fn flow_controller(&self) -> FlowController { self.rb.cr.read().pfctrl().bit().into() } + /// Returns the Transfer Direction pub fn transfer_direction(&self) -> TransferDirection { self.rb.cr.read().dir().bits().try_into().unwrap() } + /// Returns the Circular Mode + /// /// **Note** (for disabled streams): /// This config value gets forced /// @@ -237,18 +264,23 @@ where self.rb.cr.read().circ().bit().into() } + /// Returns the Peripheral Increment config flag pub fn pinc(&self) -> Pinc { self.rb.cr.read().pinc().bit().into() } + /// Returns the Memory Increment config flag pub fn minc(&self) -> Minc { self.rb.cr.read().minc().bit().into() } + /// Returns the Peripheral Size pub fn p_size(&self) -> PSize { self.rb.cr.read().psize().bits().try_into().unwrap() } + /// Returns the Memory Size + /// /// **Note** (for disabled streams): /// This config value gets forced to `p_size`, if `transfer_mode` is `Direct`. /// @@ -257,6 +289,8 @@ where self.rb.cr.read().msize().bits().try_into().unwrap() } + /// Returns the Peripheral Increment Offset + /// /// **Note** (for disabled and enabled streams): /// /// - This config value has no meaning, if `pinc` is `Fixed`. @@ -267,10 +301,13 @@ where self.rb.cr.read().pincos().bit().into() } + /// Returns the Priority Level pub fn priority_level(&self) -> PriorityLevel { self.rb.cr.read().pl().bits().try_into().unwrap() } + /// Returns the Buffer Mode + /// /// **Note** (for disabled streams): /// This config value gets forced to `Regular` **by software** (to avoid TransferError-Flag), if /// @@ -282,6 +319,8 @@ where self.rb.cr.read().dbm().bit().into() } + /// Returns the Current Target + /// /// **Note** (for disabled and enabled streams): /// This config value has no meaning, if `BufferMode` is `Regular`. /// @@ -290,8 +329,12 @@ where self.rb.cr.read().ct().bit().into() } + /// Returns the effective Current Target + /// + /// Read the documentation of `current_target` for more details. + /// /// **Note**: If this config value has no meaning (because `BufferMode` is `Regular`), - /// the method returns `CurrentTarget::M0a` instead of `None`. + /// the method returns `CurrentTarget::M0a`. pub fn effective_current_target(&self) -> CurrentTarget { if self.buffer_mode() == BufferMode::Regular { CurrentTarget::M0a @@ -300,6 +343,8 @@ where } } + /// Returns the Peripheral Burst config flag + /// /// **Note** (for disabled streams): /// This config value gets forced to `Single`, if `transfer_mode` is `Direct`. /// @@ -308,6 +353,8 @@ where self.rb.cr.read().pburst().bits().try_into().unwrap() } + /// Returns the Memory Burst config flag + /// /// **Note** (for disabled streams): /// This config value gets forced to `Single`, if `transfer_mode` is `Direct`. /// @@ -316,22 +363,28 @@ where self.rb.cr.read().mburst().bits().try_into().unwrap() } + /// Returns the content of the NDT register pub fn ndt(&self) -> Ndt { self.rb.ndtr.read().ndt().bits().into() } + /// Sets the content of the NDT register pub fn configured_ndt(&self) -> Ndt { self.config_ndt } + /// Returns the Peripheral Address pub fn pa(&self) -> Pa { self.rb.par.read().pa().bits().into() } + /// Returns the Memory-0 Address pub fn m0a(&self) -> M0a { self.rb.m0ar.read().m0a().bits().into() } + /// Returns the Memory-1 Address + /// /// **Note** (for disabled and enabled streams): /// This config value has no meaning, if `buffer_mode` is `Regular`. /// @@ -340,6 +393,9 @@ where self.rb.m1ar.read().m1a().bits().into() } + /// Returns the effective Memory-1 Address + /// + /// Read the documentation of `m1a` for more details. pub fn effective_m1a(&self) -> Option { if self.buffer_mode() == BufferMode::Regular { None @@ -348,6 +404,8 @@ where } } + /// Returns the Fifo Threshold + /// /// **Note** (for disabled and enabled streams): /// This config value has no meaning, if `transfer_mode` is `Direct`. /// @@ -356,6 +414,11 @@ where self.rb.fcr.read().fth().bits().try_into().unwrap() } + /// Returns the effective Fifo Threshold. + /// + /// If the Fifo Threshold has no meaning, `None` is being returned. + /// + /// Read the documentation of `fifo_threshold` for more details. pub fn effective_fifo_threshold(&self) -> Option { if self.transfer_mode() == TransferMode::Direct { None @@ -364,22 +427,26 @@ where } } + /// Returns the Transfer Mode (`Direct` or `Fifo` Mode) pub fn transfer_mode(&self) -> TransferMode { self.rb.fcr.read().dmdis().bit().into() } + /// Performs the volatile write to the `M0a` register fn impl_set_m0a(&mut self, m0a: M0a) { unsafe { self.rb.m0ar.modify(|_, w| w.m0a().bits(m0a.into())); } } + /// Performs the volatile write to the `M1a` register fn impl_set_m1a(&mut self, m1a: M1a) { unsafe { self.rb.m0ar.modify(|_, w| w.m0a().bits(m1a.into())); } } + /// Transmutes the state of `self` fn transmute( self, ) -> Stream @@ -401,72 +468,86 @@ where DMA: DMATrait, IsrState: IsrStateTrait, { + /// Sets the Flow Controller pub fn set_flow_controller(&mut self, flow_controller: FlowController) { self.rb .cr .modify(|_, w| w.pfctrl().bit(flow_controller.into())); } + /// Sets the Transfer Direction pub fn set_transfer_direction(&mut self, transfer_dir: TransferDirection) { unsafe { self.rb.cr.modify(|_, w| w.dir().bits(transfer_dir.into())); } } + /// Sets the Circular Mode pub fn set_circular_mode(&mut self, circ_mode: CircularMode) { self.rb.cr.modify(|_, w| w.circ().bit(circ_mode.into())); } + /// Sets the Peripheral Increment config flag pub fn set_pinc(&mut self, pinc: Pinc) { self.rb.cr.modify(|_, w| w.pinc().bit(pinc.into())); } + /// Sets the Memory Increment config flag pub fn set_minc(&mut self, minc: Minc) { self.rb.cr.modify(|_, w| w.minc().bit(minc.into())); } + /// Sets the Peripheral Size pub fn set_p_size(&mut self, p_size: PSize) { unsafe { self.rb.cr.modify(|_, w| w.psize().bits(p_size.into())); } } + /// Sets the Memory Size pub fn set_m_size(&mut self, m_size: MSize) { unsafe { self.rb.cr.modify(|_, w| w.msize().bits(m_size.into())); } } + /// Sets the Peripheral Increment Offset pub fn set_pincos(&mut self, pincos: Pincos) { self.rb.cr.modify(|_, w| w.pincos().bit(pincos.into())); } + /// Sets the Priority Level pub fn set_priority_level(&mut self, priority_level: PriorityLevel) { unsafe { self.rb.cr.modify(|_, w| w.pl().bits(priority_level.into())); } } + /// Sets the Buffer Mode (`Direct` or `Fifo` mode) pub fn set_buffer_mode(&mut self, buffer_mode: BufferMode) { self.rb.cr.modify(|_, w| w.dbm().bit(buffer_mode.into())); } + /// Sets the Current Target pub fn set_current_target(&mut self, current_target: CurrentTarget) { self.rb.cr.modify(|_, w| w.ct().bit(current_target.into())); } + /// Sets the Peripheral Burst pub fn set_p_burst(&mut self, p_burst: PBurst) { unsafe { self.rb.cr.modify(|_, w| w.pburst().bits(p_burst.into())); } } + /// Sets the Memory Burst pub fn set_m_burst(&mut self, m_burst: MBurst) { unsafe { self.rb.cr.modify(|_, w| w.mburst().bits(m_burst.into())); } } + /// Sets the NDT register pub fn set_ndt(&mut self, ndt: Ndt) { self.config_ndt = ndt; @@ -475,20 +556,24 @@ where } } + /// Sets the Peripheral Address pub fn set_pa(&mut self, pa: Pa) { unsafe { self.rb.par.modify(|_, w| w.pa().bits(pa.into())); } } + /// Sets the Memory-0 Address pub fn set_m0a(&mut self, m0a: M0a) { self.impl_set_m0a(m0a); } + /// Sets the Memory-1 Address pub fn set_m1a(&mut self, m1a: M1a) { self.impl_set_m1a(m1a); } + /// Sets the Fifo Threshold pub fn set_fifo_threshold(&mut self, fifo_threshold: FifoThreshold) { unsafe { self.rb @@ -497,12 +582,16 @@ where } } + /// Sets the Transfer Mode pub fn set_transfer_mode(&mut self, transfer_mode: TransferMode) { self.rb .fcr .modify(|_, w| w.dmdis().bit(transfer_mode.into())); } + /// Returns the effective Flow Controller + /// + /// Read the documentation of `flow_controller` for more details. pub fn effective_flow_controller(&self) -> FlowController { if self.transfer_direction() == TransferDirection::M2M { FlowController::Dma @@ -511,6 +600,9 @@ where } } + /// Returns the effective Circular Mode + /// + /// Read the documentation of `circular_mode` for more details. pub fn effective_circular_mode(&self) -> CircularMode { if self.buffer_mode() == BufferMode::DoubleBuffer { CircularMode::Enabled @@ -519,6 +611,9 @@ where } } + /// Returns the effective Memory Size + /// + /// Read the documentation of `m_size` for more details. pub fn effective_m_size(&self) -> MSize { if self.transfer_mode() == TransferMode::Direct { match self.p_size() { @@ -531,6 +626,9 @@ where } } + /// Returns the effective Peripheral Increment Offset + /// + /// Read the documentation of `pincos` for more details. pub fn effective_pincos(&self) -> Option { if self.pinc() == Pinc::Fixed { return None; @@ -545,6 +643,9 @@ where } } + /// Returns the effective Peripheral Burst + /// + /// Read the documentation of `p_burst` for more details. pub fn effective_p_burst(&self) -> PBurst { if self.transfer_mode() == TransferMode::Direct { PBurst::Single @@ -553,6 +654,9 @@ where } } + /// Returns the effective Memory Burst + /// + /// Read the documentation of `m_burst` for more details. pub fn effective_m_burst(&self) -> MBurst { if self.transfer_mode() == TransferMode::Direct { MBurst::Single @@ -569,6 +673,11 @@ where ED: NotDisabled, IsrState: IsrStateTrait, { + /// Sets the Memory-0 Address on the fly + /// + /// # Panic + /// + /// This panics if the stream is not in Double Buffer Mode. pub fn set_m0a(&mut self, m0a: M0a) -> nb::Result<(), Infallible> { self.check_double_buffer(); @@ -581,6 +690,11 @@ where Ok(()) } + /// Sets the Memory-1 Address on the fly + /// + /// # Panic + /// + /// This panics if the stream is not in Double Buffer Mode. pub fn set_m1a(&mut self, m1a: M1a) -> nb::Result<(), Infallible> { self.check_double_buffer(); @@ -593,6 +707,7 @@ where Ok(()) } + /// Checks if the stream is in Double Buffer Mode fn check_double_buffer(&self) { if self.buffer_mode() == BufferMode::Regular { panic!("The buffer must be in double buffer mode to be changed on the fly."); @@ -605,15 +720,21 @@ where CXX: ChannelId, DMA: DMATrait, { + /// Checks the config for data integrity and enables the stream + /// /// # Safety /// - /// Aliasing rules aren't enforced + /// Aliasing rules aren't enforced. pub unsafe fn enable(self) -> Stream { self.check_config(); self.enable_unchecked() } + /// Enables the stream without checking the config + /// + /// Consider using the checked version instead (`enable`). + /// /// # Safety /// /// - Aliasing rules aren't enforced @@ -626,6 +747,7 @@ where self.transmute() } + /// Checks the config for data integrity fn check_config(&self) { if self.effective_circular_mode() == CircularMode::Enabled { self.check_config_circular(); @@ -638,6 +760,9 @@ where self.check_ndt(); } + /// Checks the circular config. + // + // Reference: RM0433 Rev 6 - Chapter 15.3.10 fn check_config_circular(&self) { // Check for clashing config values if self.transfer_direction() == TransferDirection::M2M @@ -682,6 +807,7 @@ where } } + /// Checks the fifo config. fn check_config_fifo(&self) { if self.m_burst() != MBurst::Single { self.check_config_fifo_m_burst(); @@ -692,6 +818,9 @@ where } } + /// Checks the memory config of fifo stream. + // + // Reference: RM0433 Rev 6 - Chapter 15.3.14 fn check_config_fifo_m_burst(&self) { let m_size = self.m_size().into_num(); let m_burst = self.m_burst().into_num(); @@ -707,6 +836,9 @@ where } } + /// Checks the peripheral config of fifio stream. + // + // Reference: RM0433 Rev 6 - Chapter 15.3.14 fn check_config_fifo_p_burst(&self) { let p_burst = self.p_burst().into_num(); let p_size = self.p_size().into_num(); @@ -724,6 +856,9 @@ where } } + /// Checks the NDT register + // + // Reference: RM0433 Rev 6 - Chapter 15.3.12 fn check_ndt(&self) { let m_size = self.m_size().into_num(); let p_size = self.p_size().into_num(); @@ -741,12 +876,16 @@ where DMA: DMATrait, IsrState: IsrStateTrait, { + /// Disables the stream pub fn disable(self) -> Stream { self.rb.cr.modify(|_, w| w.en().clear_bit()); self.transmute() } + /// Returns the effective Peripheral Increment Offset + /// + /// Read the documentation of `pincos` for more details. pub fn effective_pincos(&self) -> Option { if self.pinc() == Pinc::Fixed { None @@ -762,6 +901,7 @@ where DMA: DMATrait, IsrState: IsrStateTrait, { + /// Block current thread until stream has been disabled. pub fn await_disabled(self) -> Stream { while self.rb.cr.read().en().bit_is_set() {} @@ -775,6 +915,10 @@ where DMA: DMATrait, ED: EDTrait, { + /// Returns the contents of the isr. + /// + /// * If there is no error, an optional event is returned as `Ok` + /// * If there are errors, the errors are being wrapped into `Error` and returned as `Err` pub fn check_isr( &self, isr: &StreamIsr, @@ -806,6 +950,7 @@ where } } + /// Returns the Transfer Complete flag pub fn transfer_complete_flag(&self, isr: &StreamIsr) -> bool { match self.id() { 0 => isr.lisr.read().tcif0().bit_is_set(), @@ -820,6 +965,7 @@ where } } + /// Returns the Half Transfer flag pub fn half_transfer_flag(&self, isr: &StreamIsr) -> bool { match self.id() { 0 => isr.lisr.read().htif0().bit_is_set(), @@ -834,6 +980,7 @@ where } } + /// Returns the Transfer Error flag pub fn transfer_error_flag(&self, isr: &StreamIsr) -> bool { match self.id() { 0 => isr.lisr.read().teif0().bit_is_set(), @@ -848,6 +995,7 @@ where } } + /// Returns the Direct Mode Error flag pub fn direct_mode_error_flag(&self, isr: &StreamIsr) -> bool { match self.id() { 0 => isr.lisr.read().dmeif0().bit_is_set(), @@ -862,6 +1010,7 @@ where } } + /// Returns the Fifo Error flag pub fn fifo_error_flag(&self, isr: &StreamIsr) -> bool { match self.id() { 0 => isr.lisr.read().feif0().bit_is_set(), @@ -876,6 +1025,7 @@ where } } + /// Performs the ISR clear fn clear_isr_impl(&self, isr: &mut StreamIsr) { self.clear_transfer_complete(isr); self.clear_half_transfer(isr); @@ -884,6 +1034,7 @@ where self.clear_fifo_error(isr); } + /// Clears the Transfer Complete flag pub fn clear_transfer_complete(&self, isr: &mut StreamIsr) { match self.id() { 0 => { @@ -914,6 +1065,7 @@ where } } + /// Clears the Half Transfer flag pub fn clear_half_transfer(&self, isr: &mut StreamIsr) { match self.id() { 0 => { @@ -944,6 +1096,7 @@ where } } + /// Clears the Transfer Error flag pub fn clear_transfer_error(&self, isr: &mut StreamIsr) { match self.id() { 0 => { @@ -974,6 +1127,7 @@ where } } + /// Clears the Direct Mode Error flag pub fn clear_direct_mode_error(&self, isr: &mut StreamIsr) { match self.id() { 0 => { @@ -1004,6 +1158,7 @@ where } } + /// Clears the Fifo Error flag pub fn clear_fifo_error(&self, isr: &mut StreamIsr) { match self.id() { 0 => { @@ -1040,6 +1195,7 @@ where CXX: ChannelId, DMA: DMATrait, { + /// Clears the ISR pub fn clear_isr( self, isr: &mut StreamIsr, @@ -1056,6 +1212,7 @@ where DMA: DMATrait, ED: NotDisabled, { + /// Clears the ISR pub fn clear_isr(&self, isr: &mut StreamIsr) { self.clear_isr_impl(isr); } @@ -1079,6 +1236,7 @@ where { } +/// DMA Mux pub struct DmaMux where CXX: ChannelId, @@ -1096,6 +1254,9 @@ impl DmaMux where CXX: ChannelId, { + /// Creates an instance of a DMA Mux in initial state. + /// + /// Should only be called after RCC-reset of the DMA. fn after_reset(rb: &'static CCR) -> Self { DmaMux { rb, @@ -1112,10 +1273,12 @@ where SyncED: SyncEDTrait, EgED: EgEDTrait, { + /// Returns the id of the DMA Mux pub fn id(&self) -> usize { CXX::MUX_ID } + /// Returns the request id assigned to this Mux pub fn request_id(&self) -> RequestId { debug_assert_eq!( ReqId::REQUEST_ID, @@ -1129,10 +1292,12 @@ where ReqId::REQUEST_ID } + /// Returns the Sync Overrun Interrupt config flag pub fn sync_overrun_interrupt(&self) -> SyncOverrunInterrupt { self.rb.read().soie().bit().into() } + /// Sets the Sync Overrun Interrupt config flag pub fn set_sync_overrun_interrupt( &mut self, sync_overrun_intrpt: SyncOverrunInterrupt, @@ -1141,34 +1306,41 @@ where .modify(|_, w| w.soie().bit(sync_overrun_intrpt.into())); } + /// Returns the Synchronization Polarity pub fn sync_polarity(&self) -> SyncPolarity { self.rb.read().spol().bits().try_into().unwrap() } + /// Sets the Synchronization Polarity pub fn set_sync_polarity(&mut self, sync_polarity: SyncPolarity) { self.rb.modify(|_, w| w.spol().bits(sync_polarity.into())); } + /// Returns the number of requests pub fn nbreq(&self) -> NbReq { self.rb.read().nbreq().bits().try_into().unwrap() } + /// Returns the Synchronization ID pub fn sync_id(&self) -> SyncId { self.rb.read().sync_id().bits().try_into().unwrap() } + /// Sets the Synchronization ID pub fn set_sync_id(&mut self, sync_id: SyncId) { unsafe { self.rb.modify(|_, w| w.sync_id().bits(sync_id.into())); } } + /// Performs the request id write fn set_req_id_impl(&mut self, request_id: RequestId) { unsafe { self.rb.modify(|_, w| w.dmareq_id().bits(request_id.into())); } } + /// Transmutes the state of the DMA Mux fn transmute( self, ) -> DmaMux @@ -1189,6 +1361,7 @@ where CXX: ChannelId, ReqId: RequestIdTrait, { + /// Sets the number of requests pub fn set_nbreq(&mut self, nbreq: NbReq) { self.rb.modify(|_, w| w.nbreq().bits(nbreq.into())); } @@ -1200,6 +1373,7 @@ where ReqId: RequestIdTrait, EgED: EgEDTrait, { + /// Enables synchronization pub fn enable_sync(self) -> DmaMux { self.rb.modify(|_, w| w.se().set_bit()); @@ -1213,6 +1387,7 @@ where ReqId: RequestIdTrait, EgED: EgEDTrait, { + /// Disables synchronization pub fn disable_sync(self) -> DmaMux { self.rb.modify(|_, w| w.se().clear_bit()); @@ -1226,6 +1401,7 @@ where ReqId: RequestIdTrait, SyncED: SyncEDTrait, { + /// Enables event generation pub fn enable_event_gen(self) -> DmaMux { self.rb.modify(|_, w| w.ege().set_bit()); @@ -1239,6 +1415,7 @@ where ReqId: RequestIdTrait, SyncED: SyncEDTrait, { + /// Disables event generation pub fn disable_event_gen(self) -> DmaMux { self.rb.modify(|_, w| w.ege().clear_bit()); @@ -1252,6 +1429,7 @@ where SyncED: SyncEDTrait, EgED: EgEDTrait, { + /// Sets request id pub fn set_req_id( mut self, req_id: NewReqId, @@ -1276,6 +1454,7 @@ where SyncED: SyncEDTrait, EgED: EgEDTrait, { + /// Unsets request id, defaulting to `ReqNone` and returning the old one pub fn unset_req_id( mut self, ) -> (DmaMux, ReqId) { @@ -1291,6 +1470,7 @@ where (new_dma_mux, old_req_id) } + /// Replaces the request id pub fn replace_req_id( mut self, req_id: NewReqId, diff --git a/src/dma/mux/mod.rs b/src/dma/mux/mod.rs index ccd7f565..c203f470 100644 --- a/src/dma/mux/mod.rs +++ b/src/dma/mux/mod.rs @@ -1,3 +1,5 @@ +//! DMA Mux + pub mod request_gen; pub mod shared; diff --git a/src/dma/mux/request_gen.rs b/src/dma/mux/request_gen.rs index 0b6651cc..bc530957 100644 --- a/src/dma/mux/request_gen.rs +++ b/src/dma/mux/request_gen.rs @@ -1,3 +1,5 @@ +//! DMA Request Generator + type_state! { ED, Disabled, Enabled } diff --git a/src/dma/mux/shared.rs b/src/dma/mux/shared.rs index cfbb32bf..4a8fb1f0 100644 --- a/src/dma/mux/shared.rs +++ b/src/dma/mux/shared.rs @@ -1,3 +1,5 @@ +//! DMA Mux shared access objects + use super::super::stm32::dmamux1::{CFR, CSR, RGCFR, RGSR}; pub struct MuxIsr { diff --git a/src/dma/safe_transfer.rs b/src/dma/safe_transfer.rs index 83605c24..27656844 100644 --- a/src/dma/safe_transfer.rs +++ b/src/dma/safe_transfer.rs @@ -1,3 +1,5 @@ +//! Safe DMA Transfers + use super::channel::ChannelId; use super::stream::{ CircularMode, Disabled, Enabled, IsrCleared, IsrUncleared, M0a, MSize, diff --git a/src/dma/stream.rs b/src/dma/stream.rs index 115e8df3..bab47b24 100644 --- a/src/dma/stream.rs +++ b/src/dma/stream.rs @@ -1,3 +1,5 @@ +//! DMA Stream + use super::stm32::dma1::{HIFCR, HISR, LIFCR, LISR}; use super::DMATrait; use core::marker::PhantomData; From f97665f22b7a5af6ab8f9052a0d64c98aa844371 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ad=C3=A4?= Date: Fri, 13 Mar 2020 15:05:12 +0100 Subject: [PATCH 056/103] Added some doc --- src/dma/mod.rs | 45 +++++++++++++++++++++++++++++++++++++++- src/dma/safe_transfer.rs | 4 ++-- 2 files changed, 46 insertions(+), 3 deletions(-) diff --git a/src/dma/mod.rs b/src/dma/mod.rs index 313dbd5b..6aa709bb 100644 --- a/src/dma/mod.rs +++ b/src/dma/mod.rs @@ -1498,6 +1498,7 @@ where SyncED: SyncEDTrait, EgED: EgEDTrait, { + /// Checks the ISR for errors pub fn check_isr(&self, mux_isr: &MuxIsr) -> Result<(), OverrunError> { if self.is_sync_overrun(mux_isr) { Err(OverrunError) @@ -1506,12 +1507,14 @@ where } } + /// Returns the Sync Overrun flag pub fn is_sync_overrun(&self, mux_isr: &MuxIsr) -> bool { let mask: u16 = 1 << self.id() as u16; mux_isr.csr.read().sof().bits() & mask != 0 } + /// Clears the ISR pub fn clear_isr(&self, mux_isr: &mut MuxIsr) { match self.id() { 0 => mux_isr.cfr.write(|w| w.csof0().set_bit()), @@ -1553,6 +1556,7 @@ where { } +/// Memory-safe DMA transfer for single-buffer pub struct SafeTransfer<'wo, Peripheral, Memory, State> where Peripheral: Payload, @@ -1569,6 +1573,7 @@ where Peripheral: Payload, Memory: Payload, { + /// Initializes new DMA transfer without starting it yet pub fn new( peripheral: PeripheralBufferStatic<'wo, Peripheral>, memory: MemoryBufferStatic, @@ -1590,14 +1595,18 @@ where Memory: Payload, State: TransferState, { + /// Returns peripheral buffer pub fn peripheral(&self) -> &PeripheralBufferStatic<'wo, Peripheral> { &self.peripheral } + /// Returns memory buffer pub fn memory(&self) -> &MemoryBufferStatic { &self.memory } + /// Sets the content of destination buffer + /// /// # Safety /// /// The caller must ensure, that the DMA is currently not modifying this address. @@ -1617,6 +1626,7 @@ where } } + /// Returns pointer to destination buffer pub fn dest_ptr( &mut self, index: Option, @@ -1638,6 +1648,7 @@ where Source: Payload, Dest: Payload, { + /// Starts the transfer pub fn start( self, mut stream: Stream, @@ -1666,10 +1677,12 @@ where CXX: ChannelId, DMA: DMATrait, { + /// Returns the stream assigned to the transfer pub fn stream(&self) -> &Stream { &self.state.stream } + /// Sets the Transfer Complete Interrupt config flag of the assigned stream pub fn set_transfer_complete_interrupt( &mut self, tc_intrpt: TransferCompleteInterrupt, @@ -1677,6 +1690,7 @@ where self.state.stream.set_transfer_complete_interrupt(tc_intrpt); } + /// Sets the Half Transfer Interrupt config flag of the assigned stream pub fn set_half_transfer_interrupt( &mut self, ht_intrpt: HalfTransferInterrupt, @@ -1684,6 +1698,7 @@ where self.state.stream.set_half_transfer_interrupt(ht_intrpt); } + /// Sets the Transfer Error Interrupt config flag of the assigned stream pub fn set_transfer_error_interrupt( &mut self, te_intrpt: TransferErrorInterrupt, @@ -1691,6 +1706,7 @@ where self.state.stream.set_transfer_error_interrupt(te_intrpt); } + /// Sets the Direct Mode Error Interrupt config flag of the assigned stream pub fn set_direct_mode_error_interrupt( &mut self, dme_intrpt: DirectModeErrorInterrupt, @@ -1700,16 +1716,18 @@ where .set_direct_mode_error_interrupt(dme_intrpt); } + /// Sets the Fifo Error Interrupt config flag of the assigned stream pub fn set_fifo_error_interrupt(&mut self, fe_intrpt: FifoErrorInterrupt) { self.state.stream.set_fifo_error_interrupt(fe_intrpt); } + /// Stops the transfer, returning the stream pub fn stop(self) -> Stream { self.state.stream.disable().await_disabled() } } -/// Safe Transfer with Double Buffer as Source +/// Memory-safe DMA transfer for double buffer pub struct SafeTransferDoubleBuffer<'wo, Peripheral, Memory, State> where Peripheral: Payload, @@ -1727,6 +1745,7 @@ where Peripheral: Payload, Memory: Payload, { + /// Initializes new DMA transfer without starting it yet pub fn new( peripheral: PeripheralBufferStatic<'wo, Peripheral>, memories: [MemoryBufferStatic; 2], @@ -1749,14 +1768,17 @@ where Memory: Payload, State: TransferState, { + /// Returns peripheral buffer pub fn peripheral(&self) -> &PeripheralBufferStatic<'wo, Peripheral> { &self.peripheral } + /// Returns memory buffers pub fn memories(&self) -> &[MemoryBufferStatic; 2] { &self.memories } + /// Sets the content of destination buffer pub unsafe fn set_dest( &mut self, index: Option, @@ -1778,6 +1800,7 @@ where } } + /// Returns a pointer to the destination buffer pub fn dest_ptr( &mut self, index: Option, @@ -1804,6 +1827,7 @@ where Peripheral: Payload, Memory: Payload, { + /// Starts the transfer pub fn start( self, mut stream: Stream, @@ -1839,10 +1863,12 @@ where CXX: ChannelId, DMA: DMATrait, { + /// Returns the stream assigned to the transfer pub fn stream(&self) -> &Stream { &self.state.stream } + /// Sets the Transfer Complete Interrupt config flag pub fn set_transfer_complete_interrupt( &mut self, tc_intrpt: TransferCompleteInterrupt, @@ -1850,6 +1876,7 @@ where self.state.stream.set_transfer_complete_interrupt(tc_intrpt); } + /// Sets the Half Transfer Interrupt config flag pub fn set_half_transfer_interrupt( &mut self, ht_intrpt: HalfTransferInterrupt, @@ -1857,6 +1884,7 @@ where self.state.stream.set_half_transfer_interrupt(ht_intrpt); } + /// Sets the Transfer Error Interrupt config flag pub fn set_transfer_error_interrupt( &mut self, te_intrpt: TransferErrorInterrupt, @@ -1864,6 +1892,7 @@ where self.state.stream.set_transfer_error_interrupt(te_intrpt); } + /// Sets the Direct Mode Error Interrupt config flag pub fn set_direct_mode_error_interrupt( &mut self, dme_intrpt: DirectModeErrorInterrupt, @@ -1873,10 +1902,12 @@ where .set_direct_mode_error_interrupt(dme_intrpt); } + /// Sets the Fifo Error Interrupt config flag pub fn set_fifo_error_interrupt(&mut self, fe_intrpt: FifoErrorInterrupt) { self.state.stream.set_fifo_error_interrupt(fe_intrpt); } + /// Sets the memory-0 address pub fn set_m0a(&mut self, m0a: MemoryBufferStatic) { let ptr = m0a.as_ptr(Some(0)); @@ -1887,6 +1918,7 @@ where block!(self.state.stream.set_m0a(M0a(ptr as u32))).unwrap(); } + /// Sets the memory-1 address pub fn set_m1a(&mut self, m1a: MemoryBufferStatic) { let ptr = m1a.as_ptr(Some(0)); @@ -1897,6 +1929,7 @@ where block!(self.state.stream.set_m1a(M1a(ptr as u32))).unwrap(); } + /// Stops the transfer pub fn stop(self) -> Stream { self.state.stream.disable().await_disabled() } @@ -1935,16 +1968,22 @@ pub type RequestGenerators = ( RequestGenerator, ); +/// Container for shared items across the dma pub struct DmaShared { pub stream_isr_dma_1: StreamIsr, pub stream_isr_dma_2: StreamIsr, pub mux_shared: MuxShared, } +/// Contains all channels, request generators and the shared items pub struct Dma { + /// Channels for DMA1 pub channels_dma_1: ChannelsDma1, + /// Channels for DMA2 pub channels_dma_2: ChannelsDma2, + /// Shared items for both DMAs pub dma_shared: DmaShared, + /// All request generators pub request_generators: RequestGenerators, /// Do not access this field. This is stored in case the user want's the peripheral back. _dma_1: DMA1, @@ -1955,6 +1994,7 @@ pub struct Dma { } impl Dma { + /// Initializes the DMA-HAL. This is the entrypoint of the HAL. pub fn new( dma_1: DMA1, dma_2: DMA2, @@ -2089,6 +2129,7 @@ impl Dma { } } + /// Resets the DMA fn reset_dma(rcc: &mut RCC) { rcc.ahb1rstr.modify(|_, w| w.dma1rst().set_bit()); rcc.ahb1rstr.modify(|_, w| w.dma1rst().clear_bit()); @@ -2096,11 +2137,13 @@ impl Dma { rcc.ahb1rstr.modify(|_, w| w.dma2rst().clear_bit()); } + /// Enables the DMA clock fn enable_dma(rcc: &mut RCC) { rcc.ahb1enr.modify(|_, w| w.dma1en().set_bit()); rcc.ahb1enr.modify(|_, w| w.dma2en().set_bit()); } + /// Resets the MUX by manually clearing all bits fn reset_mux(mux: &mut DMAMUX1) { for ccr in mux.ccr.iter() { ccr.reset(); diff --git a/src/dma/safe_transfer.rs b/src/dma/safe_transfer.rs index 27656844..38c156cf 100644 --- a/src/dma/safe_transfer.rs +++ b/src/dma/safe_transfer.rs @@ -1143,7 +1143,7 @@ fn check_buffer_not_empty

(buffer: &[P]) { } // -// Secure Transfer implementations +// Safe Transfer implementations // fn check_word_offset

(buffer: &[*const P]) @@ -1304,7 +1304,7 @@ pub(super) fn check_double_buffer( if len_0 != len_1 { panic!( - "Invalid double buffer config: len_0 ({}) != len_1({})", + "Invalid double buffer config: len_0 ({}) != len_1 ({})", len_0, len_1 ); } From 1ef4ed56ff09d920f4791095407b71af7559eaa4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ad=C3=A4?= Date: Fri, 13 Mar 2020 19:34:44 +0100 Subject: [PATCH 057/103] fmt --- src/dma/mux/mod.rs | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/src/dma/mux/mod.rs b/src/dma/mux/mod.rs index c203f470..fa43853d 100644 --- a/src/dma/mux/mod.rs +++ b/src/dma/mux/mod.rs @@ -260,9 +260,9 @@ impl MuxShared { pub struct OverrunError; pub struct RequestGenerator - where - GXX: GenId, - ED: GenED, +where + GXX: GenId, + ED: GenED, { /// This field *must not* be mutated using shared references rb: &'static RGCR, @@ -270,8 +270,8 @@ pub struct RequestGenerator } impl RequestGenerator - where - GXX: GenId, +where + GXX: GenId, { pub(super) fn after_reset(rb: &'static RGCR) -> Self { RequestGenerator { @@ -282,9 +282,9 @@ impl RequestGenerator } impl RequestGenerator - where - GXX: GenId, - ED: GenED, +where + GXX: GenId, + ED: GenED, { pub fn id(&self) -> usize { GXX::ID @@ -324,8 +324,8 @@ impl RequestGenerator } fn transmute(self) -> RequestGenerator - where - NewED: GenED, + where + NewED: GenED, { RequestGenerator { rb: self.rb, @@ -335,8 +335,8 @@ impl RequestGenerator } impl RequestGenerator - where - GXX: GenId, +where + GXX: GenId, { pub fn set_gnbreq(&mut self, gnbreq: GNbReq) { self.rb.modify(|_, w| w.gnbreq().bits(gnbreq.into())); @@ -350,8 +350,8 @@ impl RequestGenerator } impl RequestGenerator - where - GXX: GenId, +where + GXX: GenId, { pub fn disable(self) -> RequestGenerator { self.rb.modify(|_, w| w.ge().clear_bit()); @@ -361,9 +361,9 @@ impl RequestGenerator } impl RequestGenerator - where - GXX: GenId, - ED: GenED, +where + GXX: GenId, + ED: GenED, { pub fn check_isr( &self, @@ -405,8 +405,8 @@ impl RequestGenerator } unsafe impl Sync for RequestGenerator - where - GXX: GenId, - ED: GenED, +where + GXX: GenId, + ED: GenED, { } From e2e046aeeaebe1cb55858fc104ae6ac93a5fee0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ad=C3=A4?= Date: Sun, 15 Mar 2020 18:49:17 +0100 Subject: [PATCH 058/103] Added Sealed trait --- src/dma/channel.rs | 10 +++++++--- src/dma/macros.rs | 6 ++++-- src/dma/mod.rs | 7 ++++--- src/dma/mux/mod.rs | 15 +++++++++------ src/dma/mux/request_gen.rs | 7 +++++-- src/dma/mux/shared.rs | 2 +- src/dma/safe_transfer.rs | 15 ++++++++++++--- src/dma/stream.rs | 10 ++++++---- src/lib.rs | 8 ++++++++ src/private.rs | 19 +++++++++++++++++++ 10 files changed, 75 insertions(+), 24 deletions(-) create mode 100644 src/private.rs diff --git a/src/dma/channel.rs b/src/dma/channel.rs index 88f06e92..46505f41 100644 --- a/src/dma/channel.rs +++ b/src/dma/channel.rs @@ -1,21 +1,25 @@ //! DMA Channels -use super::stm32::{DMA1, DMA2}; use super::DMATrait; +use crate::private; +use crate::stm32::{DMA1, DMA2}; -pub unsafe trait ChannelId: Send { +pub trait ChannelId: Send + private::Sealed { const STREAM_ID: usize; const MUX_ID: usize; type DMA: DMATrait; } +#[doc(hidden)] macro_rules! channels { ($($channel:ident => [$stream:tt, $mux:tt, $dma:ident]),*) => { $( pub struct $channel; - unsafe impl ChannelId for $channel { + impl crate::private::Sealed for $channel {} + + impl ChannelId for $channel { const STREAM_ID: usize = $stream; const MUX_ID: usize = $mux; diff --git a/src/dma/macros.rs b/src/dma/macros.rs index 80704ded..81f6149d 100644 --- a/src/dma/macros.rs +++ b/src/dma/macros.rs @@ -2,13 +2,15 @@ macro_rules! type_state { ($trait:ident, $($type_state:ident),*) => { - pub unsafe trait $trait: core::fmt::Debug + PartialEq + Eq + Clone + Copy + Send + Sync {} + pub trait $trait: core::fmt::Debug + PartialEq + Eq + Clone + Copy + Send + Sync + crate::private::Sealed {} $( #[derive(Debug, PartialEq, Eq, Clone, Copy)] pub struct $type_state; - unsafe impl $trait for $type_state {} + impl crate::private::Sealed for $type_state {} + + impl $trait for $type_state {} )* }; } diff --git a/src/dma/mod.rs b/src/dma/mod.rs index 6aa709bb..d97a0818 100644 --- a/src/dma/mod.rs +++ b/src/dma/mod.rs @@ -45,6 +45,7 @@ use self::stream::{ TransferErrorInterrupt, TransferMode, ED as EDTrait, }; use crate::nb::{self, block, Error as NbError}; +use crate::private; use crate::rcc::Ccdr; use core::convert::{Infallible, TryFrom, TryInto}; use core::marker::PhantomData; @@ -54,9 +55,9 @@ use stm32h7::stm32h743 as stm32; use stm32h7::stm32h743::DMAMUX1; /// Marker Trait for DMA peripherals -pub unsafe trait DMATrait: Send {} -unsafe impl DMATrait for DMA1 {} -unsafe impl DMATrait for DMA2 {} +pub trait DMATrait: Send + private::Sealed {} +impl DMATrait for DMA1 {} +impl DMATrait for DMA2 {} /// DMA Channel pub struct Channel diff --git a/src/dma/mux/mod.rs b/src/dma/mux/mod.rs index fa43853d..a8b1c8ec 100644 --- a/src/dma/mux/mod.rs +++ b/src/dma/mux/mod.rs @@ -8,7 +8,7 @@ use self::request_gen::{ TriggerOverrunError, TriggerOverrunInterrupt, ED as GenED, }; use self::shared::{MuxIsr, RequestGenIsr}; -use super::stm32::dmamux1::RGCR; +use crate::stm32::dmamux1::RGCR; use core::convert::TryInto; use core::marker::PhantomData; @@ -85,19 +85,21 @@ macro_rules! request_id { pub mod request_ids { use super::RequestId as RequestIdEnum; + use crate::private; - pub unsafe trait RequestId: Send { + pub trait RequestId: Send + private::Sealed { const REQUEST_ID: RequestIdEnum; } #[derive(Clone, Copy)] pub struct ReqNone; - unsafe impl RequestId for ReqNone { + impl private::Sealed for ReqNone {} + impl RequestId for ReqNone { const REQUEST_ID: RequestIdEnum = RequestIdEnum::None; } - pub unsafe trait RequestIdSome: RequestId {} + pub trait RequestIdSome: RequestId + private::Sealed {} $( pub struct $request_id { @@ -112,11 +114,12 @@ macro_rules! request_id { } } - unsafe impl RequestId for $request_id { + impl private::Sealed for $request_id {} + impl RequestId for $request_id { const REQUEST_ID: RequestIdEnum = RequestIdEnum::$request_id; } - unsafe impl RequestIdSome for $request_id {} + impl RequestIdSome for $request_id {} )* } }; diff --git a/src/dma/mux/request_gen.rs b/src/dma/mux/request_gen.rs index bc530957..c48b85bb 100644 --- a/src/dma/mux/request_gen.rs +++ b/src/dma/mux/request_gen.rs @@ -1,10 +1,12 @@ //! DMA Request Generator +use crate::private; + type_state! { ED, Disabled, Enabled } -pub unsafe trait GenId: Send { +pub trait GenId: Send + private::Sealed { const ID: usize; } @@ -13,7 +15,8 @@ macro_rules! gen_ids { $( pub struct $name; - unsafe impl GenId for $name { + impl private::Sealed for $name {} + impl GenId for $name { const ID:usize = $id; } )* diff --git a/src/dma/mux/shared.rs b/src/dma/mux/shared.rs index 4a8fb1f0..2fce6af4 100644 --- a/src/dma/mux/shared.rs +++ b/src/dma/mux/shared.rs @@ -1,6 +1,6 @@ //! DMA Mux shared access objects -use super::super::stm32::dmamux1::{CFR, CSR, RGCFR, RGSR}; +use crate::stm32::dmamux1::{CFR, CSR, RGCFR, RGSR}; pub struct MuxIsr { pub(in super::super) csr: &'static CSR, diff --git a/src/dma/safe_transfer.rs b/src/dma/safe_transfer.rs index 38c156cf..6c75c269 100644 --- a/src/dma/safe_transfer.rs +++ b/src/dma/safe_transfer.rs @@ -6,15 +6,17 @@ use super::stream::{ Minc, Ndt, PSize, Pa, Pinc, Pincos, TransferDirection, TransferMode, }; use super::{DMATrait, Stream}; +use crate::private; use core::convert::{TryFrom, TryInto}; use core::fmt::Debug; use core::marker::PhantomData; use core::{mem, ptr}; -pub unsafe trait TransferState: Send + Sync {} +pub trait TransferState: Send + Sync + private::Sealed {} pub struct Start; -unsafe impl TransferState for Start {} +impl private::Sealed for Start {} +impl TransferState for Start {} pub struct Ongoing where @@ -24,7 +26,14 @@ where pub(super) stream: Stream, } -unsafe impl TransferState for Ongoing +impl private::Sealed for Ongoing +where + CXX: ChannelId, + DMA: DMATrait, +{ +} + +impl TransferState for Ongoing where CXX: ChannelId, DMA: DMATrait, diff --git a/src/dma/stream.rs b/src/dma/stream.rs index bab47b24..2156f40d 100644 --- a/src/dma/stream.rs +++ b/src/dma/stream.rs @@ -1,16 +1,18 @@ //! DMA Stream -use super::stm32::dma1::{HIFCR, HISR, LIFCR, LISR}; use super::DMATrait; +use crate::private; +use crate::stm32::dma1::{HIFCR, HISR, LIFCR, LISR}; use core::marker::PhantomData; type_state! { ED, Disabled, Disabling, Enabled } -pub unsafe trait NotDisabled: ED {} -unsafe impl NotDisabled for Disabling {} -unsafe impl NotDisabled for Enabled {} +pub trait NotDisabled: ED + private::Sealed {} + +impl NotDisabled for Disabling {} +impl NotDisabled for Enabled {} type_state! { IsrState, IsrCleared, IsrUncleared diff --git a/src/lib.rs b/src/lib.rs index b84ef61f..d8e2d92c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -31,6 +31,11 @@ pub use nb; pub use nb::block; // Single core + +// TODO: Remove and uncomment below +pub use stm32h7::stm32h743 as stm32; + +/* #[cfg(any( feature = "stm32h742", feature = "stm32h743", @@ -55,6 +60,7 @@ pub use stm32h7::stm32h753v as stm32; pub use stm32h7::stm32h747cm7 as stm32; #[cfg(any(feature = "stm32h757cm7",))] pub use stm32h7::stm32h757cm7 as stm32; +*/ #[cfg(all(feature = "singlecore", feature = "dualcore"))] compile_error!("Cannot not select both singlecore and dualcore"); @@ -68,6 +74,8 @@ pub use crate::stm32 as device; #[cfg(feature = "rt")] pub use crate::stm32::interrupt; +mod private; + #[cfg(feature = "device-selected")] pub mod adc; #[cfg(feature = "device-selected")] diff --git a/src/private.rs b/src/private.rs new file mode 100644 index 00000000..8ed8be36 --- /dev/null +++ b/src/private.rs @@ -0,0 +1,19 @@ +//! Internal Module + +/// Protects public traits from being implemented outside this crate +/// +/// # Usage +/// +/// ``` +/// pub trait InternalTrait: private::Sealed {} +/// +/// pub struct Foo; +/// +/// // Enables `Foo` to implement `InternalTrait`. +/// impl private::Sealed for Foo {} +/// impl InternalTrait for Foo {} +/// ``` +pub trait Sealed {} + +impl Sealed for crate::stm32::DMA1 {} +impl Sealed for crate::stm32::DMA2 {} From 0cceb5bfe382185fd063ac2557b1306f1b2ecbc7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ad=C3=A4?= Date: Sun, 15 Mar 2020 19:03:24 +0100 Subject: [PATCH 059/103] Removed Disabling state for dma stream --- src/dma/mod.rs | 38 ++++++++++++-------------------------- src/dma/stream.rs | 8 +------- 2 files changed, 13 insertions(+), 33 deletions(-) diff --git a/src/dma/mod.rs b/src/dma/mod.rs index d97a0818..6f5a5ba3 100644 --- a/src/dma/mod.rs +++ b/src/dma/mod.rs @@ -37,12 +37,12 @@ use self::stm32::dmamux1::CCR; use self::stm32::{DMA1, DMA2, RCC}; use self::stream::{ BufferMode, CircularMode, CurrentTarget, DirectModeErrorInterrupt, - Disabled, Disabling, Enabled, Error, Event, FifoErrorInterrupt, - FifoThreshold, FlowController, HalfTransferInterrupt, IntoNum, IsrCleared, + Disabled, Enabled, Error, Event, FifoErrorInterrupt, FifoThreshold, + FlowController, HalfTransferInterrupt, IntoNum, IsrCleared, IsrState as IsrStateTrait, IsrUncleared, M0a, M1a, MBurst, MSize, Minc, - Ndt, NotDisabled, PBurst, PSize, Pa, Pinc, Pincos, PriorityLevel, - StreamIsr, TransferCompleteInterrupt, TransferDirection, - TransferErrorInterrupt, TransferMode, ED as EDTrait, + Ndt, PBurst, PSize, Pa, Pinc, Pincos, PriorityLevel, StreamIsr, + TransferCompleteInterrupt, TransferDirection, TransferErrorInterrupt, + TransferMode, ED as EDTrait, }; use crate::nb::{self, block, Error as NbError}; use crate::private; @@ -667,11 +667,10 @@ where } } -impl Stream +impl Stream where CXX: ChannelId, DMA: DMATrait, - ED: NotDisabled, IsrState: IsrStateTrait, { /// Sets the Memory-0 Address on the fly @@ -878,9 +877,11 @@ where IsrState: IsrStateTrait, { /// Disables the stream - pub fn disable(self) -> Stream { + pub fn disable(self) -> Stream { self.rb.cr.modify(|_, w| w.en().clear_bit()); + while self.rb.cr.read().en().bit_is_set() {} + self.transmute() } @@ -896,20 +897,6 @@ where } } -impl Stream -where - CXX: ChannelId, - DMA: DMATrait, - IsrState: IsrStateTrait, -{ - /// Block current thread until stream has been disabled. - pub fn await_disabled(self) -> Stream { - while self.rb.cr.read().en().bit_is_set() {} - - self.transmute() - } -} - impl Stream where CXX: ChannelId, @@ -1207,11 +1194,10 @@ where } } -impl Stream +impl Stream where CXX: ChannelId, DMA: DMATrait, - ED: NotDisabled, { /// Clears the ISR pub fn clear_isr(&self, isr: &mut StreamIsr) { @@ -1724,7 +1710,7 @@ where /// Stops the transfer, returning the stream pub fn stop(self) -> Stream { - self.state.stream.disable().await_disabled() + self.state.stream.disable() } } @@ -1932,7 +1918,7 @@ where /// Stops the transfer pub fn stop(self) -> Stream { - self.state.stream.disable().await_disabled() + self.state.stream.disable() } } diff --git a/src/dma/stream.rs b/src/dma/stream.rs index 2156f40d..f48f5ba8 100644 --- a/src/dma/stream.rs +++ b/src/dma/stream.rs @@ -1,19 +1,13 @@ //! DMA Stream use super::DMATrait; -use crate::private; use crate::stm32::dma1::{HIFCR, HISR, LIFCR, LISR}; use core::marker::PhantomData; type_state! { - ED, Disabled, Disabling, Enabled + ED, Disabled, Enabled } -pub trait NotDisabled: ED + private::Sealed {} - -impl NotDisabled for Disabling {} -impl NotDisabled for Enabled {} - type_state! { IsrState, IsrCleared, IsrUncleared } From 58019376032e924b779365e88e6e3743cb1adc47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ad=C3=A4?= Date: Sun, 15 Mar 2020 19:16:09 +0100 Subject: [PATCH 060/103] After merge cleanup --- src/dma/mod.rs | 38 ++++++++++---------------------------- 1 file changed, 10 insertions(+), 28 deletions(-) diff --git a/src/dma/mod.rs b/src/dma/mod.rs index af17400f..d93066d2 100644 --- a/src/dma/mod.rs +++ b/src/dma/mod.rs @@ -435,16 +435,12 @@ where /// Performs the volatile write to the `M0a` register fn impl_set_m0a(&mut self, m0a: M0a) { - unsafe { - self.rb.m0ar.modify(|_, w| w.m0a().bits(m0a.into())); - } + self.rb.m0ar.modify(|_, w| w.m0a().bits(m0a.into())); } /// Performs the volatile write to the `M1a` register fn impl_set_m1a(&mut self, m1a: M1a) { - unsafe { - self.rb.m0ar.modify(|_, w| w.m0a().bits(m1a.into())); - } + self.rb.m0ar.modify(|_, w| w.m0a().bits(m1a.into())); } /// Transmutes the state of `self` @@ -519,9 +515,7 @@ where /// Sets the Priority Level pub fn set_priority_level(&mut self, priority_level: PriorityLevel) { - unsafe { - self.rb.cr.modify(|_, w| w.pl().bits(priority_level.into())); - } + self.rb.cr.modify(|_, w| w.pl().bits(priority_level.into())); } /// Sets the Buffer Mode (`Direct` or `Fifo` mode) @@ -536,32 +530,24 @@ where /// Sets the Peripheral Burst pub fn set_p_burst(&mut self, p_burst: PBurst) { - unsafe { - self.rb.cr.modify(|_, w| w.pburst().bits(p_burst.into())); - } + self.rb.cr.modify(|_, w| w.pburst().bits(p_burst.into())); } /// Sets the Memory Burst pub fn set_m_burst(&mut self, m_burst: MBurst) { - unsafe { - self.rb.cr.modify(|_, w| w.mburst().bits(m_burst.into())); - } + self.rb.cr.modify(|_, w| w.mburst().bits(m_burst.into())); } /// Sets the NDT register pub fn set_ndt(&mut self, ndt: Ndt) { self.config_ndt = ndt; - unsafe { - self.rb.ndtr.modify(|_, w| w.ndt().bits(ndt.into())); - } + self.rb.ndtr.modify(|_, w| w.ndt().bits(ndt.into())); } /// Sets the Peripheral Address pub fn set_pa(&mut self, pa: Pa) { - unsafe { - self.rb.par.modify(|_, w| w.pa().bits(pa.into())); - } + self.rb.par.modify(|_, w| w.pa().bits(pa.into())); } /// Sets the Memory-0 Address @@ -576,11 +562,9 @@ where /// Sets the Fifo Threshold pub fn set_fifo_threshold(&mut self, fifo_threshold: FifoThreshold) { - unsafe { - self.rb - .fcr - .modify(|_, w| w.fth().bits(fifo_threshold.into())); - } + self.rb + .fcr + .modify(|_, w| w.fth().bits(fifo_threshold.into())); } /// Sets the Transfer Mode @@ -1496,8 +1480,6 @@ where /// Returns the Sync Overrun flag pub fn is_sync_overrun(&self, mux_isr: &MuxIsr) -> bool { - let mask: u16 = 1 << self.id() as u16; - mux_isr.csr.read().sof0().bit_is_set() } From 42600dd820bf4567b7cabdf0c6f06d79a8c9b1c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ad=C3=A4?= Date: Mon, 16 Mar 2020 11:42:28 +0100 Subject: [PATCH 061/103] minor changes --- src/dma/mod.rs | 8 +++----- src/private.rs | 4 ++-- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/src/dma/mod.rs b/src/dma/mod.rs index d93066d2..fdb08b1f 100644 --- a/src/dma/mod.rs +++ b/src/dma/mod.rs @@ -32,9 +32,6 @@ use self::safe_transfer::{ MemoryBufferStatic, Ongoing, Payload, PayloadPort, PeripheralBufferStatic, PointerPort, Start, TransferState, }; -use self::stm32::dma1::ST; -use self::stm32::dmamux1::CCR; -use self::stm32::{DMA1, DMA2, RCC}; use self::stream::{ BufferMode, CircularMode, CurrentTarget, DirectModeErrorInterrupt, Disabled, Enabled, Error, Event, FifoErrorInterrupt, FifoThreshold, @@ -47,11 +44,12 @@ use self::stream::{ use crate::nb::{self, block, Error as NbError}; use crate::private; use crate::rcc::Ccdr; +use crate::stm32::dma1::ST; +use crate::stm32::dmamux1::CCR; +use crate::stm32::{DMA1, DMA2, RCC}; use core::convert::{Infallible, TryFrom, TryInto}; use core::marker::PhantomData; use core::mem; -// TODO: Remove when merging. Necessary for me as I'm using CLion with rust plugin, which doesn't support conditionally imported items yet. -use stm32h7::stm32h743 as stm32; use stm32h7::stm32h743::DMAMUX1; /// Marker Trait for DMA peripherals diff --git a/src/private.rs b/src/private.rs index 8ed8be36..0aac03aa 100644 --- a/src/private.rs +++ b/src/private.rs @@ -5,12 +5,12 @@ /// # Usage /// /// ``` -/// pub trait InternalTrait: private::Sealed {} +/// pub trait InternalTrait: Sealed {} /// /// pub struct Foo; /// /// // Enables `Foo` to implement `InternalTrait`. -/// impl private::Sealed for Foo {} +/// impl Sealed for Foo {} /// impl InternalTrait for Foo {} /// ``` pub trait Sealed {} From 3389b3030c2863ceebac945d616fbe707b1e3e57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ad=C3=A4?= Date: Thu, 19 Mar 2020 14:02:00 +0100 Subject: [PATCH 062/103] begun implementation of config builder --- src/dma/stream.rs | 58 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/src/dma/stream.rs b/src/dma/stream.rs index f48f5ba8..d856ac46 100644 --- a/src/dma/stream.rs +++ b/src/dma/stream.rs @@ -3,6 +3,7 @@ use super::DMATrait; use crate::stm32::dma1::{HIFCR, HISR, LIFCR, LISR}; use core::marker::PhantomData; +use crate::private; type_state! { ED, Disabled, Enabled @@ -248,3 +249,60 @@ pub struct Error { pub event: Option, pub crashed: bool, } + +pub struct ConfigBuilder +where + TransferDir: TransferDirectionTrait, +{ + _transfer_dir: PhantomData, +} + +pub trait TransferDirectionTrait: private::Sealed { + fn transfer_direction() -> TransferDirection; +} + +pub struct P2M; +pub struct M2P; +pub struct M2M; + +impl private::Sealed for P2M {} +impl private::Sealed for M2P {} +impl private::Sealed for M2M {} + +impl TransferDirectionTrait for P2M { + fn transfer_direction() -> TransferDirection { + TransferDirection::P2M + } +} + +impl TransferDirectionTrait for M2P { + fn transfer_direction() -> TransferDirection { + TransferDirection::M2P + } +} + +impl TransferDirectionTrait for M2M { + fn transfer_direction() -> TransferDirection { + TransferDirection::M2M + } +} + +pub trait NotM2M: private::Sealed {} +impl NotM2M for P2M {} +impl NotM2M for M2P {} + +pub struct NotConfigured; + +macro_rules! panic_not_configured { + ($item:tt) => { + panic!("{} is not configured.", $item); + } +} + +impl private::Sealed for NotConfigured {} + +impl TransferDirectionTrait for NotConfigured { + fn transfer_direction() -> TransferDirection { + panic_not_configured!("Transfer Direction"); + } +} From d732c0a888c6d8b03912a9353591a2c03957fa78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ad=C3=A4?= Date: Fri, 20 Mar 2020 15:24:46 +0100 Subject: [PATCH 063/103] update --- src/dma/mod.rs | 1 + src/dma/stream.rs | 47 ++++++++++++++++++++++++++++++++++++++++------- src/dma/utils.rs | 9 +++++++++ 3 files changed, 50 insertions(+), 7 deletions(-) create mode 100644 src/dma/utils.rs diff --git a/src/dma/mod.rs b/src/dma/mod.rs index fdb08b1f..2328cf55 100644 --- a/src/dma/mod.rs +++ b/src/dma/mod.rs @@ -5,6 +5,7 @@ #[macro_use] mod macros; +mod utils; pub mod channel; pub mod mux; pub mod safe_transfer; diff --git a/src/dma/stream.rs b/src/dma/stream.rs index d856ac46..923e3a7e 100644 --- a/src/dma/stream.rs +++ b/src/dma/stream.rs @@ -3,6 +3,8 @@ use super::DMATrait; use crate::stm32::dma1::{HIFCR, HISR, LIFCR, LISR}; use core::marker::PhantomData; +use core::fmt; +use super::utils::DefaultTraits; use crate::private; type_state! { @@ -250,19 +252,27 @@ pub struct Error { pub crashed: bool, } +#[derive(Debug, PartialEq, Eq, Clone, Copy)] pub struct ConfigBuilder where TransferDir: TransferDirectionTrait, { - _transfer_dir: PhantomData, + transfer_dir: TransferDir, } -pub trait TransferDirectionTrait: private::Sealed { +pub trait TransferDirectionTrait: DefaultTraits + private::Sealed { fn transfer_direction() -> TransferDirection; } -pub struct P2M; -pub struct M2P; +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +pub struct P2M { + conf: NotM2MConf, +} +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +pub struct M2P { + conf: NotM2MConf, +} +#[derive(Debug, PartialEq, Eq, Clone, Copy)] pub struct M2M; impl private::Sealed for P2M {} @@ -287,10 +297,33 @@ impl TransferDirectionTrait for M2M { } } -pub trait NotM2M: private::Sealed {} -impl NotM2M for P2M {} -impl NotM2M for M2P {} +pub trait NotM2M: DefaultTraits + private::Sealed { + fn not_m2m_conf(self) -> NotM2MConf; +} + +impl NotM2M for P2M { + fn not_m2m_conf(self) -> NotM2MConf { + self.conf + } +} +impl NotM2M for M2P { + fn not_m2m_conf(self) -> NotM2MConf { + self.conf + } +} + +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +pub struct NotM2MConf { + +} + +impl private::Sealed for NotM2MConf {} +pub trait TransferModeTrait: private::Sealed { + fn transfer_mode() -> TransferMode; +} + +#[derive(Debug, PartialEq, Eq, Clone, Copy)] pub struct NotConfigured; macro_rules! panic_not_configured { diff --git a/src/dma/utils.rs b/src/dma/utils.rs new file mode 100644 index 00000000..abf79da7 --- /dev/null +++ b/src/dma/utils.rs @@ -0,0 +1,9 @@ +use core::fmt; +use crate::private; + +pub trait DefaultTraits: fmt::Debug + PartialEq + Eq + Clone + Copy {} + +impl DefaultTraits for T +where + T: fmt::Debug + PartialEq + Eq + Clone + Copy + private::Sealed, +{} \ No newline at end of file From abd4b02017b9bdc43225a043b72ec7fe9fa767b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ad=C3=A4?= Date: Fri, 20 Mar 2020 16:53:15 +0100 Subject: [PATCH 064/103] Implemented config type states --- src/dma/mod.rs | 2 +- src/dma/stream.rs | 217 ++++++++++++++++++++++++++++++++++++---------- src/dma/utils.rs | 7 +- 3 files changed, 176 insertions(+), 50 deletions(-) diff --git a/src/dma/mod.rs b/src/dma/mod.rs index 2328cf55..a3663f76 100644 --- a/src/dma/mod.rs +++ b/src/dma/mod.rs @@ -5,11 +5,11 @@ #[macro_use] mod macros; -mod utils; pub mod channel; pub mod mux; pub mod safe_transfer; pub mod stream; +mod utils; use self::channel::{ ChannelId, C0, C1, C10, C11, C12, C13, C14, C15, C2, C3, C4, C5, C6, C7, diff --git a/src/dma/stream.rs b/src/dma/stream.rs index 923e3a7e..1a712058 100644 --- a/src/dma/stream.rs +++ b/src/dma/stream.rs @@ -1,11 +1,11 @@ //! DMA Stream +use super::utils::DefaultTraits; use super::DMATrait; +use crate::private; use crate::stm32::dma1::{HIFCR, HISR, LIFCR, LISR}; -use core::marker::PhantomData; use core::fmt; -use super::utils::DefaultTraits; -use crate::private; +use core::marker::PhantomData; type_state! { ED, Disabled, Enabled @@ -252,26 +252,65 @@ pub struct Error { pub crashed: bool, } +///////////////////////////////////////////////////////////////////////// +// CONFIG BUILDER +///////////////////////////////////////////////////////////////////////// + #[derive(Debug, PartialEq, Eq, Clone, Copy)] -pub struct ConfigBuilder +pub struct ConfigBuilder< + C_TransferDir, + C_TransferMode, + C_FlowController, + C_CircularMode, + C_BufferMode, +> where + C_TransferDir: TransferDirectionTrait, + C_TransferMode: TransferModeTrait, + C_FlowController: FlowControllerTrait, + C_CircularMode: CircularModeTrait, + C_BufferMode: BufferModeTrait, +{ + transfer_mode: C_TransferMode, + buffer_mode: C_BufferMode, + _phantom: PhantomData<(C_TransferDir, C_FlowController, C_CircularMode)>, +} + +// Generic Impl +impl< + C_TransferDir, + C_TransferMode, + C_FlowController, + C_CircularMode, + C_BufferMode, + > + ConfigBuilder< + C_TransferDir, + C_TransferMode, + C_FlowController, + C_CircularMode, + C_BufferMode, + > where - TransferDir: TransferDirectionTrait, + C_TransferDir: TransferDirectionTrait, + C_TransferMode: TransferModeTrait, + C_FlowController: FlowControllerTrait, + C_CircularMode: CircularModeTrait, + C_BufferMode: BufferModeTrait, { - transfer_dir: TransferDir, + // IMPL } +///////////////////////////////////////////////////////////////////////// +// # TRANSFER DIRECTION +///////////////////////////////////////////////////////////////////////// pub trait TransferDirectionTrait: DefaultTraits + private::Sealed { - fn transfer_direction() -> TransferDirection; + const TRANSFER_DIRECTION: Option; } #[derive(Debug, PartialEq, Eq, Clone, Copy)] -pub struct P2M { - conf: NotM2MConf, -} +pub struct P2M {} #[derive(Debug, PartialEq, Eq, Clone, Copy)] -pub struct M2P { - conf: NotM2MConf, -} +pub struct M2P {} #[derive(Debug, PartialEq, Eq, Clone, Copy)] pub struct M2M; @@ -280,62 +319,152 @@ impl private::Sealed for M2P {} impl private::Sealed for M2M {} impl TransferDirectionTrait for P2M { - fn transfer_direction() -> TransferDirection { - TransferDirection::P2M - } + const TRANSFER_DIRECTION: Option = + Some(TransferDirection::P2M); } impl TransferDirectionTrait for M2P { - fn transfer_direction() -> TransferDirection { - TransferDirection::M2P - } + const TRANSFER_DIRECTION: Option = + Some(TransferDirection::M2P); } impl TransferDirectionTrait for M2M { - fn transfer_direction() -> TransferDirection { - TransferDirection::M2M - } + const TRANSFER_DIRECTION: Option = + Some(TransferDirection::M2M); +} + +pub trait NotM2M: DefaultTraits + private::Sealed {} + +impl NotM2M for P2M {} +impl NotM2M for M2P {} + +///////////////////////////////////////////////////////////////////////// +// # TRANSFER MODE +///////////////////////////////////////////////////////////////////////// + +pub trait TransferModeTrait: DefaultTraits + private::Sealed { + const TRANSFER_MODE: Option; } -pub trait NotM2M: DefaultTraits + private::Sealed { - fn not_m2m_conf(self) -> NotM2MConf; +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +pub struct Direct; + +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +pub struct Fifo { + fifo_threshold: Option, + p_burst: Option, + m_burst: Option, + m_size: Option, } -impl NotM2M for P2M { - fn not_m2m_conf(self) -> NotM2MConf { - self.conf - } +impl private::Sealed for Direct {} +impl private::Sealed for Fifo {} + +impl TransferModeTrait for Direct { + const TRANSFER_MODE: Option = Some(TransferMode::Direct); } -impl NotM2M for M2P { - fn not_m2m_conf(self) -> NotM2MConf { - self.conf - } +impl TransferModeTrait for Fifo { + const TRANSFER_MODE: Option = Some(TransferMode::Fifo); +} + +///////////////////////////////////////////////////////////////////////// +// # FLOW CONTROLLER +///////////////////////////////////////////////////////////////////////// + +pub trait FlowControllerTrait: DefaultTraits + private::Sealed { + const FLOW_CONTROLLER: Option; } #[derive(Debug, PartialEq, Eq, Clone, Copy)] -pub struct NotM2MConf { +pub struct Dma; +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +pub struct Peripheral; + +impl private::Sealed for Dma {} +impl private::Sealed for Peripheral {} +impl FlowControllerTrait for Dma { + const FLOW_CONTROLLER: Option = Some(FlowController::Dma); +} +impl FlowControllerTrait for Peripheral { + const FLOW_CONTROLLER: Option = + Some(FlowController::Peripheral); } -impl private::Sealed for NotM2MConf {} +///////////////////////////////////////////////////////////////////////// +// # CIRCULAR MODE +///////////////////////////////////////////////////////////////////////// -pub trait TransferModeTrait: private::Sealed { - fn transfer_mode() -> TransferMode; +pub trait CircularModeTrait: DefaultTraits + private::Sealed { + const CIRCULAR_MODE: Option; } #[derive(Debug, PartialEq, Eq, Clone, Copy)] -pub struct NotConfigured; +pub struct Circular; +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +pub struct NotCircular; -macro_rules! panic_not_configured { - ($item:tt) => { - panic!("{} is not configured.", $item); - } +impl private::Sealed for Circular {} +impl private::Sealed for NotCircular {} + +impl CircularModeTrait for Circular { + const CIRCULAR_MODE: Option = Some(CircularMode::Enabled); +} +impl CircularModeTrait for NotCircular { + const CIRCULAR_MODE: Option = Some(CircularMode::Disabled); +} + +///////////////////////////////////////////////////////////////////////// +// # BUFFER MODE +///////////////////////////////////////////////////////////////////////// + +pub trait BufferModeTrait: DefaultTraits + private::Sealed { + const BUFFER_MODE: Option; } +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +pub struct RegularBuffer; +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +pub struct DoubleBuffer { + current_target: Option, + m1a: Option, +} + +impl private::Sealed for RegularBuffer {} +impl private::Sealed for DoubleBuffer {} + +impl BufferModeTrait for RegularBuffer { + const BUFFER_MODE: Option = Some(BufferMode::Regular); +} +impl BufferModeTrait for DoubleBuffer { + const BUFFER_MODE: Option = Some(BufferMode::DoubleBuffer); +} + +///////////////////////////////////////////////////////////////////////// +// # NOT CONFIGURED +///////////////////////////////////////////////////////////////////////// + +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +pub struct NotConfigured; + impl private::Sealed for NotConfigured {} impl TransferDirectionTrait for NotConfigured { - fn transfer_direction() -> TransferDirection { - panic_not_configured!("Transfer Direction"); - } + const TRANSFER_DIRECTION: Option = None; +} + +impl TransferModeTrait for NotConfigured { + const TRANSFER_MODE: Option = None; +} + +impl FlowControllerTrait for NotConfigured { + const FLOW_CONTROLLER: Option = None; +} + +impl CircularModeTrait for NotConfigured { + const CIRCULAR_MODE: Option = None; +} + +impl BufferModeTrait for NotConfigured { + const BUFFER_MODE: Option = None; } diff --git a/src/dma/utils.rs b/src/dma/utils.rs index abf79da7..6fcb9e2d 100644 --- a/src/dma/utils.rs +++ b/src/dma/utils.rs @@ -1,9 +1,6 @@ -use core::fmt; use crate::private; +use core::fmt; pub trait DefaultTraits: fmt::Debug + PartialEq + Eq + Clone + Copy {} -impl DefaultTraits for T -where - T: fmt::Debug + PartialEq + Eq + Clone + Copy + private::Sealed, -{} \ No newline at end of file +impl DefaultTraits for T where T: fmt::Debug + PartialEq + Eq + Clone + Copy {} From a67f86d708bb62517b6a0d7221b3dc38f53aa72b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ad=C3=A4?= Date: Fri, 20 Mar 2020 18:56:13 +0100 Subject: [PATCH 065/103] update --- src/dma/stream.rs | 222 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 220 insertions(+), 2 deletions(-) diff --git a/src/dma/stream.rs b/src/dma/stream.rs index 1a712058..7d77edf1 100644 --- a/src/dma/stream.rs +++ b/src/dma/stream.rs @@ -256,6 +256,10 @@ pub struct Error { // CONFIG BUILDER ///////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +// # CONFIG BUILDER +///////////////////////////////////////////////////////////////////////// + #[derive(Debug, PartialEq, Eq, Clone, Copy)] pub struct ConfigBuilder< C_TransferDir, @@ -270,12 +274,27 @@ pub struct ConfigBuilder< C_CircularMode: CircularModeTrait, C_BufferMode: BufferModeTrait, { + tc_intrpt: Option, + ht_intrpt: Option, + te_intrpt: Option, + dme_intrpt: Option, + fe_intrpt: Option, + pinc: Option, + minc: Option, + priority: Option, + p_size: Option, + ndt: Option, + pa: Option, + m0a: Option, transfer_mode: C_TransferMode, buffer_mode: C_BufferMode, _phantom: PhantomData<(C_TransferDir, C_FlowController, C_CircularMode)>, } -// Generic Impl +///////////////////////////////////////////////////////////////////////// +// ## GENERIC IMPLEMENTATION +///////////////////////////////////////////////////////////////////////// + impl< C_TransferDir, C_TransferMode, @@ -297,12 +316,211 @@ where C_CircularMode: CircularModeTrait, C_BufferMode: BufferModeTrait, { - // IMPL + pub fn transfer_complete_interrupt( + mut self, + tc_intrpt: TransferCompleteInterrupt, + ) -> Self { + self.tc_intrpt = Some(tc_intrpt); + + self + } + + pub fn half_transfer_interrupt( + mut self, + ht_intrpt: HalfTransferInterrupt, + ) -> Self { + self.ht_intrpt = Some(ht_intrpt); + + self + } + + pub fn transfer_error_interrupt( + mut self, + te_intrpt: TransferErrorInterrupt, + ) -> Self { + self.te_intrpt = Some(te_intrpt); + + self + } + + pub fn direct_mode_error_interrupt( + mut self, + dme_intrpt: DirectModeErrorInterrupt, + ) -> Self { + self.dme_intrpt = Some(dme_intrpt); + + self + } + + pub fn fifo_error_interrupt( + mut self, + fe_intrpt: FifoErrorInterrupt, + ) -> Self { + self.fe_intrpt = Some(fe_intrpt); + + self + } + + pub fn pinc(mut self, pinc: Pinc) -> Self { + self.pinc = Some(pinc); + + self + } + + pub fn minc(mut self, minc: Minc) -> Self { + self.minc = Some(minc); + + self + } + + pub fn priority_level(mut self, priority: PriorityLevel) -> Self { + self.priority = Some(priority); + + self + } + + pub fn p_size(mut self, p_size: PSize) -> Self { + self.p_size = Some(p_size); + + self + } + + pub fn ndt(mut self, ndt: Ndt) -> Self { + self.ndt = Some(ndt); + + self + } + + pub fn pa(mut self, pa: Pa) -> Self { + self.pa = Some(pa); + + self + } + + pub fn m0a(mut self, m0a: M0a) -> Self { + self.m0a = Some(m0a); + + self + } + + fn transmute( + self, + ) -> ConfigBuilder< + NewC_TransferDir, + C_TransferMode, + NewC_FlowController, + NewC_CircularMode, + C_BufferMode, + > + where + NewC_TransferDir: TransferDirectionTrait, + NewC_FlowController: FlowControllerTrait, + NewC_CircularMode: CircularModeTrait, + { + ConfigBuilder { + tc_intrpt: self.tc_intrpt, + ht_intrpt: self.ht_intrpt, + te_intrpt: self.te_intrpt, + dme_intrpt: self.dme_intrpt, + fe_intrpt: self.fe_intrpt, + pinc: self.pinc, + minc: self.minc, + priority: self.priority, + p_size: self.p_size, + ndt: self.ndt, + pa: self.pa, + m0a: self.m0a, + transfer_mode: self.transfer_mode, + buffer_mode: self.buffer_mode, + _phantom: PhantomData, + } + } + + fn transmute_new_transfer_mode< + NewC_TransferDir, + NewC_TransferMode, + NewC_FlowController, + NewC_CircularMode, + >( + self, + transfer_mode: NewC_TransferMode, + ) -> ConfigBuilder< + NewC_TransferDir, + NewC_TransferMode, + NewC_FlowController, + NewC_CircularMode, + C_BufferMode, + > + where + NewC_TransferDir: TransferDirectionTrait, + NewC_TransferMode: TransferModeTrait, + NewC_FlowController: FlowControllerTrait, + NewC_CircularMode: CircularModeTrait, + { + ConfigBuilder { + tc_intrpt: self.tc_intrpt, + ht_intrpt: self.ht_intrpt, + te_intrpt: self.te_intrpt, + dme_intrpt: self.dme_intrpt, + fe_intrpt: self.fe_intrpt, + pinc: self.pinc, + minc: self.minc, + priority: self.priority, + p_size: self.p_size, + ndt: self.ndt, + pa: self.pa, + m0a: self.m0a, + buffer_mode: self.buffer_mode, + _phantom: PhantomData, + transfer_mode, + } + } + + fn transmute_new_buffer_mode< + NewC_TransferDir, + NewC_FlowController, + NewC_CircularMode, + NewC_BufferMode, + >( + self, + buffer_mode: NewC_TransferMode, + ) -> ConfigBuilder< + NewC_TransferDir, + C_TransferMode, + NewC_FlowController, + NewC_CircularMode, + NewC_BufferMode, + > + where + NewC_TransferDir: TransferDirectionTrait, + NewC_FlowController: FlowControllerTrait, + NewC_CircularMode: CircularModeTrait, + NewC_BufferMode: BufferModeTrait, + { + ConfigBuilder { + tc_intrpt: self.tc_intrpt, + ht_intrpt: self.ht_intrpt, + te_intrpt: self.te_intrpt, + dme_intrpt: self.dme_intrpt, + fe_intrpt: self.fe_intrpt, + pinc: self.pinc, + minc: self.minc, + priority: self.priority, + p_size: self.p_size, + ndt: self.ndt, + pa: self.pa, + m0a: self.m0a, + transfer_mode: self.transfer_mode, + _phantom: PhantomData, + buffer_mode, + } + } } ///////////////////////////////////////////////////////////////////////// // # TRANSFER DIRECTION ///////////////////////////////////////////////////////////////////////// + pub trait TransferDirectionTrait: DefaultTraits + private::Sealed { const TRANSFER_DIRECTION: Option; } From abe452113cc384c0271c85f239d70b2468f3c9a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ad=C3=A4?= Date: Sun, 22 Mar 2020 13:53:59 +0100 Subject: [PATCH 066/103] update --- src/dma/stream.rs | 125 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 125 insertions(+) diff --git a/src/dma/stream.rs b/src/dma/stream.rs index 7d77edf1..7ff54e55 100644 --- a/src/dma/stream.rs +++ b/src/dma/stream.rs @@ -252,6 +252,131 @@ pub struct Error { pub crashed: bool, } +///////////////////////////////////////////////////////////////////////// +// CONFIG +///////////////////////////////////////////////////////////////////////// + +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +pub struct Config { + pub transfer_complete_interrupt: TransferCompleteInterrupt, + pub half_transfer_interrupt: HalfTransferInterrupt, + pub transfer_error_interrupt: TransferErrorInterrupt, + pub direct_mode_error_interrupt: DirectModeErrorInterrupt, + pub fifo_error_interrupt: FifoErrorInterrupt, + pub pinc: Pinc, + pub minc: Minc, + pub priority_level: PriorityLevel, + pub p_size: PSize, + pub ndt: Ndt, + pub pa: Pa, + pub m0a: M0a, +} + +///////////////////////////////////////////////////////////////////////// +// # TRANSFER DIRECTION CONFIG +///////////////////////////////////////////////////////////////////////// + +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +pub enum TransferDirectionConf { + M2M(FifoConf), + NotM2M(NotM2MConf), +} + +///////////////////////////////////////////////////////////////////////// +// # NOT-M2M CONFIG +///////////////////////////////////////////////////////////////////////// + +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +pub struct NotM2MConf { + pub transfer_dir: TransferDirectionNotM2M, + pub transfer_mode: TransferModeConf, + pub flow: FlowControllerConf, +} + +///////////////////////////////////////////////////////////////////////// +// # TRANSFER DIRECTION NOT M2M +///////////////////////////////////////////////////////////////////////// + +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +pub enum TransferDirectionNotM2M { + P2M, + M2P, +} + +///////////////////////////////////////////////////////////////////////// +// # TRANSFER MODE CONFIG +///////////////////////////////////////////////////////////////////////// + +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +pub enum TransferModeConf { + Direct, + Fifo(FifoConf), +} + +///////////////////////////////////////////////////////////////////////// +// # FLOW CONTROLLER CONFIG +///////////////////////////////////////////////////////////////////////// + +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +pub enum FlowControllerConf { + Dma(CircularModeConf), + Peripheral, +} + +///////////////////////////////////////////////////////////////////////// +// # FIFO CONFIG +///////////////////////////////////////////////////////////////////////// + +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +pub struct FifoConf { + pub fifo_threshold: FifoThreshold, + pub p_burst: PBurstConf, + pub m_burst: MBurst, + pub m_size: MSize, +} + +///////////////////////////////////////////////////////////////////////// +// # PBURST CONFIG +///////////////////////////////////////////////////////////////////////// + +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +pub enum PBurstConf { + Single(Pincos), + Incr4, + Incr8, + Incr16, +} + +///////////////////////////////////////////////////////////////////////// +// # CIRCULAR CONFIG +///////////////////////////////////////////////////////////////////////// + +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +pub enum CircularModeConf { + Disabled, + Enabled(BufferModeConf), +} + +///////////////////////////////////////////////////////////////////////// +// # BUFFER MODE CONFIG +///////////////////////////////////////////////////////////////////////// + +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +pub enum BufferModeConf { + Regular, + DoubleBuffer(DoubleBufferConf), +} + +///////////////////////////////////////////////////////////////////////// +// # DOUBLE BUFFER CONFIG +///////////////////////////////////////////////////////////////////////// + +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +pub struct DoubleBufferConf { + pub current_target: CurrentTarget, + pub m1a: M1a, +} + ///////////////////////////////////////////////////////////////////////// // CONFIG BUILDER ///////////////////////////////////////////////////////////////////////// From 5269529e24785fa9ed9ba9d43764d3c2db8eb0b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ad=C3=A4?= Date: Tue, 24 Mar 2020 01:53:29 +0100 Subject: [PATCH 067/103] update --- src/dma/stream.rs | 278 +++++++++++++++++++++++++++++++++++++++++++++- src/dma/utils.rs | 1 - 2 files changed, 273 insertions(+), 6 deletions(-) diff --git a/src/dma/stream.rs b/src/dma/stream.rs index 7ff54e55..6b9183ca 100644 --- a/src/dma/stream.rs +++ b/src/dma/stream.rs @@ -4,7 +4,6 @@ use super::utils::DefaultTraits; use super::DMATrait; use crate::private; use crate::stm32::dma1::{HIFCR, HISR, LIFCR, LISR}; -use core::fmt; use core::marker::PhantomData; type_state! { @@ -420,6 +419,36 @@ pub struct ConfigBuilder< // ## GENERIC IMPLEMENTATION ///////////////////////////////////////////////////////////////////////// +impl + ConfigBuilder< + NotConfigured, + NotConfigured, + NotConfigured, + NotConfigured, + NotConfigured, + > +{ + pub fn new() -> Self { + Self { + tc_intrpt: None, + ht_intrpt: None, + te_intrpt: None, + dme_intrpt: None, + fe_intrpt: None, + pinc: None, + minc: None, + priority: None, + p_size: None, + ndt: None, + pa: None, + m0a: None, + transfer_mode: NotConfigured, + buffer_mode: NotConfigured, + _phantom: PhantomData, + } + } +} + impl< C_TransferDir, C_TransferMode, @@ -528,6 +557,66 @@ where self } + pub fn transfer_dir_p2m( + self, + ) -> ConfigBuilder< + P2M, + C_TransferMode, + C_FlowController, + C_CircularMode, + C_BufferMode, + > { + self.transmute() + } + + pub fn transfer_dir_m2p( + self, + ) -> ConfigBuilder< + M2P, + C_TransferMode, + C_FlowController, + C_CircularMode, + C_BufferMode, + > { + self.transmute() + } + + pub fn transfer_mode_fifo( + self, + ) -> ConfigBuilder< + C_TransferDir, + Fifo, + C_FlowController, + C_CircularMode, + C_BufferMode, + > { + self.transmute_new_transfer_mode(Fifo::default()) + } + + pub fn flow_controller_dma( + self, + ) -> ConfigBuilder< + C_TransferDir, + C_TransferMode, + Dma, + C_CircularMode, + C_BufferMode, + > { + self.transmute() + } + + pub fn buffer_mode_regular( + self, + ) -> ConfigBuilder< + C_TransferDir, + C_TransferMode, + C_FlowController, + C_CircularMode, + RegularBuffer, + > { + self.transmute_new_buffer_mode(RegularBuffer) + } + fn transmute( self, ) -> ConfigBuilder< @@ -608,7 +697,7 @@ where NewC_BufferMode, >( self, - buffer_mode: NewC_TransferMode, + buffer_mode: NewC_BufferMode, ) -> ConfigBuilder< NewC_TransferDir, C_TransferMode, @@ -642,6 +731,153 @@ where } } +impl + ConfigBuilder +where + C_TransferDir: TransferDirectionTrait, + C_Fifo: TransferModeTrait + Into, + C_Dma: FlowControllerTrait + Into, + C_NotCircular: CircularModeTrait + Into, + C_RegularBuffer: BufferModeTrait + Into, +{ + pub fn transfer_dir_m2m( + self, + ) -> ConfigBuilder { + let builder: ConfigBuilder = + self.transmute_new_transfer_mode(Fifo::default()); + + builder.transmute_new_buffer_mode(RegularBuffer) + } +} + +impl< + C_NotM2M, + C_TransferMode, + C_FlowController, + C_CircularMode, + C_BufferMode, + > + ConfigBuilder< + C_NotM2M, + C_TransferMode, + C_FlowController, + C_CircularMode, + C_BufferMode, + > +where + C_NotM2M: NotM2M, + C_TransferMode: TransferModeTrait, + C_FlowController: FlowControllerTrait, + C_CircularMode: CircularModeTrait, + C_BufferMode: BufferModeTrait, +{ + pub fn transfer_mode_direct( + self, + ) -> ConfigBuilder< + C_NotM2M, + Direct, + C_FlowController, + C_CircularMode, + C_BufferMode, + > { + self.transmute_new_transfer_mode(Direct) + } + + pub fn flow_controller_peripheral( + self, + ) -> ConfigBuilder< + C_NotM2M, + C_TransferMode, + Peripheral, + C_CircularMode, + C_BufferMode, + > { + self.transmute() + } +} + +impl< + C_TransferDir, + C_TransferMode, + C_FlowController, + C_CircularMode, + C_RegularBuffer, + > + ConfigBuilder< + C_TransferDir, + C_TransferMode, + C_FlowController, + C_CircularMode, + C_RegularBuffer, + > +where + C_TransferDir: TransferDirectionTrait, + C_TransferMode: TransferModeTrait, + C_FlowController: FlowControllerTrait, + C_CircularMode: CircularModeTrait, + C_RegularBuffer: BufferModeTrait + Into, +{ + pub fn circular_mode_disabled( + self, + ) -> ConfigBuilder< + C_TransferDir, + C_TransferMode, + C_FlowController, + NotCircular, + RegularBuffer, + > { + self.transmute_new_buffer_mode(RegularBuffer) + } +} + +impl + ConfigBuilder +where + C_NotM2M: NotM2M, + C_TransferMode: TransferModeTrait, + C_Dma: FlowControllerTrait + Into, + C_CircularMode: CircularModeTrait, + C_BufferMode: BufferModeTrait, +{ + pub fn circular_mode_enabled( + self, + ) -> ConfigBuilder + { + self.transmute() + } +} + +impl + ConfigBuilder +where + C_NotM2M: NotM2M, + C_TransferMode: TransferModeTrait, + C_Dma: FlowControllerTrait + Into, + C_Circular: CircularModeTrait + Into, + C_BufferMode: BufferModeTrait, +{ + pub fn buffer_mode_double_buffer( + self, + ) -> ConfigBuilder + { + self.transmute_new_buffer_mode(DoubleBuffer::default()) + } +} + +impl Default + for ConfigBuilder< + NotConfigured, + NotConfigured, + NotConfigured, + NotConfigured, + NotConfigured, + > +{ + fn default() -> Self { + Self::new() + } +} + ///////////////////////////////////////////////////////////////////////// // # TRANSFER DIRECTION ///////////////////////////////////////////////////////////////////////// @@ -676,7 +912,7 @@ impl TransferDirectionTrait for M2M { Some(TransferDirection::M2M); } -pub trait NotM2M: DefaultTraits + private::Sealed {} +pub trait NotM2M: TransferDirectionTrait {} impl NotM2M for P2M {} impl NotM2M for M2P {} @@ -692,7 +928,7 @@ pub trait TransferModeTrait: DefaultTraits + private::Sealed { #[derive(Debug, PartialEq, Eq, Clone, Copy)] pub struct Direct; -#[derive(Debug, PartialEq, Eq, Clone, Copy)] +#[derive(Default, Debug, PartialEq, Eq, Clone, Copy)] pub struct Fifo { fifo_threshold: Option, p_burst: Option, @@ -767,7 +1003,7 @@ pub trait BufferModeTrait: DefaultTraits + private::Sealed { #[derive(Debug, PartialEq, Eq, Clone, Copy)] pub struct RegularBuffer; -#[derive(Debug, PartialEq, Eq, Clone, Copy)] +#[derive(Default, Debug, PartialEq, Eq, Clone, Copy)] pub struct DoubleBuffer { current_target: Option, m1a: Option, @@ -811,3 +1047,35 @@ impl CircularModeTrait for NotConfigured { impl BufferModeTrait for NotConfigured { const BUFFER_MODE: Option = None; } + +impl NotM2M for NotConfigured {} + +impl From for Fifo { + fn from(_: NotConfigured) -> Self { + Self::default() + } +} + +impl From for Dma { + fn from(_: NotConfigured) -> Self { + Self + } +} + +impl From for NotCircular { + fn from(_: NotConfigured) -> Self { + Self + } +} + +impl From for Circular { + fn from(_: NotConfigured) -> Self { + Self + } +} + +impl From for RegularBuffer { + fn from(_: NotConfigured) -> Self { + Self + } +} diff --git a/src/dma/utils.rs b/src/dma/utils.rs index 6fcb9e2d..bddcf42b 100644 --- a/src/dma/utils.rs +++ b/src/dma/utils.rs @@ -1,4 +1,3 @@ -use crate::private; use core::fmt; pub trait DefaultTraits: fmt::Debug + PartialEq + Eq + Clone + Copy {} From aca7179a17dce53cb1f4702472aadb804cfee7b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ad=C3=A4?= Date: Tue, 24 Mar 2020 15:43:41 +0100 Subject: [PATCH 068/103] update --- src/dma/stream.rs | 115 +++++++++++++++++++++++++++++++++------------- 1 file changed, 82 insertions(+), 33 deletions(-) diff --git a/src/dma/stream.rs b/src/dma/stream.rs index 6b9183ca..2bf86e0f 100644 --- a/src/dma/stream.rs +++ b/src/dma/stream.rs @@ -590,7 +590,7 @@ where C_CircularMode, C_BufferMode, > { - self.transmute_new_transfer_mode(Fifo::default()) + self.transmute_transfer_mode(Fifo::default()) } pub fn flow_controller_dma( @@ -614,7 +614,7 @@ where C_CircularMode, RegularBuffer, > { - self.transmute_new_buffer_mode(RegularBuffer) + self.transmute_buffer_mode(RegularBuffer) } fn transmute( @@ -650,26 +650,18 @@ where } } - fn transmute_new_transfer_mode< - NewC_TransferDir, - NewC_TransferMode, - NewC_FlowController, - NewC_CircularMode, - >( + fn transmute_transfer_mode( self, transfer_mode: NewC_TransferMode, ) -> ConfigBuilder< - NewC_TransferDir, + C_TransferDir, NewC_TransferMode, - NewC_FlowController, - NewC_CircularMode, + C_FlowController, + C_CircularMode, C_BufferMode, > where - NewC_TransferDir: TransferDirectionTrait, NewC_TransferMode: TransferModeTrait, - NewC_FlowController: FlowControllerTrait, - NewC_CircularMode: CircularModeTrait, { ConfigBuilder { tc_intrpt: self.tc_intrpt, @@ -690,25 +682,17 @@ where } } - fn transmute_new_buffer_mode< - NewC_TransferDir, - NewC_FlowController, - NewC_CircularMode, - NewC_BufferMode, - >( + fn transmute_buffer_mode( self, buffer_mode: NewC_BufferMode, ) -> ConfigBuilder< - NewC_TransferDir, + C_TransferDir, C_TransferMode, - NewC_FlowController, - NewC_CircularMode, + C_FlowController, + C_CircularMode, NewC_BufferMode, > where - NewC_TransferDir: TransferDirectionTrait, - NewC_FlowController: FlowControllerTrait, - NewC_CircularMode: CircularModeTrait, NewC_BufferMode: BufferModeTrait, { ConfigBuilder { @@ -743,10 +727,9 @@ where pub fn transfer_dir_m2m( self, ) -> ConfigBuilder { - let builder: ConfigBuilder = - self.transmute_new_transfer_mode(Fifo::default()); - - builder.transmute_new_buffer_mode(RegularBuffer) + self.transmute() + .transmute_transfer_mode(Fifo::default()) + .transmute_buffer_mode(RegularBuffer) } } @@ -780,7 +763,7 @@ where C_CircularMode, C_BufferMode, > { - self.transmute_new_transfer_mode(Direct) + self.transmute_transfer_mode(Direct) } pub fn flow_controller_peripheral( @@ -826,7 +809,7 @@ where NotCircular, RegularBuffer, > { - self.transmute_new_buffer_mode(RegularBuffer) + self.transmute().transmute_buffer_mode(RegularBuffer) } } @@ -860,7 +843,7 @@ where self, ) -> ConfigBuilder { - self.transmute_new_buffer_mode(DoubleBuffer::default()) + self.transmute_buffer_mode(DoubleBuffer::default()) } } @@ -878,6 +861,72 @@ impl Default } } +impl + ConfigBuilder< + C_TransferDir, + Fifo, + C_FlowController, + C_CircularMode, + C_BufferMode, + > +where + C_TransferDir: TransferDirectionTrait, + C_FlowController: FlowControllerTrait, + C_CircularMode: CircularModeTrait, + C_BufferMode: BufferModeTrait, +{ + pub fn fifo_threshold(mut self, fifo_threshold: FifoThreshold) -> Self { + self.transfer_mode.fifo_threshold = Some(fifo_threshold); + + self + } + + pub fn p_burst(mut self, p_burst: PBurst) -> Self { + self.transfer_mode.p_burst = Some(p_burst); + + self + } + + pub fn m_burst(mut self, m_burst: MBurst) -> Self { + self.transfer_mode.m_burst = Some(m_burst); + + self + } + + pub fn m_size(mut self, m_size: MSize) -> Self { + self.transfer_mode.m_size = Some(m_size); + + self + } +} + +impl + ConfigBuilder< + C_TransferDir, + C_TransferMode, + C_FlowController, + C_CircularMode, + DoubleBuffer, + > +where + C_TransferDir: TransferDirectionTrait, + C_TransferMode: TransferModeTrait, + C_FlowController: FlowControllerTrait, + C_CircularMode: CircularModeTrait, +{ + pub fn current_target(mut self, current_target: CurrentTarget) -> Self { + self.buffer_mode.current_target = Some(current_target); + + self + } + + pub fn m1a(mut self, m1a: M1a) -> Self { + self.buffer_mode.m1a = Some(m1a); + + self + } +} + ///////////////////////////////////////////////////////////////////////// // # TRANSFER DIRECTION ///////////////////////////////////////////////////////////////////////// From 3b8acccbd9bc5e436a67a3bc4919e932b481879e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ad=C3=A4?= Date: Tue, 24 Mar 2020 16:46:49 +0100 Subject: [PATCH 069/103] update --- src/dma/channel.rs | 4 +- src/dma/mod.rs | 180 +++++++++++++++++++-------------------- src/dma/safe_transfer.rs | 12 +-- src/dma/stream.rs | 148 ++++++++++++++++---------------- 4 files changed, 171 insertions(+), 173 deletions(-) diff --git a/src/dma/channel.rs b/src/dma/channel.rs index 46505f41..bb73358b 100644 --- a/src/dma/channel.rs +++ b/src/dma/channel.rs @@ -1,6 +1,6 @@ //! DMA Channels -use super::DMATrait; +use super::DmaPeripheral; use crate::private; use crate::stm32::{DMA1, DMA2}; @@ -8,7 +8,7 @@ pub trait ChannelId: Send + private::Sealed { const STREAM_ID: usize; const MUX_ID: usize; - type DMA: DMATrait; + type DMA: DmaPeripheral; } #[doc(hidden)] diff --git a/src/dma/mod.rs b/src/dma/mod.rs index a3663f76..0c5a602a 100644 --- a/src/dma/mod.rs +++ b/src/dma/mod.rs @@ -18,14 +18,12 @@ use self::channel::{ use self::mux::request_gen::{ Disabled as GenDisabled, G0, G1, G2, G3, G4, G5, G6, G7, }; -use self::mux::request_ids::{ - ReqNone, RequestId as RequestIdTrait, RequestIdSome, -}; +use self::mux::request_ids::{ReqNone, RequestId as IRequestId, RequestIdSome}; use self::mux::shared::{MuxIsr, RequestGenIsr}; use self::mux::{ - EgDisabled, EgED as EgEDTrait, EgEnabled, MuxShared, NbReq, OverrunError, - RequestGenerator, RequestId, SyncDisabled, SyncED as SyncEDTrait, - SyncEnabled, SyncId, SyncOverrunInterrupt, SyncPolarity, + EgDisabled, EgED as IEgED, EgEnabled, MuxShared, NbReq, OverrunError, + RequestGenerator, RequestId, SyncDisabled, SyncED as ISyncED, SyncEnabled, + SyncId, SyncOverrunInterrupt, SyncPolarity, }; use self::safe_transfer::{ check_buffer, check_double_buffer, configure_safe_transfer, mut_ptr_memory, @@ -37,10 +35,10 @@ use self::stream::{ BufferMode, CircularMode, CurrentTarget, DirectModeErrorInterrupt, Disabled, Enabled, Error, Event, FifoErrorInterrupt, FifoThreshold, FlowController, HalfTransferInterrupt, IntoNum, IsrCleared, - IsrState as IsrStateTrait, IsrUncleared, M0a, M1a, MBurst, MSize, Minc, - Ndt, PBurst, PSize, Pa, Pinc, Pincos, PriorityLevel, StreamIsr, + IsrState as IIsrState, IsrUncleared, M0a, M1a, MBurst, MSize, Minc, Ndt, + PBurst, PSize, Pa, Pinc, Pincos, PriorityLevel, StreamIsr, TransferCompleteInterrupt, TransferDirection, TransferErrorInterrupt, - TransferMode, ED as EDTrait, + TransferMode, ED as IED, }; use crate::nb::{self, block, Error as NbError}; use crate::private; @@ -54,20 +52,20 @@ use core::mem; use stm32h7::stm32h743::DMAMUX1; /// Marker Trait for DMA peripherals -pub trait DMATrait: Send + private::Sealed {} -impl DMATrait for DMA1 {} -impl DMATrait for DMA2 {} +pub trait DmaPeripheral: Send + private::Sealed {} +impl DmaPeripheral for DMA1 {} +impl DmaPeripheral for DMA2 {} /// DMA Channel pub struct Channel where CXX: ChannelId, - DMA: DMATrait, - StreamED: EDTrait, - IsrState: IsrStateTrait, - ReqId: RequestIdTrait, - SyncED: SyncEDTrait, - EgED: EgEDTrait, + DMA: DmaPeripheral, + StreamED: IED, + IsrState: IIsrState, + ReqId: IRequestId, + SyncED: ISyncED, + EgED: IEgED, { pub stream: Stream, pub mux: DmaMux, @@ -77,12 +75,12 @@ impl Channel where CXX: ChannelId, - DMA: DMATrait, - StreamED: EDTrait, - IsrState: IsrStateTrait, - ReqId: RequestIdTrait, - SyncED: SyncEDTrait, - EgED: EgEDTrait, + DMA: DmaPeripheral, + StreamED: IED, + IsrState: IIsrState, + ReqId: IRequestId, + SyncED: ISyncED, + EgED: IEgED, { /// Exposes the stream as owned value in a closure pub fn stream_owned( @@ -93,8 +91,8 @@ where F: FnOnce( Stream, ) -> Stream, - NewStreamED: EDTrait, - NewIsrState: IsrStateTrait, + NewStreamED: IED, + NewIsrState: IIsrState, { let new_stream = op(self.stream); @@ -113,9 +111,9 @@ where F: FnOnce( DmaMux, ) -> DmaMux, - NewReqId: RequestIdTrait, - NewSyncED: SyncEDTrait, - NewEgED: EgEDTrait, + NewReqId: IRequestId, + NewSyncED: ISyncED, + NewEgED: IEgED, { let new_mux = op(self.mux); @@ -130,9 +128,9 @@ where pub struct Stream where CXX: ChannelId, - DMA: DMATrait, - ED: EDTrait, - IsrState: IsrStateTrait, + DMA: DmaPeripheral, + ED: IED, + IsrState: IIsrState, { /// This field *must not* be mutated using shared references rb: &'static ST, @@ -143,7 +141,7 @@ where impl Stream where CXX: ChannelId, - DMA: DMATrait, + DMA: DmaPeripheral, { /// Creates an instance of a Stream in initial state. /// @@ -160,9 +158,9 @@ where impl Stream where CXX: ChannelId, - DMA: DMATrait, - ED: EDTrait, - IsrState: IsrStateTrait, + DMA: DmaPeripheral, + ED: IED, + IsrState: IIsrState, { /// Returns the id of the Stream pub fn id(&self) -> usize { @@ -447,8 +445,8 @@ where self, ) -> Stream where - NewED: EDTrait, - NewIsrState: IsrStateTrait, + NewED: IED, + NewIsrState: IIsrState, { Stream { rb: self.rb, @@ -461,8 +459,8 @@ where impl Stream where CXX: ChannelId, - DMA: DMATrait, - IsrState: IsrStateTrait, + DMA: DmaPeripheral, + IsrState: IIsrState, { /// Sets the Flow Controller pub fn set_flow_controller(&mut self, flow_controller: FlowController) { @@ -653,8 +651,8 @@ where impl Stream where CXX: ChannelId, - DMA: DMATrait, - IsrState: IsrStateTrait, + DMA: DmaPeripheral, + IsrState: IIsrState, { /// Sets the Memory-0 Address on the fly /// @@ -701,7 +699,7 @@ where impl Stream where CXX: ChannelId, - DMA: DMATrait, + DMA: DmaPeripheral, { /// Checks the config for data integrity and enables the stream /// @@ -856,8 +854,8 @@ where impl Stream where CXX: ChannelId, - DMA: DMATrait, - IsrState: IsrStateTrait, + DMA: DmaPeripheral, + IsrState: IIsrState, { /// Disables the stream pub fn disable(self) -> Stream { @@ -883,8 +881,8 @@ where impl Stream where CXX: ChannelId, - DMA: DMATrait, - ED: EDTrait, + DMA: DmaPeripheral, + ED: IED, { /// Returns the contents of the isr. /// @@ -1164,7 +1162,7 @@ where impl Stream where CXX: ChannelId, - DMA: DMATrait, + DMA: DmaPeripheral, { /// Clears the ISR pub fn clear_isr( @@ -1180,7 +1178,7 @@ where impl Stream where CXX: ChannelId, - DMA: DMATrait, + DMA: DmaPeripheral, { /// Clears the ISR pub fn clear_isr(&self, isr: &mut StreamIsr) { @@ -1191,18 +1189,18 @@ where unsafe impl Send for Stream where CXX: ChannelId, - DMA: DMATrait, - ED: EDTrait, - IsrState: IsrStateTrait, + DMA: DmaPeripheral, + ED: IED, + IsrState: IIsrState, { } unsafe impl Sync for Stream where CXX: ChannelId, - DMA: DMATrait, - ED: EDTrait, - IsrState: IsrStateTrait, + DMA: DmaPeripheral, + ED: IED, + IsrState: IIsrState, { } @@ -1210,9 +1208,9 @@ where pub struct DmaMux where CXX: ChannelId, - ReqId: RequestIdTrait, - SyncED: SyncEDTrait, - EgED: EgEDTrait, + ReqId: IRequestId, + SyncED: ISyncED, + EgED: IEgED, { /// This field *must not* be mutated using shared references rb: &'static CCR, @@ -1239,9 +1237,9 @@ where impl DmaMux where CXX: ChannelId, - ReqId: RequestIdTrait, - SyncED: SyncEDTrait, - EgED: EgEDTrait, + ReqId: IRequestId, + SyncED: ISyncED, + EgED: IEgED, { /// Returns the id of the DMA Mux pub fn id(&self) -> usize { @@ -1315,8 +1313,8 @@ where self, ) -> DmaMux where - NewSyncED: SyncEDTrait, - NewEgED: EgEDTrait, + NewSyncED: ISyncED, + NewEgED: IEgED, { DmaMux { rb: self.rb, @@ -1329,7 +1327,7 @@ where impl DmaMux where CXX: ChannelId, - ReqId: RequestIdTrait, + ReqId: IRequestId, { /// Sets the number of requests pub fn set_nbreq(&mut self, nbreq: NbReq) { @@ -1340,8 +1338,8 @@ where impl DmaMux where CXX: ChannelId, - ReqId: RequestIdTrait, - EgED: EgEDTrait, + ReqId: IRequestId, + EgED: IEgED, { /// Enables synchronization pub fn enable_sync(self) -> DmaMux { @@ -1354,8 +1352,8 @@ where impl DmaMux where CXX: ChannelId, - ReqId: RequestIdTrait, - EgED: EgEDTrait, + ReqId: IRequestId, + EgED: IEgED, { /// Disables synchronization pub fn disable_sync(self) -> DmaMux { @@ -1368,8 +1366,8 @@ where impl DmaMux where CXX: ChannelId, - ReqId: RequestIdTrait, - SyncED: SyncEDTrait, + ReqId: IRequestId, + SyncED: ISyncED, { /// Enables event generation pub fn enable_event_gen(self) -> DmaMux { @@ -1382,8 +1380,8 @@ where impl DmaMux where CXX: ChannelId, - ReqId: RequestIdTrait, - SyncED: SyncEDTrait, + ReqId: IRequestId, + SyncED: ISyncED, { /// Disables event generation pub fn disable_event_gen(self) -> DmaMux { @@ -1396,8 +1394,8 @@ where impl DmaMux where CXX: ChannelId, - SyncED: SyncEDTrait, - EgED: EgEDTrait, + SyncED: ISyncED, + EgED: IEgED, { /// Sets request id pub fn set_req_id( @@ -1421,8 +1419,8 @@ impl DmaMux where CXX: ChannelId, ReqId: RequestIdSome, - SyncED: SyncEDTrait, - EgED: EgEDTrait, + SyncED: ISyncED, + EgED: IEgED, { /// Unsets request id, defaulting to `ReqNone` and returning the old one pub fn unset_req_id( @@ -1464,9 +1462,9 @@ where impl DmaMux where CXX: ChannelId, - ReqId: RequestIdTrait, - SyncED: SyncEDTrait, - EgED: EgEDTrait, + ReqId: IRequestId, + SyncED: ISyncED, + EgED: IEgED, { /// Checks the ISR for errors pub fn check_isr(&self, mux_isr: &MuxIsr) -> Result<(), OverrunError> { @@ -1509,18 +1507,18 @@ where unsafe impl Send for DmaMux where CXX: ChannelId, - ReqId: RequestIdTrait, - SyncED: SyncEDTrait, - EgED: EgEDTrait, + ReqId: IRequestId, + SyncED: ISyncED, + EgED: IEgED, { } unsafe impl Sync for DmaMux where CXX: ChannelId, - ReqId: RequestIdTrait, - SyncED: SyncEDTrait, - EgED: EgEDTrait, + ReqId: IRequestId, + SyncED: ISyncED, + EgED: IEgED, { } @@ -1623,7 +1621,7 @@ where ) -> SafeTransfer<'wo, Source, Dest, Ongoing> where CXX: ChannelId, - DMA: DMATrait, + DMA: DmaPeripheral, { configure_safe_transfer(&mut stream, &self.peripheral, &self.memory); stream.set_buffer_mode(BufferMode::Regular); @@ -1643,7 +1641,7 @@ where Source: Payload, Dest: Payload, CXX: ChannelId, - DMA: DMATrait, + DMA: DmaPeripheral, { /// Returns the stream assigned to the transfer pub fn stream(&self) -> &Stream { @@ -1802,7 +1800,7 @@ where ) -> SafeTransferDoubleBuffer<'wo, Peripheral, Memory, Ongoing> where CXX: ChannelId, - DMA: DMATrait, + DMA: DmaPeripheral, { stream.set_buffer_mode(BufferMode::DoubleBuffer); stream.set_m1a(M1a(self.memories[1].as_ptr(Some(0)) as u32)); @@ -1829,7 +1827,7 @@ where Peripheral: Payload, Memory: Payload, CXX: ChannelId, - DMA: DMATrait, + DMA: DmaPeripheral, { /// Returns the stream assigned to the transfer pub fn stream(&self) -> &Stream { @@ -2177,8 +2175,8 @@ impl Dma { } } -pub trait DmaExt: DMATrait { - type Other: DMATrait; +pub trait DmaExt: DmaPeripheral { + type Other: DmaPeripheral; fn dma( self, diff --git a/src/dma/safe_transfer.rs b/src/dma/safe_transfer.rs index 6c75c269..6b90f6d5 100644 --- a/src/dma/safe_transfer.rs +++ b/src/dma/safe_transfer.rs @@ -5,7 +5,7 @@ use super::stream::{ CircularMode, Disabled, Enabled, IsrCleared, IsrUncleared, M0a, MSize, Minc, Ndt, PSize, Pa, Pinc, Pincos, TransferDirection, TransferMode, }; -use super::{DMATrait, Stream}; +use super::{DmaPeripheral, Stream}; use crate::private; use core::convert::{TryFrom, TryInto}; use core::fmt::Debug; @@ -21,7 +21,7 @@ impl TransferState for Start {} pub struct Ongoing where CXX: ChannelId, - DMA: DMATrait, + DMA: DmaPeripheral, { pub(super) stream: Stream, } @@ -29,14 +29,14 @@ where impl private::Sealed for Ongoing where CXX: ChannelId, - DMA: DMATrait, + DMA: DmaPeripheral, { } impl TransferState for Ongoing where CXX: ChannelId, - DMA: DMATrait, + DMA: DmaPeripheral, { } @@ -1183,7 +1183,7 @@ pub(super) fn configure_safe_transfer( memory: &MemoryBuffer, ) where CXX: ChannelId, - DMA: DMATrait, + DMA: DmaPeripheral, Peripheral: Payload, Memory: Payload, { @@ -1248,7 +1248,7 @@ fn configure_ndt( memory: &MemoryBuffer, ) where CXX: ChannelId, - DMA: DMATrait, + DMA: DmaPeripheral, Peripheral: Payload, Memory: Payload, { diff --git a/src/dma/stream.rs b/src/dma/stream.rs index 2bf86e0f..e2acde67 100644 --- a/src/dma/stream.rs +++ b/src/dma/stream.rs @@ -1,7 +1,7 @@ //! DMA Stream use super::utils::DefaultTraits; -use super::DMATrait; +use super::DmaPeripheral; use crate::private; use crate::stm32::dma1::{HIFCR, HISR, LIFCR, LISR}; use core::marker::PhantomData; @@ -202,7 +202,7 @@ impl IntoNum for FifoThreshold { pub struct StreamIsr where - DMA: DMATrait, + DMA: DmaPeripheral, { pub(super) lisr: &'static LISR, pub(super) hisr: &'static HISR, @@ -215,7 +215,7 @@ where impl StreamIsr where - DMA: DMATrait, + DMA: DmaPeripheral, { pub(super) fn new( lisr: &'static LISR, @@ -233,8 +233,8 @@ where } } -unsafe impl Send for StreamIsr where DMA: DMATrait {} -unsafe impl Sync for StreamIsr where DMA: DMATrait {} +unsafe impl Send for StreamIsr where DMA: DmaPeripheral {} +unsafe impl Sync for StreamIsr where DMA: DmaPeripheral {} #[derive(Debug, PartialEq, Eq, Clone, Copy)] pub enum Event { @@ -392,11 +392,11 @@ pub struct ConfigBuilder< C_CircularMode, C_BufferMode, > where - C_TransferDir: TransferDirectionTrait, - C_TransferMode: TransferModeTrait, - C_FlowController: FlowControllerTrait, - C_CircularMode: CircularModeTrait, - C_BufferMode: BufferModeTrait, + C_TransferDir: ITransferDirection, + C_TransferMode: ITransferMode, + C_FlowController: IFlowController, + C_CircularMode: ICircularMode, + C_BufferMode: IBufferMode, { tc_intrpt: Option, ht_intrpt: Option, @@ -464,11 +464,11 @@ impl< C_BufferMode, > where - C_TransferDir: TransferDirectionTrait, - C_TransferMode: TransferModeTrait, - C_FlowController: FlowControllerTrait, - C_CircularMode: CircularModeTrait, - C_BufferMode: BufferModeTrait, + C_TransferDir: ITransferDirection, + C_TransferMode: ITransferMode, + C_FlowController: IFlowController, + C_CircularMode: ICircularMode, + C_BufferMode: IBufferMode, { pub fn transfer_complete_interrupt( mut self, @@ -627,9 +627,9 @@ where C_BufferMode, > where - NewC_TransferDir: TransferDirectionTrait, - NewC_FlowController: FlowControllerTrait, - NewC_CircularMode: CircularModeTrait, + NewC_TransferDir: ITransferDirection, + NewC_FlowController: IFlowController, + NewC_CircularMode: ICircularMode, { ConfigBuilder { tc_intrpt: self.tc_intrpt, @@ -661,7 +661,7 @@ where C_BufferMode, > where - NewC_TransferMode: TransferModeTrait, + NewC_TransferMode: ITransferMode, { ConfigBuilder { tc_intrpt: self.tc_intrpt, @@ -693,7 +693,7 @@ where NewC_BufferMode, > where - NewC_BufferMode: BufferModeTrait, + NewC_BufferMode: IBufferMode, { ConfigBuilder { tc_intrpt: self.tc_intrpt, @@ -718,11 +718,11 @@ where impl ConfigBuilder where - C_TransferDir: TransferDirectionTrait, - C_Fifo: TransferModeTrait + Into, - C_Dma: FlowControllerTrait + Into, - C_NotCircular: CircularModeTrait + Into, - C_RegularBuffer: BufferModeTrait + Into, + C_TransferDir: ITransferDirection, + C_Fifo: ITransferMode + Into, + C_Dma: IFlowController + Into, + C_NotCircular: ICircularMode + Into, + C_RegularBuffer: IBufferMode + Into, { pub fn transfer_dir_m2m( self, @@ -749,10 +749,10 @@ impl< > where C_NotM2M: NotM2M, - C_TransferMode: TransferModeTrait, - C_FlowController: FlowControllerTrait, - C_CircularMode: CircularModeTrait, - C_BufferMode: BufferModeTrait, + C_TransferMode: ITransferMode, + C_FlowController: IFlowController, + C_CircularMode: ICircularMode, + C_BufferMode: IBufferMode, { pub fn transfer_mode_direct( self, @@ -794,11 +794,11 @@ impl< C_RegularBuffer, > where - C_TransferDir: TransferDirectionTrait, - C_TransferMode: TransferModeTrait, - C_FlowController: FlowControllerTrait, - C_CircularMode: CircularModeTrait, - C_RegularBuffer: BufferModeTrait + Into, + C_TransferDir: ITransferDirection, + C_TransferMode: ITransferMode, + C_FlowController: IFlowController, + C_CircularMode: ICircularMode, + C_RegularBuffer: IBufferMode + Into, { pub fn circular_mode_disabled( self, @@ -817,10 +817,10 @@ impl ConfigBuilder where C_NotM2M: NotM2M, - C_TransferMode: TransferModeTrait, - C_Dma: FlowControllerTrait + Into, - C_CircularMode: CircularModeTrait, - C_BufferMode: BufferModeTrait, + C_TransferMode: ITransferMode, + C_Dma: IFlowController + Into, + C_CircularMode: ICircularMode, + C_BufferMode: IBufferMode, { pub fn circular_mode_enabled( self, @@ -834,10 +834,10 @@ impl ConfigBuilder where C_NotM2M: NotM2M, - C_TransferMode: TransferModeTrait, - C_Dma: FlowControllerTrait + Into, - C_Circular: CircularModeTrait + Into, - C_BufferMode: BufferModeTrait, + C_TransferMode: ITransferMode, + C_Dma: IFlowController + Into, + C_Circular: ICircularMode + Into, + C_BufferMode: IBufferMode, { pub fn buffer_mode_double_buffer( self, @@ -870,10 +870,10 @@ impl C_BufferMode, > where - C_TransferDir: TransferDirectionTrait, - C_FlowController: FlowControllerTrait, - C_CircularMode: CircularModeTrait, - C_BufferMode: BufferModeTrait, + C_TransferDir: ITransferDirection, + C_FlowController: IFlowController, + C_CircularMode: ICircularMode, + C_BufferMode: IBufferMode, { pub fn fifo_threshold(mut self, fifo_threshold: FifoThreshold) -> Self { self.transfer_mode.fifo_threshold = Some(fifo_threshold); @@ -909,10 +909,10 @@ impl DoubleBuffer, > where - C_TransferDir: TransferDirectionTrait, - C_TransferMode: TransferModeTrait, - C_FlowController: FlowControllerTrait, - C_CircularMode: CircularModeTrait, + C_TransferDir: ITransferDirection, + C_TransferMode: ITransferMode, + C_FlowController: IFlowController, + C_CircularMode: ICircularMode, { pub fn current_target(mut self, current_target: CurrentTarget) -> Self { self.buffer_mode.current_target = Some(current_target); @@ -931,14 +931,14 @@ where // # TRANSFER DIRECTION ///////////////////////////////////////////////////////////////////////// -pub trait TransferDirectionTrait: DefaultTraits + private::Sealed { +pub trait ITransferDirection: DefaultTraits + private::Sealed { const TRANSFER_DIRECTION: Option; } #[derive(Debug, PartialEq, Eq, Clone, Copy)] -pub struct P2M {} +pub struct P2M; #[derive(Debug, PartialEq, Eq, Clone, Copy)] -pub struct M2P {} +pub struct M2P; #[derive(Debug, PartialEq, Eq, Clone, Copy)] pub struct M2M; @@ -946,22 +946,22 @@ impl private::Sealed for P2M {} impl private::Sealed for M2P {} impl private::Sealed for M2M {} -impl TransferDirectionTrait for P2M { +impl ITransferDirection for P2M { const TRANSFER_DIRECTION: Option = Some(TransferDirection::P2M); } -impl TransferDirectionTrait for M2P { +impl ITransferDirection for M2P { const TRANSFER_DIRECTION: Option = Some(TransferDirection::M2P); } -impl TransferDirectionTrait for M2M { +impl ITransferDirection for M2M { const TRANSFER_DIRECTION: Option = Some(TransferDirection::M2M); } -pub trait NotM2M: TransferDirectionTrait {} +pub trait NotM2M: ITransferDirection {} impl NotM2M for P2M {} impl NotM2M for M2P {} @@ -970,7 +970,7 @@ impl NotM2M for M2P {} // # TRANSFER MODE ///////////////////////////////////////////////////////////////////////// -pub trait TransferModeTrait: DefaultTraits + private::Sealed { +pub trait ITransferMode: DefaultTraits + private::Sealed { const TRANSFER_MODE: Option; } @@ -988,10 +988,10 @@ pub struct Fifo { impl private::Sealed for Direct {} impl private::Sealed for Fifo {} -impl TransferModeTrait for Direct { +impl ITransferMode for Direct { const TRANSFER_MODE: Option = Some(TransferMode::Direct); } -impl TransferModeTrait for Fifo { +impl ITransferMode for Fifo { const TRANSFER_MODE: Option = Some(TransferMode::Fifo); } @@ -999,7 +999,7 @@ impl TransferModeTrait for Fifo { // # FLOW CONTROLLER ///////////////////////////////////////////////////////////////////////// -pub trait FlowControllerTrait: DefaultTraits + private::Sealed { +pub trait IFlowController: DefaultTraits + private::Sealed { const FLOW_CONTROLLER: Option; } @@ -1011,10 +1011,10 @@ pub struct Peripheral; impl private::Sealed for Dma {} impl private::Sealed for Peripheral {} -impl FlowControllerTrait for Dma { +impl IFlowController for Dma { const FLOW_CONTROLLER: Option = Some(FlowController::Dma); } -impl FlowControllerTrait for Peripheral { +impl IFlowController for Peripheral { const FLOW_CONTROLLER: Option = Some(FlowController::Peripheral); } @@ -1023,7 +1023,7 @@ impl FlowControllerTrait for Peripheral { // # CIRCULAR MODE ///////////////////////////////////////////////////////////////////////// -pub trait CircularModeTrait: DefaultTraits + private::Sealed { +pub trait ICircularMode: DefaultTraits + private::Sealed { const CIRCULAR_MODE: Option; } @@ -1035,10 +1035,10 @@ pub struct NotCircular; impl private::Sealed for Circular {} impl private::Sealed for NotCircular {} -impl CircularModeTrait for Circular { +impl ICircularMode for Circular { const CIRCULAR_MODE: Option = Some(CircularMode::Enabled); } -impl CircularModeTrait for NotCircular { +impl ICircularMode for NotCircular { const CIRCULAR_MODE: Option = Some(CircularMode::Disabled); } @@ -1046,7 +1046,7 @@ impl CircularModeTrait for NotCircular { // # BUFFER MODE ///////////////////////////////////////////////////////////////////////// -pub trait BufferModeTrait: DefaultTraits + private::Sealed { +pub trait IBufferMode: DefaultTraits + private::Sealed { const BUFFER_MODE: Option; } @@ -1061,10 +1061,10 @@ pub struct DoubleBuffer { impl private::Sealed for RegularBuffer {} impl private::Sealed for DoubleBuffer {} -impl BufferModeTrait for RegularBuffer { +impl IBufferMode for RegularBuffer { const BUFFER_MODE: Option = Some(BufferMode::Regular); } -impl BufferModeTrait for DoubleBuffer { +impl IBufferMode for DoubleBuffer { const BUFFER_MODE: Option = Some(BufferMode::DoubleBuffer); } @@ -1077,23 +1077,23 @@ pub struct NotConfigured; impl private::Sealed for NotConfigured {} -impl TransferDirectionTrait for NotConfigured { +impl ITransferDirection for NotConfigured { const TRANSFER_DIRECTION: Option = None; } -impl TransferModeTrait for NotConfigured { +impl ITransferMode for NotConfigured { const TRANSFER_MODE: Option = None; } -impl FlowControllerTrait for NotConfigured { +impl IFlowController for NotConfigured { const FLOW_CONTROLLER: Option = None; } -impl CircularModeTrait for NotConfigured { +impl ICircularMode for NotConfigured { const CIRCULAR_MODE: Option = None; } -impl BufferModeTrait for NotConfigured { +impl IBufferMode for NotConfigured { const BUFFER_MODE: Option = None; } From 417daf1e53e412ac5364f49af6d526fff62b9610 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ad=C3=A4?= Date: Thu, 26 Mar 2020 17:35:59 +0100 Subject: [PATCH 070/103] implemented config builder --- src/dma/stream.rs | 969 ++++++++++++++++++++++++++++++++++++---------- 1 file changed, 764 insertions(+), 205 deletions(-) diff --git a/src/dma/stream.rs b/src/dma/stream.rs index e2acde67..6da624fd 100644 --- a/src/dma/stream.rs +++ b/src/dma/stream.rs @@ -269,6 +269,7 @@ pub struct Config { pub ndt: Ndt, pub pa: Pa, pub m0a: M0a, + pub transfer_direction: TransferDirectionConf, } ///////////////////////////////////////////////////////////////////////// @@ -391,12 +392,14 @@ pub struct ConfigBuilder< C_FlowController, C_CircularMode, C_BufferMode, + C_PBurst, > where - C_TransferDir: ITransferDirection, - C_TransferMode: ITransferMode, - C_FlowController: IFlowController, - C_CircularMode: ICircularMode, - C_BufferMode: IBufferMode, + C_TransferDir: MaybeNotConfigured, + C_TransferMode: MaybeNotConfigured, + C_FlowController: MaybeNotConfigured, + C_CircularMode: MaybeNotConfigured, + C_BufferMode: MaybeNotConfigured, + C_PBurst: MaybeNotConfigured, { tc_intrpt: Option, ht_intrpt: Option, @@ -412,6 +415,7 @@ pub struct ConfigBuilder< m0a: Option, transfer_mode: C_TransferMode, buffer_mode: C_BufferMode, + p_burst: C_PBurst, _phantom: PhantomData<(C_TransferDir, C_FlowController, C_CircularMode)>, } @@ -426,6 +430,7 @@ impl NotConfigured, NotConfigured, NotConfigured, + NotConfigured, > { pub fn new() -> Self { @@ -444,6 +449,7 @@ impl m0a: None, transfer_mode: NotConfigured, buffer_mode: NotConfigured, + p_burst: NotConfigured, _phantom: PhantomData, } } @@ -455,6 +461,7 @@ impl< C_FlowController, C_CircularMode, C_BufferMode, + C_PBurst, > ConfigBuilder< C_TransferDir, @@ -462,13 +469,15 @@ impl< C_FlowController, C_CircularMode, C_BufferMode, + C_PBurst, > where - C_TransferDir: ITransferDirection, - C_TransferMode: ITransferMode, - C_FlowController: IFlowController, - C_CircularMode: ICircularMode, - C_BufferMode: IBufferMode, + C_TransferDir: MaybeNotConfigured, + C_TransferMode: MaybeNotConfigured, + C_FlowController: MaybeNotConfigured, + C_CircularMode: MaybeNotConfigured, + C_BufferMode: MaybeNotConfigured, + C_PBurst: MaybeNotConfigured, { pub fn transfer_complete_interrupt( mut self, @@ -557,66 +566,6 @@ where self } - pub fn transfer_dir_p2m( - self, - ) -> ConfigBuilder< - P2M, - C_TransferMode, - C_FlowController, - C_CircularMode, - C_BufferMode, - > { - self.transmute() - } - - pub fn transfer_dir_m2p( - self, - ) -> ConfigBuilder< - M2P, - C_TransferMode, - C_FlowController, - C_CircularMode, - C_BufferMode, - > { - self.transmute() - } - - pub fn transfer_mode_fifo( - self, - ) -> ConfigBuilder< - C_TransferDir, - Fifo, - C_FlowController, - C_CircularMode, - C_BufferMode, - > { - self.transmute_transfer_mode(Fifo::default()) - } - - pub fn flow_controller_dma( - self, - ) -> ConfigBuilder< - C_TransferDir, - C_TransferMode, - Dma, - C_CircularMode, - C_BufferMode, - > { - self.transmute() - } - - pub fn buffer_mode_regular( - self, - ) -> ConfigBuilder< - C_TransferDir, - C_TransferMode, - C_FlowController, - C_CircularMode, - RegularBuffer, - > { - self.transmute_buffer_mode(RegularBuffer) - } - fn transmute( self, ) -> ConfigBuilder< @@ -625,11 +574,12 @@ where NewC_FlowController, NewC_CircularMode, C_BufferMode, + C_PBurst, > where - NewC_TransferDir: ITransferDirection, - NewC_FlowController: IFlowController, - NewC_CircularMode: ICircularMode, + NewC_TransferDir: MaybeNotConfigured, + NewC_FlowController: MaybeNotConfigured, + NewC_CircularMode: MaybeNotConfigured, { ConfigBuilder { tc_intrpt: self.tc_intrpt, @@ -646,6 +596,7 @@ where m0a: self.m0a, transfer_mode: self.transfer_mode, buffer_mode: self.buffer_mode, + p_burst: self.p_burst, _phantom: PhantomData, } } @@ -659,9 +610,10 @@ where C_FlowController, C_CircularMode, C_BufferMode, + C_PBurst, > where - NewC_TransferMode: ITransferMode, + NewC_TransferMode: MaybeNotConfigured, { ConfigBuilder { tc_intrpt: self.tc_intrpt, @@ -677,6 +629,7 @@ where pa: self.pa, m0a: self.m0a, buffer_mode: self.buffer_mode, + p_burst: self.p_burst, _phantom: PhantomData, transfer_mode, } @@ -691,9 +644,10 @@ where C_FlowController, C_CircularMode, NewC_BufferMode, + C_PBurst, > where - NewC_BufferMode: IBufferMode, + NewC_BufferMode: MaybeNotConfigured, { ConfigBuilder { tc_intrpt: self.tc_intrpt, @@ -709,182 +663,495 @@ where pa: self.pa, m0a: self.m0a, transfer_mode: self.transfer_mode, + p_burst: self.p_burst, _phantom: PhantomData, buffer_mode, } } -} -impl - ConfigBuilder -where - C_TransferDir: ITransferDirection, - C_Fifo: ITransferMode + Into, - C_Dma: IFlowController + Into, - C_NotCircular: ICircularMode + Into, - C_RegularBuffer: IBufferMode + Into, -{ - pub fn transfer_dir_m2m( + fn transmute_p_burst( self, - ) -> ConfigBuilder { - self.transmute() - .transmute_transfer_mode(Fifo::default()) - .transmute_buffer_mode(RegularBuffer) + p_burst: NewC_PBurst, + ) -> ConfigBuilder< + C_TransferDir, + C_TransferMode, + C_FlowController, + C_CircularMode, + C_BufferMode, + NewC_PBurst, + > + where + NewC_PBurst: MaybeNotConfigured, + { + ConfigBuilder { + tc_intrpt: self.tc_intrpt, + ht_intrpt: self.ht_intrpt, + te_intrpt: self.te_intrpt, + dme_intrpt: self.dme_intrpt, + fe_intrpt: self.fe_intrpt, + pinc: self.pinc, + minc: self.minc, + priority: self.priority, + p_size: self.p_size, + ndt: self.ndt, + pa: self.pa, + m0a: self.m0a, + transfer_mode: self.transfer_mode, + buffer_mode: self.buffer_mode, + _phantom: PhantomData, + p_burst, + } } } impl< - C_NotM2M, C_TransferMode, C_FlowController, C_CircularMode, C_BufferMode, + C_PBurst, > ConfigBuilder< - C_NotM2M, + NotConfigured, C_TransferMode, C_FlowController, C_CircularMode, C_BufferMode, + C_PBurst, > where - C_NotM2M: NotM2M, - C_TransferMode: ITransferMode, - C_FlowController: IFlowController, - C_CircularMode: ICircularMode, - C_BufferMode: IBufferMode, + C_TransferMode: MaybeNotConfigured, + C_FlowController: MaybeNotConfigured, + C_CircularMode: MaybeNotConfigured, + C_BufferMode: MaybeNotConfigured, + C_PBurst: MaybeNotConfigured, { - pub fn transfer_mode_direct( + pub fn transfer_dir_p2m( self, ) -> ConfigBuilder< - C_NotM2M, - Direct, + P2M, + C_TransferMode, C_FlowController, C_CircularMode, C_BufferMode, + C_PBurst, > { - self.transmute_transfer_mode(Direct) + self.transmute() } - pub fn flow_controller_peripheral( + pub fn transfer_dir_m2p( self, ) -> ConfigBuilder< - C_NotM2M, + M2P, C_TransferMode, - Peripheral, + C_FlowController, C_CircularMode, C_BufferMode, + C_PBurst, > { self.transmute() } + + pub fn transfer_dir_m2m( + self, + ) -> ConfigBuilder + { + self.transmute() + .transmute_transfer_mode(Fifo::default()) + .transmute_buffer_mode(RegularBuffer) + } } impl< C_TransferDir, - C_TransferMode, C_FlowController, C_CircularMode, - C_RegularBuffer, + C_BufferMode, + C_PBurst, > ConfigBuilder< C_TransferDir, - C_TransferMode, + NotConfigured, C_FlowController, C_CircularMode, - C_RegularBuffer, + C_BufferMode, + C_PBurst, > where C_TransferDir: ITransferDirection, - C_TransferMode: ITransferMode, - C_FlowController: IFlowController, - C_CircularMode: ICircularMode, - C_RegularBuffer: IBufferMode + Into, + C_FlowController: MaybeNotConfigured, + C_CircularMode: MaybeNotConfigured, + C_BufferMode: MaybeNotConfigured, + C_PBurst: MaybeNotConfigured, { - pub fn circular_mode_disabled( + pub fn transfer_mode_fifo( self, ) -> ConfigBuilder< C_TransferDir, - C_TransferMode, + Fifo, C_FlowController, - NotCircular, - RegularBuffer, + C_CircularMode, + C_BufferMode, + C_PBurst, > { - self.transmute().transmute_buffer_mode(RegularBuffer) + self.transmute_transfer_mode(Fifo::default()) } } -impl - ConfigBuilder +impl + ConfigBuilder< + C_NotM2M, + NotConfigured, + C_FlowController, + C_CircularMode, + C_BufferMode, + C_PBurst, + > where C_NotM2M: NotM2M, - C_TransferMode: ITransferMode, - C_Dma: IFlowController + Into, - C_CircularMode: ICircularMode, - C_BufferMode: IBufferMode, + C_FlowController: MaybeNotConfigured, + C_CircularMode: MaybeNotConfigured, + C_BufferMode: MaybeNotConfigured, + C_PBurst: MaybeNotConfigured, { - pub fn circular_mode_enabled( + pub fn transfer_mode_direct( self, - ) -> ConfigBuilder - { - self.transmute() + ) -> ConfigBuilder< + C_NotM2M, + Direct, + C_FlowController, + C_CircularMode, + C_BufferMode, + Single, + > { + self.transmute_transfer_mode(Direct) + .transmute_p_burst(Single::default()) } } -impl - ConfigBuilder +impl + ConfigBuilder< + C_TransferDir, + C_TransferMode, + NotConfigured, + C_CircularMode, + C_BufferMode, + C_PBurst, + > where - C_NotM2M: NotM2M, - C_TransferMode: ITransferMode, - C_Dma: IFlowController + Into, - C_Circular: ICircularMode + Into, - C_BufferMode: IBufferMode, + C_TransferDir: ITransferDirection, + C_TransferMode: MaybeNotConfigured, + C_CircularMode: MaybeNotConfigured, + C_BufferMode: MaybeNotConfigured, + C_PBurst: MaybeNotConfigured, { - pub fn buffer_mode_double_buffer( + pub fn flow_controller_dma( self, - ) -> ConfigBuilder - { - self.transmute_buffer_mode(DoubleBuffer::default()) + ) -> ConfigBuilder< + C_TransferDir, + C_TransferMode, + Dma, + C_CircularMode, + C_BufferMode, + C_PBurst, + > { + self.transmute() } } -impl Default - for ConfigBuilder< - NotConfigured, - NotConfigured, - NotConfigured, - NotConfigured, +impl + ConfigBuilder< + C_NotM2M, + C_TransferMode, NotConfigured, + C_CircularMode, + C_BufferMode, + C_PBurst, > +where + C_NotM2M: NotM2M, + C_TransferMode: MaybeNotConfigured, + C_CircularMode: MaybeNotConfigured, + C_BufferMode: MaybeNotConfigured, + C_PBurst: MaybeNotConfigured, { - fn default() -> Self { - Self::new() + pub fn flow_controller_peripheral( + self, + ) -> ConfigBuilder< + C_NotM2M, + C_TransferMode, + Peripheral, + NotCircular, + RegularBuffer, + C_PBurst, + > { + self.transmute().transmute_buffer_mode(RegularBuffer) } } -impl +impl< + C_TransferDir, + C_TransferMode, + C_FlowController, + C_BufferMode, + C_PBurst, + > ConfigBuilder< C_TransferDir, - Fifo, + C_TransferMode, C_FlowController, - C_CircularMode, + NotConfigured, C_BufferMode, + C_PBurst, > where - C_TransferDir: ITransferDirection, + C_TransferDir: MaybeNotConfigured, + C_TransferMode: MaybeNotConfigured, C_FlowController: IFlowController, - C_CircularMode: ICircularMode, - C_BufferMode: IBufferMode, + C_BufferMode: MaybeNotConfigured, + C_PBurst: MaybeNotConfigured, { - pub fn fifo_threshold(mut self, fifo_threshold: FifoThreshold) -> Self { - self.transfer_mode.fifo_threshold = Some(fifo_threshold); - - self - } - - pub fn p_burst(mut self, p_burst: PBurst) -> Self { - self.transfer_mode.p_burst = Some(p_burst); - - self + pub fn circular_mode_disabled( + self, + ) -> ConfigBuilder< + C_TransferDir, + C_TransferMode, + C_FlowController, + NotCircular, + C_BufferMode, + C_PBurst, + > { + self.transmute() + } +} + +impl + ConfigBuilder< + C_NotM2M, + C_TransferMode, + Dma, + NotConfigured, + C_BufferMode, + C_PBurst, + > +where + C_NotM2M: NotM2M, + C_TransferMode: MaybeNotConfigured, + C_BufferMode: MaybeNotConfigured, + C_PBurst: MaybeNotConfigured, +{ + pub fn circular_mode_enabled( + self, + ) -> ConfigBuilder< + C_NotM2M, + C_TransferMode, + Dma, + Circular, + C_BufferMode, + C_PBurst, + > { + self.transmute() + } +} + +impl< + C_TransferDir, + C_TransferMode, + C_FlowController, + C_CircularMode, + C_PBurst, + > + ConfigBuilder< + C_TransferDir, + C_TransferMode, + C_FlowController, + C_CircularMode, + NotConfigured, + C_PBurst, + > +where + C_TransferDir: MaybeNotConfigured, + C_TransferMode: MaybeNotConfigured, + C_FlowController: MaybeNotConfigured, + C_CircularMode: ICircularMode, + C_PBurst: MaybeNotConfigured, +{ + pub fn buffer_mode_regular( + self, + ) -> ConfigBuilder< + C_TransferDir, + C_TransferMode, + C_FlowController, + C_CircularMode, + RegularBuffer, + C_PBurst, + > { + self.transmute_buffer_mode(RegularBuffer) + } +} + +impl + ConfigBuilder< + C_TransferDir, + C_TransferMode, + C_FlowController, + Circular, + NotConfigured, + C_PBurst, + > +where + C_TransferDir: MaybeNotConfigured, + C_TransferMode: MaybeNotConfigured, + C_FlowController: MaybeNotConfigured, + C_PBurst: MaybeNotConfigured, +{ + pub fn buffer_mode_double_buffer( + self, + ) -> ConfigBuilder< + C_TransferDir, + C_TransferMode, + C_FlowController, + Circular, + DoubleBuffer, + C_PBurst, + > { + self.transmute_buffer_mode(DoubleBuffer::default()) + } +} + +impl< + C_TransferDir, + C_TransferMode, + C_FlowController, + C_CircularMode, + C_BufferMode, + > + ConfigBuilder< + C_TransferDir, + C_TransferMode, + C_FlowController, + C_CircularMode, + C_BufferMode, + NotConfigured, + > +where + C_TransferDir: MaybeNotConfigured, + C_TransferMode: ITransferMode, + C_FlowController: MaybeNotConfigured, + C_CircularMode: MaybeNotConfigured, + C_BufferMode: MaybeNotConfigured, +{ +} + +impl + ConfigBuilder< + C_TransferDir, + Fifo, + C_FlowController, + C_CircularMode, + C_BufferMode, + NotConfigured, + > +where + C_TransferDir: MaybeNotConfigured, + C_FlowController: MaybeNotConfigured, + C_CircularMode: MaybeNotConfigured, + C_BufferMode: MaybeNotConfigured, +{ + pub fn p_burst_single( + self, + ) -> ConfigBuilder< + C_TransferDir, + Fifo, + C_FlowController, + C_CircularMode, + C_BufferMode, + Single, + > { + self.transmute_p_burst(Single::default()) + } + + pub fn p_burst_incr4( + self, + ) -> ConfigBuilder< + C_TransferDir, + Fifo, + C_FlowController, + C_CircularMode, + C_BufferMode, + Incr4, + > { + self.transmute_p_burst(Incr4) + } + + pub fn p_burst_incr8( + self, + ) -> ConfigBuilder< + C_TransferDir, + Fifo, + C_FlowController, + C_CircularMode, + C_BufferMode, + Incr8, + > { + self.transmute_p_burst(Incr8) + } + + pub fn p_burst_incr16( + self, + ) -> ConfigBuilder< + C_TransferDir, + Fifo, + C_FlowController, + C_CircularMode, + C_BufferMode, + Incr16, + > { + self.transmute_p_burst(Incr16) + } +} + +impl Default + for ConfigBuilder< + NotConfigured, + NotConfigured, + NotConfigured, + NotConfigured, + NotConfigured, + NotConfigured, + > +{ + fn default() -> Self { + Self::new() + } +} + +impl< + C_TransferDir, + C_FlowController, + C_CircularMode, + C_BufferMode, + C_PBurst, + > + ConfigBuilder< + C_TransferDir, + Fifo, + C_FlowController, + C_CircularMode, + C_BufferMode, + C_PBurst, + > +where + C_TransferDir: MaybeNotConfigured, + C_FlowController: MaybeNotConfigured, + C_CircularMode: MaybeNotConfigured, + C_BufferMode: MaybeNotConfigured, + C_PBurst: MaybeNotConfigured, +{ + pub fn fifo_threshold(mut self, fifo_threshold: FifoThreshold) -> Self { + self.transfer_mode.fifo_threshold = Some(fifo_threshold); + + self } pub fn m_burst(mut self, m_burst: MBurst) -> Self { @@ -900,19 +1167,27 @@ where } } -impl +impl< + C_TransferDir, + C_TransferMode, + C_FlowController, + C_CircularMode, + C_PBurst, + > ConfigBuilder< C_TransferDir, C_TransferMode, C_FlowController, C_CircularMode, DoubleBuffer, + C_PBurst, > where - C_TransferDir: ITransferDirection, - C_TransferMode: ITransferMode, - C_FlowController: IFlowController, - C_CircularMode: ICircularMode, + C_TransferDir: MaybeNotConfigured, + C_TransferMode: MaybeNotConfigured, + C_FlowController: MaybeNotConfigured, + C_CircularMode: MaybeNotConfigured, + C_PBurst: MaybeNotConfigured, { pub fn current_target(mut self, current_target: CurrentTarget) -> Self { self.buffer_mode.current_target = Some(current_target); @@ -927,12 +1202,109 @@ where } } +impl< + C_TransferDir, + C_TransferMode, + C_FlowController, + C_CircularMode, + C_BufferMode, + > + ConfigBuilder< + C_TransferDir, + C_TransferMode, + C_FlowController, + C_CircularMode, + C_BufferMode, + Single, + > +where + C_TransferDir: MaybeNotConfigured, + C_TransferMode: MaybeNotConfigured, + C_FlowController: MaybeNotConfigured, + C_CircularMode: MaybeNotConfigured, + C_BufferMode: MaybeNotConfigured, +{ + pub fn pincos(mut self, pincos: Pincos) -> Self { + self.p_burst.pincos = Some(pincos); + + self + } +} + +impl< + C_TransferDir, + C_TransferMode, + C_FlowController, + C_CircularMode, + C_BufferMode, + C_PBurst, + > + ConfigBuilder< + C_TransferDir, + C_TransferMode, + C_FlowController, + C_CircularMode, + C_BufferMode, + C_PBurst, + > +where + C_TransferDir: ITransferDirection, + C_TransferMode: ITransferMode, + C_FlowController: IFlowController, + C_CircularMode: ICircularMode, + C_BufferMode: IBufferMode, + C_PBurst: IPBurst, +{ + pub fn build(self) -> Config { + let transfer_direction_conf = + C_TransferDir::build::<_, C_FlowController, C_CircularMode, _, _>( + self.transfer_mode, + self.buffer_mode, + self.p_burst, + ); + + Config { + transfer_complete_interrupt: self.tc_intrpt.unwrap(), + half_transfer_interrupt: self.ht_intrpt.unwrap(), + transfer_error_interrupt: self.te_intrpt.unwrap(), + direct_mode_error_interrupt: self.dme_intrpt.unwrap(), + fifo_error_interrupt: self.fe_intrpt.unwrap(), + pinc: self.pinc.unwrap(), + minc: self.minc.unwrap(), + priority_level: self.priority.unwrap(), + p_size: self.p_size.unwrap(), + ndt: self.ndt.unwrap(), + pa: self.pa.unwrap(), + m0a: self.m0a.unwrap(), + transfer_direction: transfer_direction_conf, + } + } +} + ///////////////////////////////////////////////////////////////////////// // # TRANSFER DIRECTION ///////////////////////////////////////////////////////////////////////// pub trait ITransferDirection: DefaultTraits + private::Sealed { const TRANSFER_DIRECTION: Option; + + fn build< + C_TransferMode, + C_FlowController, + C_CircularMode, + C_BufferMode, + C_PBurst, + >( + transfer_mode: C_TransferMode, + buffer_mode: C_BufferMode, + p_burst: C_PBurst, + ) -> TransferDirectionConf + where + C_TransferMode: ITransferMode, + C_FlowController: IFlowController, + C_CircularMode: ICircularMode, + C_BufferMode: IBufferMode, + C_PBurst: IPBurst; } #[derive(Debug, PartialEq, Eq, Clone, Copy)] @@ -949,16 +1321,90 @@ impl private::Sealed for M2M {} impl ITransferDirection for P2M { const TRANSFER_DIRECTION: Option = Some(TransferDirection::P2M); + + fn build< + C_TransferMode, + C_FlowController, + C_CircularMode, + C_BufferMode, + C_PBurst, + >( + transfer_mode: C_TransferMode, + buffer_mode: C_BufferMode, + p_burst: C_PBurst, + ) -> TransferDirectionConf + where + C_TransferMode: ITransferMode, + C_FlowController: IFlowController, + C_CircularMode: ICircularMode, + C_BufferMode: IBufferMode, + C_PBurst: IPBurst, + { + TransferDirectionConf::NotM2M(NotM2MConf { + transfer_dir: TransferDirectionNotM2M::P2M, + transfer_mode: transfer_mode.build(p_burst), + flow: C_FlowController::build::(buffer_mode), + }) + } } impl ITransferDirection for M2P { const TRANSFER_DIRECTION: Option = Some(TransferDirection::M2P); + + fn build< + C_TransferMode, + C_FlowController, + C_CircularMode, + C_BufferMode, + C_PBurst, + >( + transfer_mode: C_TransferMode, + buffer_mode: C_BufferMode, + p_burst: C_PBurst, + ) -> TransferDirectionConf + where + C_TransferMode: ITransferMode, + C_FlowController: IFlowController, + C_CircularMode: ICircularMode, + C_BufferMode: IBufferMode, + C_PBurst: IPBurst, + { + TransferDirectionConf::NotM2M(NotM2MConf { + transfer_dir: TransferDirectionNotM2M::M2P, + transfer_mode: transfer_mode.build(p_burst), + flow: C_FlowController::build::(buffer_mode), + }) + } } impl ITransferDirection for M2M { const TRANSFER_DIRECTION: Option = Some(TransferDirection::M2M); + + fn build< + C_TransferMode, + C_FlowController, + C_CircularMode, + C_BufferMode, + C_PBurst, + >( + transfer_mode: C_TransferMode, + _: C_BufferMode, + p_burst: C_PBurst, + ) -> TransferDirectionConf + where + C_TransferMode: ITransferMode, + C_FlowController: IFlowController, + C_CircularMode: ICircularMode, + C_BufferMode: IBufferMode, + C_PBurst: IPBurst, + { + TransferDirectionConf::M2M(match transfer_mode.build(p_burst) { + TransferModeConf::Fifo(fifo_conf) => fifo_conf, + _ => unreachable!(), + }) + } } pub trait NotM2M: ITransferDirection {} @@ -972,6 +1418,10 @@ impl NotM2M for M2P {} pub trait ITransferMode: DefaultTraits + private::Sealed { const TRANSFER_MODE: Option; + + fn build(self, p_burst: C_PBurst) -> TransferModeConf + where + C_PBurst: IPBurst; } #[derive(Debug, PartialEq, Eq, Clone, Copy)] @@ -980,7 +1430,6 @@ pub struct Direct; #[derive(Default, Debug, PartialEq, Eq, Clone, Copy)] pub struct Fifo { fifo_threshold: Option, - p_burst: Option, m_burst: Option, m_size: Option, } @@ -990,9 +1439,30 @@ impl private::Sealed for Fifo {} impl ITransferMode for Direct { const TRANSFER_MODE: Option = Some(TransferMode::Direct); + + fn build(self, _: C_PBurst) -> TransferModeConf + where + C_PBurst: IPBurst, + { + TransferModeConf::Direct + } } impl ITransferMode for Fifo { const TRANSFER_MODE: Option = Some(TransferMode::Fifo); + + fn build(self, p_burst: C_PBurst) -> TransferModeConf + where + C_PBurst: IPBurst, + { + let conf = FifoConf { + fifo_threshold: self.fifo_threshold.unwrap(), + p_burst: p_burst.build(), + m_burst: self.m_burst.unwrap(), + m_size: self.m_size.unwrap(), + }; + + TransferModeConf::Fifo(conf) + } } ///////////////////////////////////////////////////////////////////////// @@ -1001,6 +1471,13 @@ impl ITransferMode for Fifo { pub trait IFlowController: DefaultTraits + private::Sealed { const FLOW_CONTROLLER: Option; + + fn build( + buffer_mode: C_BufferMode, + ) -> FlowControllerConf + where + C_CircularMode: ICircularMode, + C_BufferMode: IBufferMode; } #[derive(Debug, PartialEq, Eq, Clone, Copy)] @@ -1013,10 +1490,30 @@ impl private::Sealed for Peripheral {} impl IFlowController for Dma { const FLOW_CONTROLLER: Option = Some(FlowController::Dma); + + fn build( + buffer_mode: C_BufferMode, + ) -> FlowControllerConf + where + C_CircularMode: ICircularMode, + C_BufferMode: IBufferMode, + { + FlowControllerConf::Dma(C_CircularMode::build(buffer_mode)) + } } impl IFlowController for Peripheral { const FLOW_CONTROLLER: Option = Some(FlowController::Peripheral); + + fn build( + _: C_BufferMode, + ) -> FlowControllerConf + where + C_CircularMode: ICircularMode, + C_BufferMode: IBufferMode, + { + FlowControllerConf::Peripheral + } } ///////////////////////////////////////////////////////////////////////// @@ -1025,6 +1522,10 @@ impl IFlowController for Peripheral { pub trait ICircularMode: DefaultTraits + private::Sealed { const CIRCULAR_MODE: Option; + + fn build(buffer_mode: C_BufferMode) -> CircularModeConf + where + C_BufferMode: IBufferMode; } #[derive(Debug, PartialEq, Eq, Clone, Copy)] @@ -1037,9 +1538,23 @@ impl private::Sealed for NotCircular {} impl ICircularMode for Circular { const CIRCULAR_MODE: Option = Some(CircularMode::Enabled); + + fn build(buffer_mode: C_BufferMode) -> CircularModeConf + where + C_BufferMode: IBufferMode, + { + CircularModeConf::Enabled(buffer_mode.build()) + } } impl ICircularMode for NotCircular { const CIRCULAR_MODE: Option = Some(CircularMode::Disabled); + + fn build(_: C_BufferMode) -> CircularModeConf + where + C_BufferMode: IBufferMode, + { + CircularModeConf::Disabled + } } ///////////////////////////////////////////////////////////////////////// @@ -1048,6 +1563,8 @@ impl ICircularMode for NotCircular { pub trait IBufferMode: DefaultTraits + private::Sealed { const BUFFER_MODE: Option; + + fn build(self) -> BufferModeConf; } #[derive(Debug, PartialEq, Eq, Clone, Copy)] @@ -1063,68 +1580,110 @@ impl private::Sealed for DoubleBuffer {} impl IBufferMode for RegularBuffer { const BUFFER_MODE: Option = Some(BufferMode::Regular); + + fn build(self) -> BufferModeConf { + BufferModeConf::Regular + } } impl IBufferMode for DoubleBuffer { const BUFFER_MODE: Option = Some(BufferMode::DoubleBuffer); + + fn build(self) -> BufferModeConf { + let conf = DoubleBufferConf { + current_target: self.current_target.unwrap(), + m1a: self.m1a.unwrap(), + }; + + BufferModeConf::DoubleBuffer(conf) + } } ///////////////////////////////////////////////////////////////////////// -// # NOT CONFIGURED +// # PBURST ///////////////////////////////////////////////////////////////////////// -#[derive(Debug, PartialEq, Eq, Clone, Copy)] -pub struct NotConfigured; +pub trait IPBurst: DefaultTraits + private::Sealed { + const P_BURST: Option; -impl private::Sealed for NotConfigured {} - -impl ITransferDirection for NotConfigured { - const TRANSFER_DIRECTION: Option = None; + fn build(self) -> PBurstConf; } -impl ITransferMode for NotConfigured { - const TRANSFER_MODE: Option = None; +#[derive(Default, Debug, PartialEq, Eq, Clone, Copy)] +pub struct Single { + pincos: Option, } +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +pub struct Incr4; +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +pub struct Incr8; +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +pub struct Incr16; -impl IFlowController for NotConfigured { - const FLOW_CONTROLLER: Option = None; -} +impl private::Sealed for Single {} +impl private::Sealed for Incr4 {} +impl private::Sealed for Incr8 {} +impl private::Sealed for Incr16 {} -impl ICircularMode for NotConfigured { - const CIRCULAR_MODE: Option = None; -} +impl IPBurst for Single { + const P_BURST: Option = Some(PBurst::Single); -impl IBufferMode for NotConfigured { - const BUFFER_MODE: Option = None; + fn build(self) -> PBurstConf { + PBurstConf::Single(self.pincos.unwrap()) + } } -impl NotM2M for NotConfigured {} +impl IPBurst for Incr4 { + const P_BURST: Option = Some(PBurst::Incr4); -impl From for Fifo { - fn from(_: NotConfigured) -> Self { - Self::default() + fn build(self) -> PBurstConf { + PBurstConf::Incr4 } } -impl From for Dma { - fn from(_: NotConfigured) -> Self { - Self - } -} +impl IPBurst for Incr8 { + const P_BURST: Option = Some(PBurst::Incr8); -impl From for NotCircular { - fn from(_: NotConfigured) -> Self { - Self + fn build(self) -> PBurstConf { + PBurstConf::Incr8 } } -impl From for Circular { - fn from(_: NotConfigured) -> Self { - Self - } -} +impl IPBurst for Incr16 { + const P_BURST: Option = Some(PBurst::Incr16); -impl From for RegularBuffer { - fn from(_: NotConfigured) -> Self { - Self + fn build(self) -> PBurstConf { + PBurstConf::Incr16 } } + +///////////////////////////////////////////////////////////////////////// +// # NOT CONFIGURED +///////////////////////////////////////////////////////////////////////// + +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +pub struct NotConfigured; + +impl private::Sealed for NotConfigured {} + +pub trait MaybeNotConfigured: DefaultTraits + private::Sealed {} + +pub struct S_TransferDir; +pub struct S_TransferMode; +pub struct S_FlowController; +pub struct S_CircularMode; +pub struct S_BufferMode; +pub struct S_PBurst; + +impl MaybeNotConfigured for NotConfigured {} +impl MaybeNotConfigured for NotConfigured {} +impl MaybeNotConfigured for NotConfigured {} +impl MaybeNotConfigured for NotConfigured {} +impl MaybeNotConfigured for NotConfigured {} +impl MaybeNotConfigured for NotConfigured {} + +impl MaybeNotConfigured for T where T: ITransferDirection {} +impl MaybeNotConfigured for T where T: ITransferMode {} +impl MaybeNotConfigured for T where T: IFlowController {} +impl MaybeNotConfigured for T where T: ICircularMode {} +impl MaybeNotConfigured for T where T: IBufferMode {} +impl MaybeNotConfigured for T where T: IPBurst {} From 6114919e4c25880b4b7b60d881b3df89576dab7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ad=C3=A4?= Date: Sat, 28 Mar 2020 15:58:58 +0100 Subject: [PATCH 071/103] Implemented config struct for stream --- src/dma/mod.rs | 167 +++++++++-------------- src/dma/safe_transfer.rs | 2 +- src/dma/stream.rs | 279 +++++++++++++++++++++++++++++++++++---- 3 files changed, 314 insertions(+), 134 deletions(-) diff --git a/src/dma/mod.rs b/src/dma/mod.rs index 0c5a602a..b39b19c3 100644 --- a/src/dma/mod.rs +++ b/src/dma/mod.rs @@ -32,7 +32,7 @@ use self::safe_transfer::{ PointerPort, Start, TransferState, }; use self::stream::{ - BufferMode, CircularMode, CurrentTarget, DirectModeErrorInterrupt, + BufferMode, CircularMode, Config, CurrentTarget, DirectModeErrorInterrupt, Disabled, Enabled, Error, Event, FifoErrorInterrupt, FifoThreshold, FlowController, HalfTransferInterrupt, IntoNum, IsrCleared, IsrState as IIsrState, IsrUncleared, M0a, M1a, MBurst, MSize, Minc, Ndt, @@ -462,190 +462,152 @@ where DMA: DmaPeripheral, IsrState: IIsrState, { + pub fn apply_config(&mut self, config: Config) { + self.set_transfer_complete_interrupt( + config.transfer_complete_interrupt, + ); + self.set_half_transfer_interrupt(config.half_transfer_interrupt); + self.set_transfer_error_interrupt(config.transfer_error_interrupt); + self.set_direct_mode_error_interrupt( + config.direct_mode_error_interrupt, + ); + self.set_fifo_error_interrupt(config.fifo_error_interrupt); + self.set_pinc(config.pinc); + self.set_minc(config.minc); + self.set_priority_level(config.priority_level); + self.set_p_size(config.p_size); + self.set_ndt(config.ndt); + self.set_pa(config.pa); + self.set_m0a(config.m0a); + + self.set_transfer_direction(config.transfer_direction()); + self.set_transfer_mode(config.transfer_mode()); + self.set_flow_controller(config.flow_controller()); + self.set_circular_mode(config.circular_mode()); + self.set_buffer_mode(config.buffer_mode()); + + if let Some(fifo_threshold) = config.fifo_threshold() { + self.set_fifo_threshold(fifo_threshold); + } + self.set_p_burst(config.p_burst()); + self.set_m_burst(config.m_burst()); + self.set_m_size(config.m_size()); + self.set_pincos(config.pincos()); + + self.set_current_target(config.current_target()); + if let Some(m1a) = config.m1a() { + self.set_m1a(m1a); + } + } + /// Sets the Flow Controller - pub fn set_flow_controller(&mut self, flow_controller: FlowController) { + fn set_flow_controller(&mut self, flow_controller: FlowController) { self.rb .cr .modify(|_, w| w.pfctrl().bit(flow_controller.into())); } /// Sets the Transfer Direction - pub fn set_transfer_direction(&mut self, transfer_dir: TransferDirection) { + fn set_transfer_direction(&mut self, transfer_dir: TransferDirection) { unsafe { self.rb.cr.modify(|_, w| w.dir().bits(transfer_dir.into())); } } /// Sets the Circular Mode - pub fn set_circular_mode(&mut self, circ_mode: CircularMode) { + fn set_circular_mode(&mut self, circ_mode: CircularMode) { self.rb.cr.modify(|_, w| w.circ().bit(circ_mode.into())); } /// Sets the Peripheral Increment config flag - pub fn set_pinc(&mut self, pinc: Pinc) { + fn set_pinc(&mut self, pinc: Pinc) { self.rb.cr.modify(|_, w| w.pinc().bit(pinc.into())); } /// Sets the Memory Increment config flag - pub fn set_minc(&mut self, minc: Minc) { + fn set_minc(&mut self, minc: Minc) { self.rb.cr.modify(|_, w| w.minc().bit(minc.into())); } /// Sets the Peripheral Size - pub fn set_p_size(&mut self, p_size: PSize) { + fn set_p_size(&mut self, p_size: PSize) { unsafe { self.rb.cr.modify(|_, w| w.psize().bits(p_size.into())); } } /// Sets the Memory Size - pub fn set_m_size(&mut self, m_size: MSize) { + fn set_m_size(&mut self, m_size: MSize) { unsafe { self.rb.cr.modify(|_, w| w.msize().bits(m_size.into())); } } /// Sets the Peripheral Increment Offset - pub fn set_pincos(&mut self, pincos: Pincos) { + fn set_pincos(&mut self, pincos: Pincos) { self.rb.cr.modify(|_, w| w.pincos().bit(pincos.into())); } /// Sets the Priority Level - pub fn set_priority_level(&mut self, priority_level: PriorityLevel) { + fn set_priority_level(&mut self, priority_level: PriorityLevel) { self.rb.cr.modify(|_, w| w.pl().bits(priority_level.into())); } /// Sets the Buffer Mode (`Direct` or `Fifo` mode) - pub fn set_buffer_mode(&mut self, buffer_mode: BufferMode) { + fn set_buffer_mode(&mut self, buffer_mode: BufferMode) { self.rb.cr.modify(|_, w| w.dbm().bit(buffer_mode.into())); } /// Sets the Current Target - pub fn set_current_target(&mut self, current_target: CurrentTarget) { + fn set_current_target(&mut self, current_target: CurrentTarget) { self.rb.cr.modify(|_, w| w.ct().bit(current_target.into())); } /// Sets the Peripheral Burst - pub fn set_p_burst(&mut self, p_burst: PBurst) { + fn set_p_burst(&mut self, p_burst: PBurst) { self.rb.cr.modify(|_, w| w.pburst().bits(p_burst.into())); } /// Sets the Memory Burst - pub fn set_m_burst(&mut self, m_burst: MBurst) { + fn set_m_burst(&mut self, m_burst: MBurst) { self.rb.cr.modify(|_, w| w.mburst().bits(m_burst.into())); } /// Sets the NDT register - pub fn set_ndt(&mut self, ndt: Ndt) { + fn set_ndt(&mut self, ndt: Ndt) { self.config_ndt = ndt; self.rb.ndtr.modify(|_, w| w.ndt().bits(ndt.into())); } /// Sets the Peripheral Address - pub fn set_pa(&mut self, pa: Pa) { + fn set_pa(&mut self, pa: Pa) { self.rb.par.modify(|_, w| w.pa().bits(pa.into())); } /// Sets the Memory-0 Address - pub fn set_m0a(&mut self, m0a: M0a) { + fn set_m0a(&mut self, m0a: M0a) { self.impl_set_m0a(m0a); } /// Sets the Memory-1 Address - pub fn set_m1a(&mut self, m1a: M1a) { + fn set_m1a(&mut self, m1a: M1a) { self.impl_set_m1a(m1a); } /// Sets the Fifo Threshold - pub fn set_fifo_threshold(&mut self, fifo_threshold: FifoThreshold) { + fn set_fifo_threshold(&mut self, fifo_threshold: FifoThreshold) { self.rb .fcr .modify(|_, w| w.fth().bits(fifo_threshold.into())); } /// Sets the Transfer Mode - pub fn set_transfer_mode(&mut self, transfer_mode: TransferMode) { + fn set_transfer_mode(&mut self, transfer_mode: TransferMode) { self.rb .fcr .modify(|_, w| w.dmdis().bit(transfer_mode.into())); } - - /// Returns the effective Flow Controller - /// - /// Read the documentation of `flow_controller` for more details. - pub fn effective_flow_controller(&self) -> FlowController { - if self.transfer_direction() == TransferDirection::M2M { - FlowController::Dma - } else { - self.flow_controller() - } - } - - /// Returns the effective Circular Mode - /// - /// Read the documentation of `circular_mode` for more details. - pub fn effective_circular_mode(&self) -> CircularMode { - if self.buffer_mode() == BufferMode::DoubleBuffer { - CircularMode::Enabled - } else { - self.circular_mode() - } - } - - /// Returns the effective Memory Size - /// - /// Read the documentation of `m_size` for more details. - pub fn effective_m_size(&self) -> MSize { - if self.transfer_mode() == TransferMode::Direct { - match self.p_size() { - PSize::Byte => MSize::Byte, - PSize::HalfWord => MSize::HalfWord, - PSize::Word => MSize::Word, - } - } else { - self.m_size() - } - } - - /// Returns the effective Peripheral Increment Offset - /// - /// Read the documentation of `pincos` for more details. - pub fn effective_pincos(&self) -> Option { - if self.pinc() == Pinc::Fixed { - return None; - } - - if self.transfer_mode() == TransferMode::Direct - || self.p_burst() != PBurst::Single - { - Some(Pincos::PSize) - } else { - Some(self.pincos()) - } - } - - /// Returns the effective Peripheral Burst - /// - /// Read the documentation of `p_burst` for more details. - pub fn effective_p_burst(&self) -> PBurst { - if self.transfer_mode() == TransferMode::Direct { - PBurst::Single - } else { - self.p_burst() - } - } - - /// Returns the effective Memory Burst - /// - /// Read the documentation of `m_burst` for more details. - pub fn effective_m_burst(&self) -> MBurst { - if self.transfer_mode() == TransferMode::Direct { - MBurst::Single - } else { - self.m_burst() - } - } } impl Stream @@ -730,7 +692,7 @@ where /// Checks the config for data integrity fn check_config(&self) { - if self.effective_circular_mode() == CircularMode::Enabled { + if self.circular_mode() == CircularMode::Enabled { self.check_config_circular(); } @@ -865,17 +827,6 @@ where self.transmute() } - - /// Returns the effective Peripheral Increment Offset - /// - /// Read the documentation of `pincos` for more details. - pub fn effective_pincos(&self) -> Option { - if self.pinc() == Pinc::Fixed { - None - } else { - Some(self.pincos()) - } - } } impl Stream diff --git a/src/dma/safe_transfer.rs b/src/dma/safe_transfer.rs index 6b90f6d5..744f27aa 100644 --- a/src/dma/safe_transfer.rs +++ b/src/dma/safe_transfer.rs @@ -1227,7 +1227,7 @@ pub(super) fn configure_safe_transfer( } } - if stream.effective_circular_mode() == CircularMode::Enabled { + if stream.circular_mode() == CircularMode::Enabled { if peripheral.is_write() { stream.set_transfer_direction(TransferDirection::M2P); } else { diff --git a/src/dma/stream.rs b/src/dma/stream.rs index 6da624fd..7c3a2993 100644 --- a/src/dma/stream.rs +++ b/src/dma/stream.rs @@ -272,6 +272,154 @@ pub struct Config { pub transfer_direction: TransferDirectionConf, } +impl Config { + pub fn transfer_direction(self) -> TransferDirection { + self.transfer_direction.into() + } + + pub fn transfer_mode(self) -> TransferMode { + match self.transfer_direction { + TransferDirectionConf::NotM2M(NotM2MConf { + transfer_mode, .. + }) => transfer_mode.into(), + TransferDirectionConf::M2M(_) => TransferMode::Fifo, + } + } + + pub fn flow_controller(self) -> FlowController { + match self.transfer_direction { + TransferDirectionConf::NotM2M(NotM2MConf { flow, .. }) => { + flow.into() + } + TransferDirectionConf::M2M(_) => FlowController::Dma, + } + } + + pub fn circular_mode(self) -> CircularMode { + match self.transfer_direction { + TransferDirectionConf::NotM2M(NotM2MConf { + flow: FlowControllerConf::Dma(circular_mode), + .. + }) => circular_mode.into(), + _ => CircularMode::Disabled, + } + } + + pub fn buffer_mode(self) -> BufferMode { + match self.transfer_direction { + TransferDirectionConf::NotM2M(NotM2MConf { + flow: + FlowControllerConf::Dma(CircularModeConf::Enabled(buffer_mode)), + .. + }) => buffer_mode.into(), + _ => BufferMode::Regular, + } + } + + pub fn fifo_threshold(self) -> Option { + match self.transfer_direction { + TransferDirectionConf::NotM2M(NotM2MConf { + transfer_mode: + TransferModeConf::Fifo(FifoConf { fifo_threshold, .. }), + .. + }) => Some(fifo_threshold), + TransferDirectionConf::M2M(FifoConf { fifo_threshold, .. }) => { + Some(fifo_threshold) + } + _ => None, + } + } + + pub fn p_burst(self) -> PBurst { + match self.transfer_direction { + TransferDirectionConf::NotM2M(NotM2MConf { + transfer_mode: TransferModeConf::Fifo(FifoConf { p_burst, .. }), + .. + }) => p_burst.into(), + TransferDirectionConf::M2M(FifoConf { p_burst, .. }) => { + p_burst.into() + } + _ => PBurst::Single, + } + } + + pub fn m_burst(self) -> MBurst { + match self.transfer_direction { + TransferDirectionConf::NotM2M(NotM2MConf { + transfer_mode: TransferModeConf::Fifo(FifoConf { m_burst, .. }), + .. + }) => m_burst, + TransferDirectionConf::M2M(FifoConf { m_burst, .. }) => m_burst, + _ => MBurst::Single, + } + } + + pub fn m_size(self) -> MSize { + match self.transfer_direction { + TransferDirectionConf::NotM2M(NotM2MConf { + transfer_mode: TransferModeConf::Fifo(FifoConf { m_size, .. }), + .. + }) => m_size, + TransferDirectionConf::M2M(FifoConf { m_size, .. }) => m_size, + _ => match self.p_size { + PSize::Byte => MSize::Byte, + PSize::HalfWord => MSize::HalfWord, + PSize::Word => MSize::Word, + }, + } + } + + pub fn pincos(self) -> Pincos { + match self.transfer_direction { + TransferDirectionConf::NotM2M(NotM2MConf { + transfer_mode: + TransferModeConf::Fifo(FifoConf { + p_burst: PBurstConf::Single(pincos), + .. + }), + .. + }) => pincos, + TransferDirectionConf::M2M(FifoConf { + p_burst: PBurstConf::Single(pincos), + .. + }) => pincos, + _ => Pincos::PSize, + } + } + + pub fn current_target(self) -> CurrentTarget { + match self.transfer_direction { + TransferDirectionConf::NotM2M(NotM2MConf { + flow: + FlowControllerConf::Dma(CircularModeConf::Enabled( + BufferModeConf::DoubleBuffer(DoubleBufferConf { + current_target, + .. + }), + )), + .. + }) => current_target, + _ => CurrentTarget::M0a, + } + } + + pub fn m1a(self) -> Option { + match self.transfer_direction { + TransferDirectionConf::NotM2M(NotM2MConf { + flow: + FlowControllerConf::Dma(CircularModeConf::Enabled( + BufferModeConf::DoubleBuffer(DoubleBufferConf { + m1a, + .. + }), + )), + .. + }) => Some(m1a), + _ => None, + } + } +} + ///////////////////////////////////////////////////////////////////////// // # TRANSFER DIRECTION CONFIG ///////////////////////////////////////////////////////////////////////// @@ -282,6 +430,17 @@ pub enum TransferDirectionConf { NotM2M(NotM2MConf), } +impl From for TransferDirection { + fn from(conf: TransferDirectionConf) -> TransferDirection { + match conf { + TransferDirectionConf::NotM2M(NotM2MConf { + transfer_dir, .. + }) => transfer_dir.into(), + TransferDirectionConf::M2M(_) => TransferDirection::M2M, + } + } +} + ///////////////////////////////////////////////////////////////////////// // # NOT-M2M CONFIG ///////////////////////////////////////////////////////////////////////// @@ -303,6 +462,15 @@ pub enum TransferDirectionNotM2M { M2P, } +impl From for TransferDirection { + fn from(dir: TransferDirectionNotM2M) -> Self { + match dir { + TransferDirectionNotM2M::P2M => Self::P2M, + TransferDirectionNotM2M::M2P => Self::M2P, + } + } +} + ///////////////////////////////////////////////////////////////////////// // # TRANSFER MODE CONFIG ///////////////////////////////////////////////////////////////////////// @@ -313,6 +481,15 @@ pub enum TransferModeConf { Fifo(FifoConf), } +impl From for TransferMode { + fn from(conf: TransferModeConf) -> Self { + match conf { + TransferModeConf::Fifo(_) => Self::Fifo, + TransferModeConf::Direct => Self::Direct, + } + } +} + ///////////////////////////////////////////////////////////////////////// // # FLOW CONTROLLER CONFIG ///////////////////////////////////////////////////////////////////////// @@ -323,6 +500,15 @@ pub enum FlowControllerConf { Peripheral, } +impl From for FlowController { + fn from(conf: FlowControllerConf) -> Self { + match conf { + FlowControllerConf::Dma(_) => Self::Dma, + FlowControllerConf::Peripheral => Self::Peripheral, + } + } +} + ///////////////////////////////////////////////////////////////////////// // # FIFO CONFIG ///////////////////////////////////////////////////////////////////////// @@ -347,6 +533,17 @@ pub enum PBurstConf { Incr16, } +impl From for PBurst { + fn from(conf: PBurstConf) -> Self { + match conf { + PBurstConf::Single(_) => Self::Single, + PBurstConf::Incr4 => Self::Incr4, + PBurstConf::Incr8 => Self::Incr8, + PBurstConf::Incr16 => Self::Incr16, + } + } +} + ///////////////////////////////////////////////////////////////////////// // # CIRCULAR CONFIG ///////////////////////////////////////////////////////////////////////// @@ -357,6 +554,15 @@ pub enum CircularModeConf { Enabled(BufferModeConf), } +impl From for CircularMode { + fn from(conf: CircularModeConf) -> Self { + match conf { + CircularModeConf::Disabled => Self::Disabled, + CircularModeConf::Enabled(_) => Self::Enabled, + } + } +} + ///////////////////////////////////////////////////////////////////////// // # BUFFER MODE CONFIG ///////////////////////////////////////////////////////////////////////// @@ -367,6 +573,15 @@ pub enum BufferModeConf { DoubleBuffer(DoubleBufferConf), } +impl From for BufferMode { + fn from(conf: BufferModeConf) -> Self { + match conf { + BufferModeConf::Regular => Self::Regular, + BufferModeConf::DoubleBuffer(_) => Self::DoubleBuffer, + } + } +} + ///////////////////////////////////////////////////////////////////////// // # DOUBLE BUFFER CONFIG ///////////////////////////////////////////////////////////////////////// @@ -1286,8 +1501,9 @@ where ///////////////////////////////////////////////////////////////////////// pub trait ITransferDirection: DefaultTraits + private::Sealed { - const TRANSFER_DIRECTION: Option; + const TRANSFER_DIRECTION: TransferDirection; + #[doc(hidden)] fn build< C_TransferMode, C_FlowController, @@ -1319,9 +1535,9 @@ impl private::Sealed for M2P {} impl private::Sealed for M2M {} impl ITransferDirection for P2M { - const TRANSFER_DIRECTION: Option = - Some(TransferDirection::P2M); + const TRANSFER_DIRECTION: TransferDirection = TransferDirection::P2M; + #[doc(hidden)] fn build< C_TransferMode, C_FlowController, @@ -1349,9 +1565,9 @@ impl ITransferDirection for P2M { } impl ITransferDirection for M2P { - const TRANSFER_DIRECTION: Option = - Some(TransferDirection::M2P); + const TRANSFER_DIRECTION: TransferDirection = TransferDirection::M2P; + #[doc(hidden)] fn build< C_TransferMode, C_FlowController, @@ -1379,9 +1595,9 @@ impl ITransferDirection for M2P { } impl ITransferDirection for M2M { - const TRANSFER_DIRECTION: Option = - Some(TransferDirection::M2M); + const TRANSFER_DIRECTION: TransferDirection = TransferDirection::M2M; + #[doc(hidden)] fn build< C_TransferMode, C_FlowController, @@ -1417,8 +1633,9 @@ impl NotM2M for M2P {} ///////////////////////////////////////////////////////////////////////// pub trait ITransferMode: DefaultTraits + private::Sealed { - const TRANSFER_MODE: Option; + const TRANSFER_MODE: TransferMode; + #[doc(hidden)] fn build(self, p_burst: C_PBurst) -> TransferModeConf where C_PBurst: IPBurst; @@ -1438,8 +1655,9 @@ impl private::Sealed for Direct {} impl private::Sealed for Fifo {} impl ITransferMode for Direct { - const TRANSFER_MODE: Option = Some(TransferMode::Direct); + const TRANSFER_MODE: TransferMode = TransferMode::Direct; + #[doc(hidden)] fn build(self, _: C_PBurst) -> TransferModeConf where C_PBurst: IPBurst, @@ -1448,7 +1666,7 @@ impl ITransferMode for Direct { } } impl ITransferMode for Fifo { - const TRANSFER_MODE: Option = Some(TransferMode::Fifo); + const TRANSFER_MODE: TransferMode = TransferMode::Fifo; fn build(self, p_burst: C_PBurst) -> TransferModeConf where @@ -1470,8 +1688,9 @@ impl ITransferMode for Fifo { ///////////////////////////////////////////////////////////////////////// pub trait IFlowController: DefaultTraits + private::Sealed { - const FLOW_CONTROLLER: Option; + const FLOW_CONTROLLER: FlowController; + #[doc(hidden)] fn build( buffer_mode: C_BufferMode, ) -> FlowControllerConf @@ -1489,8 +1708,9 @@ impl private::Sealed for Dma {} impl private::Sealed for Peripheral {} impl IFlowController for Dma { - const FLOW_CONTROLLER: Option = Some(FlowController::Dma); + const FLOW_CONTROLLER: FlowController = FlowController::Dma; + #[doc(hidden)] fn build( buffer_mode: C_BufferMode, ) -> FlowControllerConf @@ -1502,8 +1722,7 @@ impl IFlowController for Dma { } } impl IFlowController for Peripheral { - const FLOW_CONTROLLER: Option = - Some(FlowController::Peripheral); + const FLOW_CONTROLLER: FlowController = FlowController::Peripheral; fn build( _: C_BufferMode, @@ -1521,8 +1740,9 @@ impl IFlowController for Peripheral { ///////////////////////////////////////////////////////////////////////// pub trait ICircularMode: DefaultTraits + private::Sealed { - const CIRCULAR_MODE: Option; + const CIRCULAR_MODE: CircularMode; + #[doc(hidden)] fn build(buffer_mode: C_BufferMode) -> CircularModeConf where C_BufferMode: IBufferMode; @@ -1537,8 +1757,9 @@ impl private::Sealed for Circular {} impl private::Sealed for NotCircular {} impl ICircularMode for Circular { - const CIRCULAR_MODE: Option = Some(CircularMode::Enabled); + const CIRCULAR_MODE: CircularMode = CircularMode::Enabled; + #[doc(hidden)] fn build(buffer_mode: C_BufferMode) -> CircularModeConf where C_BufferMode: IBufferMode, @@ -1547,7 +1768,7 @@ impl ICircularMode for Circular { } } impl ICircularMode for NotCircular { - const CIRCULAR_MODE: Option = Some(CircularMode::Disabled); + const CIRCULAR_MODE: CircularMode = CircularMode::Disabled; fn build(_: C_BufferMode) -> CircularModeConf where @@ -1562,8 +1783,9 @@ impl ICircularMode for NotCircular { ///////////////////////////////////////////////////////////////////////// pub trait IBufferMode: DefaultTraits + private::Sealed { - const BUFFER_MODE: Option; + const BUFFER_MODE: BufferMode; + #[doc(hidden)] fn build(self) -> BufferModeConf; } @@ -1579,15 +1801,17 @@ impl private::Sealed for RegularBuffer {} impl private::Sealed for DoubleBuffer {} impl IBufferMode for RegularBuffer { - const BUFFER_MODE: Option = Some(BufferMode::Regular); + const BUFFER_MODE: BufferMode = BufferMode::Regular; + #[doc(hidden)] fn build(self) -> BufferModeConf { BufferModeConf::Regular } } impl IBufferMode for DoubleBuffer { - const BUFFER_MODE: Option = Some(BufferMode::DoubleBuffer); + const BUFFER_MODE: BufferMode = BufferMode::DoubleBuffer; + #[doc(hidden)] fn build(self) -> BufferModeConf { let conf = DoubleBufferConf { current_target: self.current_target.unwrap(), @@ -1603,8 +1827,9 @@ impl IBufferMode for DoubleBuffer { ///////////////////////////////////////////////////////////////////////// pub trait IPBurst: DefaultTraits + private::Sealed { - const P_BURST: Option; + const P_BURST: PBurst; + #[doc(hidden)] fn build(self) -> PBurstConf; } @@ -1625,32 +1850,36 @@ impl private::Sealed for Incr8 {} impl private::Sealed for Incr16 {} impl IPBurst for Single { - const P_BURST: Option = Some(PBurst::Single); + const P_BURST: PBurst = PBurst::Single; + #[doc(hidden)] fn build(self) -> PBurstConf { PBurstConf::Single(self.pincos.unwrap()) } } impl IPBurst for Incr4 { - const P_BURST: Option = Some(PBurst::Incr4); + const P_BURST: PBurst = PBurst::Incr4; + #[doc(hidden)] fn build(self) -> PBurstConf { PBurstConf::Incr4 } } impl IPBurst for Incr8 { - const P_BURST: Option = Some(PBurst::Incr8); + const P_BURST: PBurst = PBurst::Incr8; + #[doc(hidden)] fn build(self) -> PBurstConf { PBurstConf::Incr8 } } impl IPBurst for Incr16 { - const P_BURST: Option = Some(PBurst::Incr16); + const P_BURST: PBurst = PBurst::Incr16; + #[doc(hidden)] fn build(self) -> PBurstConf { PBurstConf::Incr16 } From 9eeee2c55c4f8b22394ba989bcab8b652d23b130 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ad=C3=A4?= Date: Sun, 29 Mar 2020 12:56:47 +0200 Subject: [PATCH 072/103] Made stream setters private and removed effective_CONF methods --- src/dma/mod.rs | 106 +++---------------------------------------------- 1 file changed, 5 insertions(+), 101 deletions(-) diff --git a/src/dma/mod.rs b/src/dma/mod.rs index b39b19c3..17a775f2 100644 --- a/src/dma/mod.rs +++ b/src/dma/mod.rs @@ -178,7 +178,7 @@ where } /// Sets the Transfer Complete Interrupt config flag - pub fn set_transfer_complete_interrupt( + fn set_transfer_complete_interrupt( &mut self, tc_intrpt: TransferCompleteInterrupt, ) { @@ -191,7 +191,7 @@ where } /// Sets the Half Transfer Interrupt config flag - pub fn set_half_transfer_interrupt( + fn set_half_transfer_interrupt( &mut self, ht_intrpt: HalfTransferInterrupt, ) { @@ -204,7 +204,7 @@ where } /// Sets the Transfer Error Interrupt config flag - pub fn set_transfer_error_interrupt( + fn set_transfer_error_interrupt( &mut self, te_intrpt: TransferErrorInterrupt, ) { @@ -217,7 +217,7 @@ where } /// Sets the Direct Mode Error Interrupt config flag - pub fn set_direct_mode_error_interrupt( + fn set_direct_mode_error_interrupt( &mut self, dme_intrpt: DirectModeErrorInterrupt, ) { @@ -230,16 +230,11 @@ where } /// Sets the Fifo Error Interrupt config flag - pub fn set_fifo_error_interrupt(&mut self, fe_intrpt: FifoErrorInterrupt) { + fn set_fifo_error_interrupt(&mut self, fe_intrpt: FifoErrorInterrupt) { self.rb.fcr.modify(|_, w| w.feie().bit(fe_intrpt.into())); } /// Returns the Flow Controller - /// - /// **Note** (for disabled streams): - /// This config value gets forced to `Dma`, if `transfer_direction` is `M2M`. - /// - /// This invariant are covered in `effective_flow_controller` (defined for disabled streams). pub fn flow_controller(&self) -> FlowController { self.rb.cr.read().pfctrl().bit().into() } @@ -250,14 +245,6 @@ where } /// Returns the Circular Mode - /// - /// **Note** (for disabled streams): - /// This config value gets forced - /// - /// - **by hardware** to `Enabled`, if `buffer_mode` is `DoubleBuffer`. - /// - **by software** to `Disabled` if `transfer_direction` is `M2M`. - /// - /// These invariants is covered in `effective_circular_mode`. pub fn circular_mode(&self) -> CircularMode { self.rb.cr.read().circ().bit().into() } @@ -278,23 +265,11 @@ where } /// Returns the Memory Size - /// - /// **Note** (for disabled streams): - /// This config value gets forced to `p_size`, if `transfer_mode` is `Direct`. - /// - /// This invariant is covered in `effective_m_size`. pub fn m_size(&self) -> MSize { self.rb.cr.read().msize().bits().try_into().unwrap() } /// Returns the Peripheral Increment Offset - /// - /// **Note** (for disabled and enabled streams): - /// - /// - This config value has no meaning, if `pinc` is `Fixed`. - /// - This config value gets forced to `PSize`, if `p_burst` is not `Single`. - /// - /// These invariants are covered in `effective_pincos` (defined for disabled and enabled streams). pub fn pincos(&self) -> Pincos { self.rb.cr.read().pincos().bit().into() } @@ -305,58 +280,21 @@ where } /// Returns the Buffer Mode - /// - /// **Note** (for disabled streams): - /// This config value gets forced to `Regular` **by software** (to avoid TransferError-Flag), if - /// - /// - `TransferDirection` is `M2M` or - /// - `FlowController` is `Peripheral` - /// - /// These invariants are covered in `effective_buffer_mode` (defined for disabled streams). pub fn buffer_mode(&self) -> BufferMode { self.rb.cr.read().dbm().bit().into() } /// Returns the Current Target - /// - /// **Note** (for disabled and enabled streams): - /// This config value has no meaning, if `BufferMode` is `Regular`. - /// - /// This invariant is covered in `effective_current_target`. pub fn current_target(&self) -> CurrentTarget { self.rb.cr.read().ct().bit().into() } - /// Returns the effective Current Target - /// - /// Read the documentation of `current_target` for more details. - /// - /// **Note**: If this config value has no meaning (because `BufferMode` is `Regular`), - /// the method returns `CurrentTarget::M0a`. - pub fn effective_current_target(&self) -> CurrentTarget { - if self.buffer_mode() == BufferMode::Regular { - CurrentTarget::M0a - } else { - self.current_target() - } - } - /// Returns the Peripheral Burst config flag - /// - /// **Note** (for disabled streams): - /// This config value gets forced to `Single`, if `transfer_mode` is `Direct`. - /// - /// This invariant is covered in `effective_p_burst` (defined for disabled streams). pub fn p_burst(&self) -> PBurst { self.rb.cr.read().pburst().bits().try_into().unwrap() } /// Returns the Memory Burst config flag - /// - /// **Note** (for disabled streams): - /// This config value gets forced to `Single`, if `transfer_mode` is `Direct`. - /// - /// This invariant is covered in `effective_m_burst` (defined for disabled streams). pub fn m_burst(&self) -> MBurst { self.rb.cr.read().mburst().bits().try_into().unwrap() } @@ -382,49 +320,15 @@ where } /// Returns the Memory-1 Address - /// - /// **Note** (for disabled and enabled streams): - /// This config value has no meaning, if `buffer_mode` is `Regular`. - /// - /// This invariant is covered in `effective_m1a` (defined for disabled and enabled streams). pub fn m1a(&self) -> M1a { self.rb.m1ar.read().m1a().bits().into() } - /// Returns the effective Memory-1 Address - /// - /// Read the documentation of `m1a` for more details. - pub fn effective_m1a(&self) -> Option { - if self.buffer_mode() == BufferMode::Regular { - None - } else { - Some(self.m1a()) - } - } - /// Returns the Fifo Threshold - /// - /// **Note** (for disabled and enabled streams): - /// This config value has no meaning, if `transfer_mode` is `Direct`. - /// - /// This invariant is covered in `effective_fifo_threshold` (defined for disabled and enabled streams). pub fn fifo_threshold(&self) -> FifoThreshold { self.rb.fcr.read().fth().bits().try_into().unwrap() } - /// Returns the effective Fifo Threshold. - /// - /// If the Fifo Threshold has no meaning, `None` is being returned. - /// - /// Read the documentation of `fifo_threshold` for more details. - pub fn effective_fifo_threshold(&self) -> Option { - if self.transfer_mode() == TransferMode::Direct { - None - } else { - Some(self.fifo_threshold()) - } - } - /// Returns the Transfer Mode (`Direct` or `Fifo` Mode) pub fn transfer_mode(&self) -> TransferMode { self.rb.fcr.read().dmdis().bit().into() From 1afd27f9b3273327fd9e897809691d042bc360e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ad=C3=A4?= Date: Sun, 29 Mar 2020 14:19:40 +0200 Subject: [PATCH 073/103] update --- src/dma/mod.rs | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/src/dma/mod.rs b/src/dma/mod.rs index 17a775f2..891dd6b7 100644 --- a/src/dma/mod.rs +++ b/src/dma/mod.rs @@ -320,13 +320,22 @@ where } /// Returns the Memory-1 Address - pub fn m1a(&self) -> M1a { - self.rb.m1ar.read().m1a().bits().into() + pub fn m1a(&self) -> Option { + if self.buffer_mode() == BufferMode::DoubleBuffer { + Some(self.rb.m1ar.read().m1a().bits().into()) + } else { + None + } + } /// Returns the Fifo Threshold - pub fn fifo_threshold(&self) -> FifoThreshold { - self.rb.fcr.read().fth().bits().try_into().unwrap() + pub fn fifo_threshold(&self) -> Option { + if self.transfer_mode() == TransferMode::Fifo { + Some(self.rb.fcr.read().fth().bits().try_into().unwrap()) + } else { + None + } } /// Returns the Transfer Mode (`Direct` or `Fifo` Mode) @@ -672,7 +681,7 @@ where let m_size = self.m_size().into_num(); let m_burst = self.m_burst().into_num(); // Fifo Size in bytes - let fifo_size = self.fifo_threshold().into_num() * 4; + let fifo_size = self.fifo_threshold().unwrap().into_num() * 4; if m_size * m_burst > fifo_size { panic!("FIFO configuration invalid, because `msize * mburst > fifo_size`"); @@ -693,7 +702,7 @@ where const FULL_FIFO_BYTES: usize = 16; if p_burst * p_size == FULL_FIFO_BYTES - && self.fifo_threshold() == FifoThreshold::F3_4 + && self.fifo_threshold().unwrap() == FifoThreshold::F3_4 { panic!( "FIFO configuration invalid, because \ From 80bbbc74cb8633f73968c9ddad039b4e40a9dfb0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ad=C3=A4?= Date: Mon, 30 Mar 2020 15:09:40 +0200 Subject: [PATCH 074/103] Implemented getter of config for stream --- src/dma/mod.rs | 113 ++++++++++++++++++++++++++++++++++++++++++---- src/dma/stream.rs | 13 ++++++ 2 files changed, 118 insertions(+), 8 deletions(-) diff --git a/src/dma/mod.rs b/src/dma/mod.rs index 891dd6b7..e8728482 100644 --- a/src/dma/mod.rs +++ b/src/dma/mod.rs @@ -32,13 +32,15 @@ use self::safe_transfer::{ PointerPort, Start, TransferState, }; use self::stream::{ - BufferMode, CircularMode, Config, CurrentTarget, DirectModeErrorInterrupt, - Disabled, Enabled, Error, Event, FifoErrorInterrupt, FifoThreshold, - FlowController, HalfTransferInterrupt, IntoNum, IsrCleared, - IsrState as IIsrState, IsrUncleared, M0a, M1a, MBurst, MSize, Minc, Ndt, - PBurst, PSize, Pa, Pinc, Pincos, PriorityLevel, StreamIsr, - TransferCompleteInterrupt, TransferDirection, TransferErrorInterrupt, - TransferMode, ED as IED, + BufferMode, BufferModeConf, CircularMode, CircularModeConf, Config, + CurrentTarget, DirectModeErrorInterrupt, Disabled, DoubleBufferConf, + Enabled, Error, Event, FifoConf, FifoErrorInterrupt, FifoThreshold, + FlowController, FlowControllerConf, HalfTransferInterrupt, IntoNum, + IsrCleared, IsrState as IIsrState, IsrUncleared, M0a, M1a, MBurst, MSize, + Minc, Ndt, NotM2MConf, PBurst, PBurstConf, PSize, Pa, Pinc, Pincos, + PriorityLevel, StreamIsr, TransferCompleteInterrupt, TransferDirection, + TransferDirectionConf, TransferErrorInterrupt, TransferMode, + TransferModeConf, ED as IED, }; use crate::nb::{self, block, Error as NbError}; use crate::private; @@ -162,6 +164,102 @@ where ED: IED, IsrState: IIsrState, { + pub fn config(&self) -> Config { + Config { + transfer_complete_interrupt: self.transfer_complete_interrupt(), + half_transfer_interrupt: self.half_transfer_interrupt(), + transfer_error_interrupt: self.transfer_error_interrupt(), + direct_mode_error_interrupt: self.direct_mode_error_interrupt(), + fifo_error_interrupt: self.fifo_error_interrupt(), + pinc: self.pinc(), + minc: self.minc(), + priority_level: self.priority_level(), + p_size: self.p_size(), + ndt: self.ndt(), + pa: self.pa(), + m0a: self.m0a(), + transfer_direction: self.transfer_direction_config(), + } + } + + fn transfer_direction_config(&self) -> TransferDirectionConf { + match self.transfer_direction() { + TransferDirection::P2M | TransferDirection::M2P => { + TransferDirectionConf::NotM2M(self.not_m2m_config()) + } + TransferDirection::M2M => { + TransferDirectionConf::M2M(self.fifo_config()) + } + } + } + + fn not_m2m_config(&self) -> NotM2MConf { + NotM2MConf { + transfer_dir: self.transfer_direction().try_into().unwrap(), + transfer_mode: self.transfer_mode_config(), + flow: self.flow_controller_config(), + } + } + + fn transfer_mode_config(&self) -> TransferModeConf { + match self.transfer_mode() { + TransferMode::Direct => TransferModeConf::Direct, + TransferMode::Fifo => TransferModeConf::Fifo(self.fifo_config()), + } + } + + fn flow_controller_config(&self) -> FlowControllerConf { + match self.flow_controller() { + FlowController::Dma => { + FlowControllerConf::Dma(self.circular_mode_config()) + } + FlowController::Peripheral => FlowControllerConf::Peripheral, + } + } + + fn circular_mode_config(&self) -> CircularModeConf { + match self.circular_mode() { + CircularMode::Disabled => CircularModeConf::Disabled, + CircularMode::Enabled => { + CircularModeConf::Enabled(self.buffer_mode_config()) + } + } + } + + fn buffer_mode_config(&self) -> BufferModeConf { + match self.buffer_mode() { + BufferMode::Regular => BufferModeConf::Regular, + BufferMode::DoubleBuffer => { + BufferModeConf::DoubleBuffer(self.double_buffer_config()) + } + } + } + + fn double_buffer_config(&self) -> DoubleBufferConf { + DoubleBufferConf { + current_target: self.current_target(), + m1a: self.m1a().unwrap(), + } + } + + fn fifo_config(&self) -> FifoConf { + FifoConf { + fifo_threshold: self.fifo_threshold().unwrap(), + p_burst: self.p_burst_config(), + m_burst: self.m_burst(), + m_size: self.m_size(), + } + } + + fn p_burst_config(&self) -> PBurstConf { + match self.p_burst() { + PBurst::Single => PBurstConf::Single(self.pincos()), + PBurst::Incr4 => PBurstConf::Incr4, + PBurst::Incr8 => PBurstConf::Incr8, + PBurst::Incr16 => PBurstConf::Incr16, + } + } + /// Returns the id of the Stream pub fn id(&self) -> usize { CXX::STREAM_ID @@ -326,7 +424,6 @@ where } else { None } - } /// Returns the Fifo Threshold diff --git a/src/dma/stream.rs b/src/dma/stream.rs index 7c3a2993..bed6842a 100644 --- a/src/dma/stream.rs +++ b/src/dma/stream.rs @@ -4,6 +4,7 @@ use super::utils::DefaultTraits; use super::DmaPeripheral; use crate::private; use crate::stm32::dma1::{HIFCR, HISR, LIFCR, LISR}; +use core::convert::TryFrom; use core::marker::PhantomData; type_state! { @@ -471,6 +472,18 @@ impl From for TransferDirection { } } +impl TryFrom for TransferDirectionNotM2M { + type Error = (); + + fn try_from(value: TransferDirection) -> Result { + match value { + TransferDirection::P2M => Ok(TransferDirectionNotM2M::P2M), + TransferDirection::M2P => Ok(TransferDirectionNotM2M::M2P), + _ => Err(()), + } + } +} + ///////////////////////////////////////////////////////////////////////// // # TRANSFER MODE CONFIG ///////////////////////////////////////////////////////////////////////// From 91b884b4bc9243255cf8e12de1365b8c48dd9fe1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ad=C3=A4?= Date: Thu, 2 Apr 2020 01:04:16 +0200 Subject: [PATCH 075/103] moved channel module into dma module --- src/dma/channel.rs | 49 ---------------------------------------- src/dma/mod.rs | 48 +++++++++++++++++++++++++++++++++++---- src/dma/safe_transfer.rs | 2 +- 3 files changed, 44 insertions(+), 55 deletions(-) delete mode 100644 src/dma/channel.rs diff --git a/src/dma/channel.rs b/src/dma/channel.rs deleted file mode 100644 index bb73358b..00000000 --- a/src/dma/channel.rs +++ /dev/null @@ -1,49 +0,0 @@ -//! DMA Channels - -use super::DmaPeripheral; -use crate::private; -use crate::stm32::{DMA1, DMA2}; - -pub trait ChannelId: Send + private::Sealed { - const STREAM_ID: usize; - const MUX_ID: usize; - - type DMA: DmaPeripheral; -} - -#[doc(hidden)] -macro_rules! channels { - ($($channel:ident => [$stream:tt, $mux:tt, $dma:ident]),*) => { - $( - pub struct $channel; - - impl crate::private::Sealed for $channel {} - - impl ChannelId for $channel { - const STREAM_ID: usize = $stream; - const MUX_ID: usize = $mux; - - type DMA = $dma; - } - )* - }; -} - -channels! { - C0 => [0, 0, DMA1], - C1 => [1, 1, DMA1], - C2 => [2, 2, DMA1], - C3 => [3, 3, DMA1], - C4 => [4, 4, DMA1], - C5 => [5, 5, DMA1], - C6 => [6, 6, DMA1], - C7 => [7, 7, DMA1], - C8 => [0, 8, DMA2], - C9 => [1, 9, DMA2], - C10 => [2, 10, DMA2], - C11 => [3, 11, DMA2], - C12 => [4, 12, DMA2], - C13 => [5, 13, DMA2], - C14 => [6, 14, DMA2], - C15 => [7, 15, DMA2] -} diff --git a/src/dma/mod.rs b/src/dma/mod.rs index e8728482..88dc9c41 100644 --- a/src/dma/mod.rs +++ b/src/dma/mod.rs @@ -5,16 +5,11 @@ #[macro_use] mod macros; -pub mod channel; pub mod mux; pub mod safe_transfer; pub mod stream; mod utils; -use self::channel::{ - ChannelId, C0, C1, C10, C11, C12, C13, C14, C15, C2, C3, C4, C5, C6, C7, - C8, C9, -}; use self::mux::request_gen::{ Disabled as GenDisabled, G0, G1, G2, G3, G4, G5, G6, G7, }; @@ -58,6 +53,49 @@ pub trait DmaPeripheral: Send + private::Sealed {} impl DmaPeripheral for DMA1 {} impl DmaPeripheral for DMA2 {} +pub trait ChannelId: Send + private::Sealed { + const STREAM_ID: usize; + const MUX_ID: usize; + + type DMA: DmaPeripheral; +} + +macro_rules! channels { + ($($channel:ident => [$stream:tt, $mux:tt, $dma:ident]),*) => { + $( + pub struct $channel; + + impl crate::private::Sealed for $channel {} + + impl ChannelId for $channel { + const STREAM_ID: usize = $stream; + const MUX_ID: usize = $mux; + + type DMA = $dma; + } + )* + }; +} + +channels! { + C0 => [0, 0, DMA1], + C1 => [1, 1, DMA1], + C2 => [2, 2, DMA1], + C3 => [3, 3, DMA1], + C4 => [4, 4, DMA1], + C5 => [5, 5, DMA1], + C6 => [6, 6, DMA1], + C7 => [7, 7, DMA1], + C8 => [0, 8, DMA2], + C9 => [1, 9, DMA2], + C10 => [2, 10, DMA2], + C11 => [3, 11, DMA2], + C12 => [4, 12, DMA2], + C13 => [5, 13, DMA2], + C14 => [6, 14, DMA2], + C15 => [7, 15, DMA2] +} + /// DMA Channel pub struct Channel where diff --git a/src/dma/safe_transfer.rs b/src/dma/safe_transfer.rs index 744f27aa..4e0904be 100644 --- a/src/dma/safe_transfer.rs +++ b/src/dma/safe_transfer.rs @@ -1,10 +1,10 @@ //! Safe DMA Transfers -use super::channel::ChannelId; use super::stream::{ CircularMode, Disabled, Enabled, IsrCleared, IsrUncleared, M0a, MSize, Minc, Ndt, PSize, Pa, Pinc, Pincos, TransferDirection, TransferMode, }; +use super::ChannelId; use super::{DmaPeripheral, Stream}; use crate::private; use core::convert::{TryFrom, TryInto}; From fe3d0af7e4c92295ae30973ad1c1710451247663 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ad=C3=A4?= Date: Thu, 2 Apr 2020 01:11:23 +0200 Subject: [PATCH 076/103] Removed dma::mux::shared module --- src/dma/mod.rs | 4 ++-- src/dma/mux/mod.rs | 18 +++++++++++++----- src/dma/mux/request_gen.rs | 19 +++++++++++++++++++ src/dma/mux/shared.rs | 30 ------------------------------ 4 files changed, 34 insertions(+), 37 deletions(-) delete mode 100644 src/dma/mux/shared.rs diff --git a/src/dma/mod.rs b/src/dma/mod.rs index 88dc9c41..f42ac946 100644 --- a/src/dma/mod.rs +++ b/src/dma/mod.rs @@ -11,10 +11,10 @@ pub mod stream; mod utils; use self::mux::request_gen::{ - Disabled as GenDisabled, G0, G1, G2, G3, G4, G5, G6, G7, + Disabled as GenDisabled, RequestGenIsr, G0, G1, G2, G3, G4, G5, G6, G7, }; use self::mux::request_ids::{ReqNone, RequestId as IRequestId, RequestIdSome}; -use self::mux::shared::{MuxIsr, RequestGenIsr}; +use self::mux::MuxIsr; use self::mux::{ EgDisabled, EgED as IEgED, EgEnabled, MuxShared, NbReq, OverrunError, RequestGenerator, RequestId, SyncDisabled, SyncED as ISyncED, SyncEnabled, diff --git a/src/dma/mux/mod.rs b/src/dma/mux/mod.rs index a8b1c8ec..da020597 100644 --- a/src/dma/mux/mod.rs +++ b/src/dma/mux/mod.rs @@ -1,14 +1,13 @@ //! DMA Mux pub mod request_gen; -pub mod shared; use self::request_gen::{ - Disabled as GenDisabled, Enabled as GenEnabled, GNbReq, GPol, GenId, SigId, - TriggerOverrunError, TriggerOverrunInterrupt, ED as GenED, + Disabled as GenDisabled, Enabled as GenEnabled, GNbReq, GPol, GenId, + RequestGenIsr, SigId, TriggerOverrunError, TriggerOverrunInterrupt, + ED as GenED, }; -use self::shared::{MuxIsr, RequestGenIsr}; -use crate::stm32::dmamux1::RGCR; +use crate::stm32::dmamux1::{CFR, CSR, RGCR}; use core::convert::TryInto; use core::marker::PhantomData; @@ -250,6 +249,15 @@ pub struct MuxShared { pub request_ids: RequestIds, } +pub struct MuxIsr { + pub(super) csr: &'static CSR, + /// This field *must not* be mutated using shared references + pub(super) cfr: &'static CFR, +} + +unsafe impl Send for MuxIsr {} +unsafe impl Sync for MuxIsr {} + impl MuxShared { pub(super) fn new(mux_isr: MuxIsr, req_gen_isr: RequestGenIsr) -> Self { MuxShared { diff --git a/src/dma/mux/request_gen.rs b/src/dma/mux/request_gen.rs index c48b85bb..09872dd0 100644 --- a/src/dma/mux/request_gen.rs +++ b/src/dma/mux/request_gen.rs @@ -1,6 +1,7 @@ //! DMA Request Generator use crate::private; +use crate::stm32::dmamux1::{RGCFR, RGSR}; type_state! { ED, Disabled, Enabled @@ -66,3 +67,21 @@ int_struct! { #[derive(Debug, Clone, Copy)] pub struct TriggerOverrunError; + +pub struct RequestGenIsr { + pub(super) rgsr: &'static RGSR, + /// This field *must not* be mutated using shared references + pub(super) rgcfr: &'static RGCFR, +} + +impl RequestGenIsr { + pub(in super::super) fn new( + rgsr: &'static RGSR, + rgcfr: &'static RGCFR, + ) -> Self { + RequestGenIsr { rgsr, rgcfr } + } +} + +unsafe impl Send for RequestGenIsr {} +unsafe impl Sync for RequestGenIsr {} diff --git a/src/dma/mux/shared.rs b/src/dma/mux/shared.rs deleted file mode 100644 index 2fce6af4..00000000 --- a/src/dma/mux/shared.rs +++ /dev/null @@ -1,30 +0,0 @@ -//! DMA Mux shared access objects - -use crate::stm32::dmamux1::{CFR, CSR, RGCFR, RGSR}; - -pub struct MuxIsr { - pub(in super::super) csr: &'static CSR, - /// This field *must not* be mutated using shared references - pub(in super::super) cfr: &'static CFR, -} - -unsafe impl Send for MuxIsr {} -unsafe impl Sync for MuxIsr {} - -pub struct RequestGenIsr { - pub(super) rgsr: &'static RGSR, - /// This field *must not* be mutated using shared references - pub(super) rgcfr: &'static RGCFR, -} - -impl RequestGenIsr { - pub(in super::super) fn new( - rgsr: &'static RGSR, - rgcfr: &'static RGCFR, - ) -> Self { - RequestGenIsr { rgsr, rgcfr } - } -} - -unsafe impl Send for RequestGenIsr {} -unsafe impl Sync for RequestGenIsr {} From 34bd18af7435e5f2efc8e0a3fc3b7eaaf7047ceb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ad=C3=A4?= Date: Thu, 2 Apr 2020 01:17:05 +0200 Subject: [PATCH 077/103] Fixed formatting --- src/dma/mux/mod.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/dma/mux/mod.rs b/src/dma/mux/mod.rs index da020597..2c67bfb5 100644 --- a/src/dma/mux/mod.rs +++ b/src/dma/mux/mod.rs @@ -249,15 +249,6 @@ pub struct MuxShared { pub request_ids: RequestIds, } -pub struct MuxIsr { - pub(super) csr: &'static CSR, - /// This field *must not* be mutated using shared references - pub(super) cfr: &'static CFR, -} - -unsafe impl Send for MuxIsr {} -unsafe impl Sync for MuxIsr {} - impl MuxShared { pub(super) fn new(mux_isr: MuxIsr, req_gen_isr: RequestGenIsr) -> Self { MuxShared { @@ -268,6 +259,15 @@ impl MuxShared { } } +pub struct MuxIsr { + pub(super) csr: &'static CSR, + /// This field *must not* be mutated using shared references + pub(super) cfr: &'static CFR, +} + +unsafe impl Send for MuxIsr {} +unsafe impl Sync for MuxIsr {} + pub struct OverrunError; pub struct RequestGenerator From def0fe3612d19d222fb92339404b8fddfc9f642f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ad=C3=A4?= Date: Thu, 9 Apr 2020 17:49:24 +0200 Subject: [PATCH 078/103] Implemented UsartDmaRx (not yet in submodule for conditional compilation) --- src/dma/mod.rs | 80 +++++++++++ src/serial.rs | 362 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 442 insertions(+) diff --git a/src/dma/mod.rs b/src/dma/mod.rs index f42ac946..5afcfe10 100644 --- a/src/dma/mod.rs +++ b/src/dma/mod.rs @@ -1183,6 +1183,86 @@ where pub fn clear_isr(&self, isr: &mut StreamIsr) { self.clear_isr_impl(isr); } + + pub fn wait_until_completed( + &self, + isr: &StreamIsr, + ) -> nb::Result<(), Error> { + match self.check_isr(isr) { + Ok(Some(Event::TransferComplete)) => Ok(()), + Err(err) => Err(NbError::Other(err)), + _ => Err(NbError::WouldBlock), + } + } + + pub fn wait_until_completed_clear( + &self, + isr: &mut StreamIsr, + ) -> nb::Result<(), Error> { + let res = self.wait_until_completed(isr); + + self.clear_isr_if_not_blocking(res, isr); + + res + } + + pub fn wait_until_half_transfer( + &self, + isr: &StreamIsr, + ) -> nb::Result<(), Error> { + match self.check_isr(isr) { + Ok(Some(Event::HalfTransfer)) => Ok(()), + Err(err) => Err(NbError::Other(err)), + _ => Err(NbError::WouldBlock), + } + } + + pub fn wait_until_half_transfer_clear( + &self, + isr: &mut StreamIsr, + ) -> nb::Result<(), Error> { + let res = self.wait_until_half_transfer(isr); + + self.clear_isr_if_not_blocking(res, isr); + + res + } + + pub fn wait_until_next_half( + &self, + isr: &StreamIsr, + ) -> nb::Result<(), Error> { + match self.check_isr(isr) { + Ok(event) => match event { + Some(Event::HalfTransfer) | Some(Event::TransferComplete) => { + Ok(()) + } + None => Err(NbError::WouldBlock), + }, + Err(err) => Err(NbError::Other(err)), + } + } + + pub fn wait_until_next_half_clear( + &self, + isr: &mut StreamIsr, + ) -> nb::Result<(), Error> { + let res = self.wait_until_next_half(isr); + + self.clear_isr_if_not_blocking(res, isr); + + res + } + + fn clear_isr_if_not_blocking( + &self, + res: nb::Result<(), Error>, + isr: &mut StreamIsr, + ) { + if !matches!(res, Err(NbError::WouldBlock)) { + self.clear_isr(isr); + } + } } unsafe impl Send for Stream diff --git a/src/serial.rs b/src/serial.rs index 3903df47..94c37b62 100644 --- a/src/serial.rs +++ b/src/serial.rs @@ -13,6 +13,7 @@ use crate::stm32::rcc::d2ccip2r; use crate::stm32::usart1::cr1::{M0_A as M0, PCE_A as PCE, PS_A as PS}; use stm32h7::Variant::Val; +use crate::stm32::usart1::RegisterBlock; use crate::stm32::{UART4, UART5, UART7, UART8}; use crate::stm32::{USART1, USART2, USART3, USART6}; @@ -35,7 +36,23 @@ use crate::gpio::{Alternate, AF11, AF14, AF4, AF6, AF7, AF8}; use crate::rcc::Ccdr; use crate::time::Hertz; +use crate::dma::mux::request_ids::{ + RequestIdSome, Uart4RxDma, Uart4TxDma, Uart5RxDma, Uart5TxDma, Uart7RxDma, + Uart7TxDma, Uart8RxDma, Uart8TxDma, Usart1RxDma, Usart1TxDma, Usart2RxDma, + Usart2TxDma, Usart3RxDma, Usart3TxDma, Usart6RxDma, Usart6TxDma, +}; +use crate::dma::mux::{EgED as IEgED, SyncED as ISyncED}; +use crate::dma::safe_transfer::{ + FixedBuffer, FixedBufferR, MemoryBufferStatic, Ongoing as TransferOngoing, + Payload, PeripheralBuffer, Start as TransferStart, +}; + +use crate::dma::stream::{ + Disabled as StreamDisabled, IsrCleared as StreamIsrCleared, StreamIsr, +}; +use crate::dma::{Channel, ChannelId, DmaMux, DmaPeripheral, SafeTransfer}; use crate::Never; +use core::ops::Deref; /// Serial error #[derive(Debug)] @@ -701,3 +718,348 @@ where Ok(()) } } + +pub trait SerialRequest: RequestIdSome {} + +impl SerialRequest for Usart1RxDma {} +impl SerialRequest for Usart1TxDma {} +impl SerialRequest for Usart2RxDma {} +impl SerialRequest for Usart2TxDma {} +impl SerialRequest for Usart3RxDma {} +impl SerialRequest for Usart3TxDma {} +impl SerialRequest for Usart6RxDma {} +impl SerialRequest for Usart6TxDma {} + +impl SerialRequest for Uart4RxDma {} +impl SerialRequest for Uart4TxDma {} +impl SerialRequest for Uart5RxDma {} +impl SerialRequest for Uart5TxDma {} +impl SerialRequest for Uart7RxDma {} +impl SerialRequest for Uart7TxDma {} +impl SerialRequest for Uart8RxDma {} +impl SerialRequest for Uart8TxDma {} + +pub trait SerialChannelDma { + type Rx: SerialRequest; + type Tx: SerialRequest; +} + +impl SerialChannelDma for USART1 { + type Rx = Usart1RxDma; + type Tx = Usart1TxDma; +} + +impl SerialChannelDma for USART2 { + type Rx = Usart2RxDma; + type Tx = Usart2TxDma; +} + +impl SerialChannelDma for USART3 { + type Rx = Usart3RxDma; + type Tx = Usart3TxDma; +} + +impl SerialChannelDma for USART6 { + type Rx = Usart6RxDma; + type Tx = Usart6TxDma; +} + +impl SerialChannelDma for UART4 { + type Rx = Uart4RxDma; + type Tx = Uart4TxDma; +} + +impl SerialChannelDma for UART5 { + type Rx = Uart5RxDma; + type Tx = Uart5TxDma; +} + +impl SerialChannelDma for UART7 { + type Rx = Uart7RxDma; + type Tx = Uart7TxDma; +} + +impl SerialChannelDma for UART8 { + type Rx = Uart8RxDma; + type Tx = Uart8TxDma; +} + +pub trait IState {} + +pub struct Start +where + CXX: ChannelId, + DMA: DmaPeripheral, + ReqId: SerialRequest, + SyncED: ISyncED, + EgED: IEgED, +{ + channel: Channel< + CXX, + DMA, + StreamDisabled, + StreamIsrCleared, + ReqId, + SyncED, + EgED, + >, +} + +pub struct Initialized +where + CXX: ChannelId, + DMA: DmaPeripheral, + ReqId: SerialRequest, + SyncED: ISyncED, + EgED: IEgED, + Peripheral: Payload, + Memory: Payload, +{ + channel: Channel< + CXX, + DMA, + StreamDisabled, + StreamIsrCleared, + ReqId, + SyncED, + EgED, + >, + transfer: SafeTransfer<'static, Peripheral, Memory, TransferStart>, +} + +pub struct Ongoing +where + CXX: ChannelId, + ReqId: SerialRequest, + SyncED: ISyncED, + EgED: IEgED, + Peripheral: Payload, + Memory: Payload, + DMA: DmaPeripheral, +{ + mux: DmaMux, + transfer: + SafeTransfer<'static, Peripheral, Memory, TransferOngoing>, +} + +impl IState + for Start +where + CXX: ChannelId, + DMA: DmaPeripheral, + ReqId: SerialRequest, + SyncED: ISyncED, + EgED: IEgED, +{ +} + +impl IState + for Initialized +where + CXX: ChannelId, + DMA: DmaPeripheral, + ReqId: SerialRequest, + SyncED: ISyncED, + EgED: IEgED, + Peripheral: Payload, + Memory: Payload, +{ +} + +impl IState + for Ongoing +where + CXX: ChannelId, + ReqId: SerialRequest, + SyncED: ISyncED, + EgED: IEgED, + Peripheral: Payload, + Memory: Payload, + DMA: DmaPeripheral, +{ +} + +pub struct SerialDmaRx +where + USART: SerialChannelDma + Deref, + State: IState, +{ + serial: Serial, + state: State, +} + +impl + SerialDmaRx> +where + USART: SerialChannelDma + Deref, + CXX: ChannelId, + DMA: DmaPeripheral, + SyncED: ISyncED, + EgED: IEgED, +{ + pub fn new( + serial: Serial, + channel: Channel< + CXX, + DMA, + StreamDisabled, + StreamIsrCleared, + USART::Rx, + SyncED, + EgED, + >, + ) -> Self { + let mut s = Self { + serial, + state: Start { channel }, + }; + + s.enable_dma_mode(); + + s + } + + pub fn init( + self, + memory: MemoryBufferStatic, + ) -> SerialDmaRx< + USART, + PINS, + Initialized, + > + where + Peripheral: Payload, + Memory: Payload, + { + if !memory.is_write() { + panic!("The memory buffer must be a Write-Buffer."); + } + + let pa = &self.serial.usart.rdr as *const _ as *const Peripheral; + let peripheral = PeripheralBuffer::Fixed(FixedBuffer::Read( + FixedBufferR::new(unsafe { &*pa }), + )); + + let transfer = SafeTransfer::new(peripheral, memory); + + SerialDmaRx { + serial: self.serial, + state: Initialized { + transfer, + channel: self.state.channel, + }, + } + } + + pub fn free( + mut self, + ) -> ( + Serial, + Channel< + CXX, + DMA, + StreamDisabled, + StreamIsrCleared, + USART::Rx, + SyncED, + EgED, + >, + ) { + self.disable_dma_mode(); + + (self.serial, self.state.channel) + } + + fn enable_dma_mode(&mut self) { + self.serial.usart.cr3.modify(|_, w| w.dmar().set_bit()); + } + + fn disable_dma_mode(&mut self) { + self.serial.usart.cr3.modify(|_, w| w.dmar().clear_bit()); + } +} + +impl + SerialDmaRx< + USART, + PINS, + Initialized, + > +where + USART: SerialChannelDma + Deref, + CXX: ChannelId, + DMA: DmaPeripheral, + SyncED: ISyncED, + EgED: IEgED, + Peripheral: Payload, + Memory: Payload, +{ + pub fn start( + self, + ) -> SerialDmaRx< + USART, + PINS, + Ongoing, + > { + let transfer = self.state.transfer.start(self.state.channel.stream); + + SerialDmaRx { + serial: self.serial, + state: Ongoing { + mux: self.state.channel.mux, + transfer, + }, + } + } +} + +impl + SerialDmaRx< + USART, + PINS, + Ongoing, + > +where + USART: SerialChannelDma + Deref, + CXX: ChannelId, + DMA: DmaPeripheral, + SyncED: ISyncED, + EgED: IEgED, + Peripheral: Payload, + Memory: Payload, +{ + pub fn transfer( + &self, + ) -> &SafeTransfer<'static, Peripheral, Memory, TransferOngoing> + { + &self.state.transfer + } + + pub fn transfer_mut( + &mut self, + ) -> &mut SafeTransfer<'static, Peripheral, Memory, TransferOngoing> + { + &mut self.state.transfer + } + + pub fn mux(&self) -> &DmaMux { + &self.state.mux + } + + pub fn stop( + self, + isr: &mut StreamIsr, + ) -> SerialDmaRx> + { + let stream = self.state.transfer.stop().clear_isr(isr); + let channel = Channel { + stream, + mux: self.state.mux, + }; + + SerialDmaRx { + serial: self.serial, + state: Start { channel }, + } + } +} From f2b94af9eb786c70670d8ddb2205985e94016261 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ad=C3=A4?= Date: Thu, 9 Apr 2020 18:32:08 +0200 Subject: [PATCH 079/103] Removed generic parameter `DMA` of Stream because unnecessary --- src/dma/mod.rs | 210 ++++++++++++++++++--------------------- src/dma/safe_transfer.rs | 38 +++---- src/serial.rs | 108 +++++++------------- 3 files changed, 142 insertions(+), 214 deletions(-) diff --git a/src/dma/mod.rs b/src/dma/mod.rs index 5afcfe10..4c364eea 100644 --- a/src/dma/mod.rs +++ b/src/dma/mod.rs @@ -97,25 +97,23 @@ channels! { } /// DMA Channel -pub struct Channel +pub struct Channel where - CXX: ChannelId, - DMA: DmaPeripheral, + CXX: ChannelId, StreamED: IED, IsrState: IIsrState, ReqId: IRequestId, SyncED: ISyncED, EgED: IEgED, { - pub stream: Stream, + pub stream: Stream, pub mux: DmaMux, } -impl - Channel +impl + Channel where - CXX: ChannelId, - DMA: DmaPeripheral, + CXX: ChannelId, StreamED: IED, IsrState: IIsrState, ReqId: IRequestId, @@ -126,11 +124,11 @@ where pub fn stream_owned( self, op: F, - ) -> Channel + ) -> Channel where F: FnOnce( - Stream, - ) -> Stream, + Stream, + ) -> Stream, NewStreamED: IED, NewIsrState: IIsrState, { @@ -146,7 +144,7 @@ where pub fn mux_owned( self, op: F, - ) -> Channel + ) -> Channel where F: FnOnce( DmaMux, @@ -165,23 +163,21 @@ where } /// DMA Stream -pub struct Stream +pub struct Stream where - CXX: ChannelId, - DMA: DmaPeripheral, + CXX: ChannelId, ED: IED, IsrState: IIsrState, { /// This field *must not* be mutated using shared references rb: &'static ST, config_ndt: Ndt, - _phantom_data: PhantomData<(CXX, DMA, ED, IsrState)>, + _phantom_data: PhantomData<(CXX, ED, IsrState)>, } -impl Stream +impl Stream where - CXX: ChannelId, - DMA: DmaPeripheral, + CXX: ChannelId, { /// Creates an instance of a Stream in initial state. /// @@ -195,10 +191,9 @@ where } } -impl Stream +impl Stream where - CXX: ChannelId, - DMA: DmaPeripheral, + CXX: ChannelId, ED: IED, IsrState: IIsrState, { @@ -489,9 +484,7 @@ where } /// Transmutes the state of `self` - fn transmute( - self, - ) -> Stream + fn transmute(self) -> Stream where NewED: IED, NewIsrState: IIsrState, @@ -504,10 +497,9 @@ where } } -impl Stream +impl Stream where - CXX: ChannelId, - DMA: DmaPeripheral, + CXX: ChannelId, IsrState: IIsrState, { pub fn apply_config(&mut self, config: Config) { @@ -658,10 +650,9 @@ where } } -impl Stream +impl Stream where - CXX: ChannelId, - DMA: DmaPeripheral, + CXX: ChannelId, IsrState: IIsrState, { /// Sets the Memory-0 Address on the fly @@ -706,17 +697,16 @@ where } } -impl Stream +impl Stream where - CXX: ChannelId, - DMA: DmaPeripheral, + CXX: ChannelId, { /// Checks the config for data integrity and enables the stream /// /// # Safety /// /// Aliasing rules aren't enforced. - pub unsafe fn enable(self) -> Stream { + pub unsafe fn enable(self) -> Stream { self.check_config(); self.enable_unchecked() @@ -730,9 +720,7 @@ where /// /// - Aliasing rules aren't enforced /// - Config is not checked for guaranteeing data integrity - pub unsafe fn enable_unchecked( - self, - ) -> Stream { + pub unsafe fn enable_unchecked(self) -> Stream { self.rb.cr.modify(|_, w| w.en().set_bit()); self.transmute() @@ -861,14 +849,13 @@ where } } -impl Stream +impl Stream where - CXX: ChannelId, - DMA: DmaPeripheral, + CXX: ChannelId, IsrState: IIsrState, { /// Disables the stream - pub fn disable(self) -> Stream { + pub fn disable(self) -> Stream { self.rb.cr.modify(|_, w| w.en().clear_bit()); while self.rb.cr.read().en().bit_is_set() {} @@ -877,10 +864,9 @@ where } } -impl Stream +impl Stream where - CXX: ChannelId, - DMA: DmaPeripheral, + CXX: ChannelId, ED: IED, { /// Returns the contents of the isr. @@ -889,7 +875,7 @@ where /// * If there are errors, the errors are being wrapped into `Error` and returned as `Err` pub fn check_isr( &self, - isr: &StreamIsr, + isr: &StreamIsr, ) -> Result, Error> { let transfer_error = self.transfer_error_flag(isr); let direct_mode_error = self.direct_mode_error_flag(isr); @@ -919,7 +905,7 @@ where } /// Returns the Transfer Complete flag - pub fn transfer_complete_flag(&self, isr: &StreamIsr) -> bool { + pub fn transfer_complete_flag(&self, isr: &StreamIsr) -> bool { match self.id() { 0 => isr.lisr.read().tcif0().bit_is_set(), 1 => isr.lisr.read().tcif1().bit_is_set(), @@ -934,7 +920,7 @@ where } /// Returns the Half Transfer flag - pub fn half_transfer_flag(&self, isr: &StreamIsr) -> bool { + pub fn half_transfer_flag(&self, isr: &StreamIsr) -> bool { match self.id() { 0 => isr.lisr.read().htif0().bit_is_set(), 1 => isr.lisr.read().htif1().bit_is_set(), @@ -949,7 +935,7 @@ where } /// Returns the Transfer Error flag - pub fn transfer_error_flag(&self, isr: &StreamIsr) -> bool { + pub fn transfer_error_flag(&self, isr: &StreamIsr) -> bool { match self.id() { 0 => isr.lisr.read().teif0().bit_is_set(), 1 => isr.lisr.read().teif1().bit_is_set(), @@ -964,7 +950,7 @@ where } /// Returns the Direct Mode Error flag - pub fn direct_mode_error_flag(&self, isr: &StreamIsr) -> bool { + pub fn direct_mode_error_flag(&self, isr: &StreamIsr) -> bool { match self.id() { 0 => isr.lisr.read().dmeif0().bit_is_set(), 1 => isr.lisr.read().dmeif1().bit_is_set(), @@ -979,7 +965,7 @@ where } /// Returns the Fifo Error flag - pub fn fifo_error_flag(&self, isr: &StreamIsr) -> bool { + pub fn fifo_error_flag(&self, isr: &StreamIsr) -> bool { match self.id() { 0 => isr.lisr.read().feif0().bit_is_set(), 1 => isr.lisr.read().feif1().bit_is_set(), @@ -994,7 +980,7 @@ where } /// Performs the ISR clear - fn clear_isr_impl(&self, isr: &mut StreamIsr) { + fn clear_isr_impl(&self, isr: &mut StreamIsr) { self.clear_transfer_complete(isr); self.clear_half_transfer(isr); self.clear_transfer_error(isr); @@ -1003,7 +989,7 @@ where } /// Clears the Transfer Complete flag - pub fn clear_transfer_complete(&self, isr: &mut StreamIsr) { + pub fn clear_transfer_complete(&self, isr: &mut StreamIsr) { match self.id() { 0 => { isr.lifcr.write(|w| w.ctcif0().set_bit()); @@ -1034,7 +1020,7 @@ where } /// Clears the Half Transfer flag - pub fn clear_half_transfer(&self, isr: &mut StreamIsr) { + pub fn clear_half_transfer(&self, isr: &mut StreamIsr) { match self.id() { 0 => { isr.lifcr.write(|w| w.chtif0().set_bit()); @@ -1065,7 +1051,7 @@ where } /// Clears the Transfer Error flag - pub fn clear_transfer_error(&self, isr: &mut StreamIsr) { + pub fn clear_transfer_error(&self, isr: &mut StreamIsr) { match self.id() { 0 => { isr.lifcr.write(|w| w.cteif0().set_bit()); @@ -1096,7 +1082,7 @@ where } /// Clears the Direct Mode Error flag - pub fn clear_direct_mode_error(&self, isr: &mut StreamIsr) { + pub fn clear_direct_mode_error(&self, isr: &mut StreamIsr) { match self.id() { 0 => { isr.lifcr.write(|w| w.cdmeif0().set_bit()); @@ -1127,7 +1113,7 @@ where } /// Clears the Fifo Error flag - pub fn clear_fifo_error(&self, isr: &mut StreamIsr) { + pub fn clear_fifo_error(&self, isr: &mut StreamIsr) { match self.id() { 0 => { isr.lifcr.write(|w| w.cfeif0().set_bit()); @@ -1158,35 +1144,33 @@ where } } -impl Stream +impl Stream where - CXX: ChannelId, - DMA: DmaPeripheral, + CXX: ChannelId, { /// Clears the ISR pub fn clear_isr( self, - isr: &mut StreamIsr, - ) -> Stream { + isr: &mut StreamIsr, + ) -> Stream { self.clear_isr_impl(isr); self.transmute() } } -impl Stream +impl Stream where - CXX: ChannelId, - DMA: DmaPeripheral, + CXX: ChannelId, { /// Clears the ISR - pub fn clear_isr(&self, isr: &mut StreamIsr) { + pub fn clear_isr(&self, isr: &mut StreamIsr) { self.clear_isr_impl(isr); } pub fn wait_until_completed( &self, - isr: &StreamIsr, + isr: &StreamIsr, ) -> nb::Result<(), Error> { match self.check_isr(isr) { Ok(Some(Event::TransferComplete)) => Ok(()), @@ -1197,7 +1181,7 @@ where pub fn wait_until_completed_clear( &self, - isr: &mut StreamIsr, + isr: &mut StreamIsr, ) -> nb::Result<(), Error> { let res = self.wait_until_completed(isr); @@ -1208,7 +1192,7 @@ where pub fn wait_until_half_transfer( &self, - isr: &StreamIsr, + isr: &StreamIsr, ) -> nb::Result<(), Error> { match self.check_isr(isr) { Ok(Some(Event::HalfTransfer)) => Ok(()), @@ -1219,7 +1203,7 @@ where pub fn wait_until_half_transfer_clear( &self, - isr: &mut StreamIsr, + isr: &mut StreamIsr, ) -> nb::Result<(), Error> { let res = self.wait_until_half_transfer(isr); @@ -1230,7 +1214,7 @@ where pub fn wait_until_next_half( &self, - isr: &StreamIsr, + isr: &StreamIsr, ) -> nb::Result<(), Error> { match self.check_isr(isr) { Ok(event) => match event { @@ -1245,7 +1229,7 @@ where pub fn wait_until_next_half_clear( &self, - isr: &mut StreamIsr, + isr: &mut StreamIsr, ) -> nb::Result<(), Error> { let res = self.wait_until_next_half(isr); @@ -1257,7 +1241,7 @@ where fn clear_isr_if_not_blocking( &self, res: nb::Result<(), Error>, - isr: &mut StreamIsr, + isr: &mut StreamIsr, ) { if !matches!(res, Err(NbError::WouldBlock)) { self.clear_isr(isr); @@ -1265,19 +1249,17 @@ where } } -unsafe impl Send for Stream +unsafe impl Send for Stream where - CXX: ChannelId, - DMA: DmaPeripheral, + CXX: ChannelId, ED: IED, IsrState: IIsrState, { } -unsafe impl Sync for Stream +unsafe impl Sync for Stream where - CXX: ChannelId, - DMA: DmaPeripheral, + CXX: ChannelId, ED: IED, IsrState: IIsrState, { @@ -1694,13 +1676,12 @@ where Dest: Payload, { /// Starts the transfer - pub fn start( + pub fn start( self, - mut stream: Stream, - ) -> SafeTransfer<'wo, Source, Dest, Ongoing> + mut stream: Stream, + ) -> SafeTransfer<'wo, Source, Dest, Ongoing> where - CXX: ChannelId, - DMA: DmaPeripheral, + CXX: ChannelId, { configure_safe_transfer(&mut stream, &self.peripheral, &self.memory); stream.set_buffer_mode(BufferMode::Regular); @@ -1715,15 +1696,14 @@ where } } -impl SafeTransfer<'_, Source, Dest, Ongoing> +impl SafeTransfer<'_, Source, Dest, Ongoing> where Source: Payload, Dest: Payload, - CXX: ChannelId, - DMA: DmaPeripheral, + CXX: ChannelId, { /// Returns the stream assigned to the transfer - pub fn stream(&self) -> &Stream { + pub fn stream(&self) -> &Stream { &self.state.stream } @@ -1767,7 +1747,7 @@ where } /// Stops the transfer, returning the stream - pub fn stop(self) -> Stream { + pub fn stop(self) -> Stream { self.state.stream.disable() } } @@ -1873,13 +1853,12 @@ where Memory: Payload, { /// Starts the transfer - pub fn start( + pub fn start( self, - mut stream: Stream, - ) -> SafeTransferDoubleBuffer<'wo, Peripheral, Memory, Ongoing> + mut stream: Stream, + ) -> SafeTransferDoubleBuffer<'wo, Peripheral, Memory, Ongoing> where - CXX: ChannelId, - DMA: DmaPeripheral, + CXX: ChannelId, { stream.set_buffer_mode(BufferMode::DoubleBuffer); stream.set_m1a(M1a(self.memories[1].as_ptr(Some(0)) as u32)); @@ -1900,16 +1879,15 @@ where } } -impl - SafeTransferDoubleBuffer<'_, Peripheral, Memory, Ongoing> +impl + SafeTransferDoubleBuffer<'_, Peripheral, Memory, Ongoing> where Peripheral: Payload, Memory: Payload, - CXX: ChannelId, - DMA: DmaPeripheral, + CXX: ChannelId, { /// Returns the stream assigned to the transfer - pub fn stream(&self) -> &Stream { + pub fn stream(&self) -> &Stream { &self.state.stream } @@ -1975,31 +1953,31 @@ where } /// Stops the transfer - pub fn stop(self) -> Stream { + pub fn stop(self) -> Stream { self.state.stream.disable() } } pub type ChannelsDma1 = ( - Channel, - Channel, - Channel, - Channel, - Channel, - Channel, - Channel, - Channel, + Channel, + Channel, + Channel, + Channel, + Channel, + Channel, + Channel, + Channel, ); pub type ChannelsDma2 = ( - Channel, - Channel, - Channel, - Channel, - Channel, - Channel, - Channel, - Channel, + Channel, + Channel, + Channel, + Channel, + Channel, + Channel, + Channel, + Channel, ); pub type RequestGenerators = ( diff --git a/src/dma/safe_transfer.rs b/src/dma/safe_transfer.rs index 4e0904be..98412102 100644 --- a/src/dma/safe_transfer.rs +++ b/src/dma/safe_transfer.rs @@ -4,8 +4,7 @@ use super::stream::{ CircularMode, Disabled, Enabled, IsrCleared, IsrUncleared, M0a, MSize, Minc, Ndt, PSize, Pa, Pinc, Pincos, TransferDirection, TransferMode, }; -use super::ChannelId; -use super::{DmaPeripheral, Stream}; +use super::{ChannelId, Stream}; use crate::private; use core::convert::{TryFrom, TryInto}; use core::fmt::Debug; @@ -18,27 +17,16 @@ pub struct Start; impl private::Sealed for Start {} impl TransferState for Start {} -pub struct Ongoing +pub struct Ongoing where - CXX: ChannelId, - DMA: DmaPeripheral, + CXX: ChannelId, { - pub(super) stream: Stream, + pub(super) stream: Stream, } -impl private::Sealed for Ongoing -where - CXX: ChannelId, - DMA: DmaPeripheral, -{ -} +impl private::Sealed for Ongoing where CXX: ChannelId {} -impl TransferState for Ongoing -where - CXX: ChannelId, - DMA: DmaPeripheral, -{ -} +impl TransferState for Ongoing where CXX: ChannelId {} /// # Safety /// @@ -1177,13 +1165,12 @@ where } } -pub(super) fn configure_safe_transfer( - stream: &mut Stream, +pub(super) fn configure_safe_transfer( + stream: &mut Stream, peripheral: &PeripheralBuffer, memory: &MemoryBuffer, ) where - CXX: ChannelId, - DMA: DmaPeripheral, + CXX: ChannelId, Peripheral: Payload, Memory: Payload, { @@ -1242,13 +1229,12 @@ pub(super) fn configure_safe_transfer( configure_ndt(stream, peripheral, memory); } -fn configure_ndt( - stream: &mut Stream, +fn configure_ndt( + stream: &mut Stream, peripheral: &PeripheralBuffer, memory: &MemoryBuffer, ) where - CXX: ChannelId, - DMA: DmaPeripheral, + CXX: ChannelId, Peripheral: Payload, Memory: Payload, { diff --git a/src/serial.rs b/src/serial.rs index 94c37b62..dfd34f98 100644 --- a/src/serial.rs +++ b/src/serial.rs @@ -50,7 +50,7 @@ use crate::dma::safe_transfer::{ use crate::dma::stream::{ Disabled as StreamDisabled, IsrCleared as StreamIsrCleared, StreamIsr, }; -use crate::dma::{Channel, ChannelId, DmaMux, DmaPeripheral, SafeTransfer}; +use crate::dma::{Channel, ChannelId, DmaMux, SafeTransfer}; use crate::Never; use core::ops::Deref; @@ -786,78 +786,57 @@ impl SerialChannelDma for UART8 { pub trait IState {} -pub struct Start +pub struct Start where - CXX: ChannelId, - DMA: DmaPeripheral, + CXX: ChannelId, ReqId: SerialRequest, SyncED: ISyncED, EgED: IEgED, { - channel: Channel< - CXX, - DMA, - StreamDisabled, - StreamIsrCleared, - ReqId, - SyncED, - EgED, - >, + channel: + Channel, } -pub struct Initialized +pub struct Initialized where - CXX: ChannelId, - DMA: DmaPeripheral, + CXX: ChannelId, ReqId: SerialRequest, SyncED: ISyncED, EgED: IEgED, Peripheral: Payload, Memory: Payload, { - channel: Channel< - CXX, - DMA, - StreamDisabled, - StreamIsrCleared, - ReqId, - SyncED, - EgED, - >, + channel: + Channel, transfer: SafeTransfer<'static, Peripheral, Memory, TransferStart>, } -pub struct Ongoing +pub struct Ongoing where - CXX: ChannelId, + CXX: ChannelId, ReqId: SerialRequest, SyncED: ISyncED, EgED: IEgED, Peripheral: Payload, Memory: Payload, - DMA: DmaPeripheral, { mux: DmaMux, - transfer: - SafeTransfer<'static, Peripheral, Memory, TransferOngoing>, + transfer: SafeTransfer<'static, Peripheral, Memory, TransferOngoing>, } -impl IState - for Start +impl IState for Start where - CXX: ChannelId, - DMA: DmaPeripheral, + CXX: ChannelId, ReqId: SerialRequest, SyncED: ISyncED, EgED: IEgED, { } -impl IState - for Initialized +impl IState + for Initialized where - CXX: ChannelId, - DMA: DmaPeripheral, + CXX: ChannelId, ReqId: SerialRequest, SyncED: ISyncED, EgED: IEgED, @@ -866,16 +845,15 @@ where { } -impl IState - for Ongoing +impl IState + for Ongoing where - CXX: ChannelId, + CXX: ChannelId, ReqId: SerialRequest, SyncED: ISyncED, EgED: IEgED, Peripheral: Payload, Memory: Payload, - DMA: DmaPeripheral, { } @@ -888,12 +866,11 @@ where state: State, } -impl - SerialDmaRx> +impl + SerialDmaRx> where USART: SerialChannelDma + Deref, - CXX: ChannelId, - DMA: DmaPeripheral, + CXX: ChannelId, SyncED: ISyncED, EgED: IEgED, { @@ -901,7 +878,6 @@ where serial: Serial, channel: Channel< CXX, - DMA, StreamDisabled, StreamIsrCleared, USART::Rx, @@ -925,7 +901,7 @@ where ) -> SerialDmaRx< USART, PINS, - Initialized, + Initialized, > where Peripheral: Payload, @@ -955,15 +931,7 @@ where mut self, ) -> ( Serial, - Channel< - CXX, - DMA, - StreamDisabled, - StreamIsrCleared, - USART::Rx, - SyncED, - EgED, - >, + Channel, ) { self.disable_dma_mode(); @@ -979,16 +947,15 @@ where } } -impl +impl SerialDmaRx< USART, PINS, - Initialized, + Initialized, > where USART: SerialChannelDma + Deref, - CXX: ChannelId, - DMA: DmaPeripheral, + CXX: ChannelId, SyncED: ISyncED, EgED: IEgED, Peripheral: Payload, @@ -999,7 +966,7 @@ where ) -> SerialDmaRx< USART, PINS, - Ongoing, + Ongoing, > { let transfer = self.state.transfer.start(self.state.channel.stream); @@ -1013,16 +980,15 @@ where } } -impl +impl SerialDmaRx< USART, PINS, - Ongoing, + Ongoing, > where USART: SerialChannelDma + Deref, - CXX: ChannelId, - DMA: DmaPeripheral, + CXX: ChannelId, SyncED: ISyncED, EgED: IEgED, Peripheral: Payload, @@ -1030,14 +996,13 @@ where { pub fn transfer( &self, - ) -> &SafeTransfer<'static, Peripheral, Memory, TransferOngoing> - { + ) -> &SafeTransfer<'static, Peripheral, Memory, TransferOngoing> { &self.state.transfer } pub fn transfer_mut( &mut self, - ) -> &mut SafeTransfer<'static, Peripheral, Memory, TransferOngoing> + ) -> &mut SafeTransfer<'static, Peripheral, Memory, TransferOngoing> { &mut self.state.transfer } @@ -1048,9 +1013,8 @@ where pub fn stop( self, - isr: &mut StreamIsr, - ) -> SerialDmaRx> - { + isr: &mut StreamIsr, + ) -> SerialDmaRx> { let stream = self.state.transfer.stop().clear_isr(isr); let channel = Channel { stream, From f3c596fdc4714d738f5cbd53b6a90ccb5253b88d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ad=C3=A4?= Date: Thu, 9 Apr 2020 18:44:29 +0200 Subject: [PATCH 080/103] Moved usart dma code into sumbodule --- src/serial/dma.rs | 328 ++++++++++++++++++++++++++++++ src/{serial.rs => serial/mod.rs} | 329 +------------------------------ 2 files changed, 331 insertions(+), 326 deletions(-) create mode 100644 src/serial/dma.rs rename src/{serial.rs => serial/mod.rs} (73%) diff --git a/src/serial/dma.rs b/src/serial/dma.rs new file mode 100644 index 00000000..7e4f8cdc --- /dev/null +++ b/src/serial/dma.rs @@ -0,0 +1,328 @@ +use super::Serial; +use crate::dma::mux::request_ids::{ + RequestIdSome, Uart4RxDma, Uart4TxDma, Uart5RxDma, Uart5TxDma, Uart7RxDma, + Uart7TxDma, Uart8RxDma, Uart8TxDma, Usart1RxDma, Usart1TxDma, Usart2RxDma, + Usart2TxDma, Usart3RxDma, Usart3TxDma, Usart6RxDma, Usart6TxDma, +}; +use crate::dma::mux::{EgED as IEgED, SyncED as ISyncED}; +use crate::dma::safe_transfer::{ + FixedBuffer, FixedBufferR, MemoryBufferStatic, Ongoing as TransferOngoing, + Payload, PeripheralBuffer, Start as TransferStart, +}; +use crate::dma::stream::{ + Disabled as StreamDisabled, IsrCleared as StreamIsrCleared, StreamIsr, +}; +use crate::dma::{Channel, ChannelId, DmaMux, SafeTransfer}; +use crate::stm32::{UART4, UART5, UART7, UART8}; +use crate::stm32::{USART1, USART2, USART3, USART6}; +use core::ops::Deref; +use stm32h7::stm32h743::usart1::RegisterBlock; + +pub trait SerialRequest: RequestIdSome {} + +impl SerialRequest for Usart1RxDma {} +impl SerialRequest for Usart1TxDma {} +impl SerialRequest for Usart2RxDma {} +impl SerialRequest for Usart2TxDma {} +impl SerialRequest for Usart3RxDma {} +impl SerialRequest for Usart3TxDma {} +impl SerialRequest for Usart6RxDma {} +impl SerialRequest for Usart6TxDma {} + +impl SerialRequest for Uart4RxDma {} +impl SerialRequest for Uart4TxDma {} +impl SerialRequest for Uart5RxDma {} +impl SerialRequest for Uart5TxDma {} +impl SerialRequest for Uart7RxDma {} +impl SerialRequest for Uart7TxDma {} +impl SerialRequest for Uart8RxDma {} +impl SerialRequest for Uart8TxDma {} + +pub trait SerialChannelDma { + type Rx: SerialRequest; + type Tx: SerialRequest; +} + +impl SerialChannelDma for USART1 { + type Rx = Usart1RxDma; + type Tx = Usart1TxDma; +} + +impl SerialChannelDma for USART2 { + type Rx = Usart2RxDma; + type Tx = Usart2TxDma; +} + +impl SerialChannelDma for USART3 { + type Rx = Usart3RxDma; + type Tx = Usart3TxDma; +} + +impl SerialChannelDma for USART6 { + type Rx = Usart6RxDma; + type Tx = Usart6TxDma; +} + +impl SerialChannelDma for UART4 { + type Rx = Uart4RxDma; + type Tx = Uart4TxDma; +} + +impl SerialChannelDma for UART5 { + type Rx = Uart5RxDma; + type Tx = Uart5TxDma; +} + +impl SerialChannelDma for UART7 { + type Rx = Uart7RxDma; + type Tx = Uart7TxDma; +} + +impl SerialChannelDma for UART8 { + type Rx = Uart8RxDma; + type Tx = Uart8TxDma; +} + +pub trait IState {} + +pub struct Start +where + CXX: ChannelId, + ReqId: SerialRequest, + SyncED: ISyncED, + EgED: IEgED, +{ + channel: + Channel, +} + +pub struct Initialized +where + CXX: ChannelId, + ReqId: SerialRequest, + SyncED: ISyncED, + EgED: IEgED, + Peripheral: Payload, + Memory: Payload, +{ + channel: + Channel, + transfer: SafeTransfer<'static, Peripheral, Memory, TransferStart>, +} + +pub struct Ongoing +where + CXX: ChannelId, + ReqId: SerialRequest, + SyncED: ISyncED, + EgED: IEgED, + Peripheral: Payload, + Memory: Payload, +{ + mux: DmaMux, + transfer: SafeTransfer<'static, Peripheral, Memory, TransferOngoing>, +} + +impl IState for Start +where + CXX: ChannelId, + ReqId: SerialRequest, + SyncED: ISyncED, + EgED: IEgED, +{ +} + +impl IState + for Initialized +where + CXX: ChannelId, + ReqId: SerialRequest, + SyncED: ISyncED, + EgED: IEgED, + Peripheral: Payload, + Memory: Payload, +{ +} + +impl IState + for Ongoing +where + CXX: ChannelId, + ReqId: SerialRequest, + SyncED: ISyncED, + EgED: IEgED, + Peripheral: Payload, + Memory: Payload, +{ +} + +pub struct SerialDmaRx +where + USART: SerialChannelDma + Deref, + State: IState, +{ + serial: Serial, + state: State, +} + +impl + SerialDmaRx> +where + USART: SerialChannelDma + Deref, + CXX: ChannelId, + SyncED: ISyncED, + EgED: IEgED, +{ + pub fn new( + serial: Serial, + channel: Channel< + CXX, + StreamDisabled, + StreamIsrCleared, + USART::Rx, + SyncED, + EgED, + >, + ) -> Self { + let mut s = Self { + serial, + state: Start { channel }, + }; + + s.enable_dma_mode(); + + s + } + + pub fn init( + self, + memory: MemoryBufferStatic, + ) -> SerialDmaRx< + USART, + PINS, + Initialized, + > + where + Peripheral: Payload, + Memory: Payload, + { + if !memory.is_write() { + panic!("The memory buffer must be a Write-Buffer."); + } + + let pa = &self.serial.usart.rdr as *const _ as *const Peripheral; + let peripheral = PeripheralBuffer::Fixed(FixedBuffer::Read( + FixedBufferR::new(unsafe { &*pa }), + )); + + let transfer = SafeTransfer::new(peripheral, memory); + + SerialDmaRx { + serial: self.serial, + state: Initialized { + transfer, + channel: self.state.channel, + }, + } + } + + pub fn free( + mut self, + ) -> ( + Serial, + Channel, + ) { + self.disable_dma_mode(); + + (self.serial, self.state.channel) + } + + fn enable_dma_mode(&mut self) { + self.serial.usart.cr3.modify(|_, w| w.dmar().set_bit()); + } + + fn disable_dma_mode(&mut self) { + self.serial.usart.cr3.modify(|_, w| w.dmar().clear_bit()); + } +} + +impl + SerialDmaRx< + USART, + PINS, + Initialized, + > +where + USART: SerialChannelDma + Deref, + CXX: ChannelId, + SyncED: ISyncED, + EgED: IEgED, + Peripheral: Payload, + Memory: Payload, +{ + pub fn start( + self, + ) -> SerialDmaRx< + USART, + PINS, + Ongoing, + > { + let transfer = self.state.transfer.start(self.state.channel.stream); + + SerialDmaRx { + serial: self.serial, + state: Ongoing { + mux: self.state.channel.mux, + transfer, + }, + } + } +} + +impl + SerialDmaRx< + USART, + PINS, + Ongoing, + > +where + USART: SerialChannelDma + Deref, + CXX: ChannelId, + SyncED: ISyncED, + EgED: IEgED, + Peripheral: Payload, + Memory: Payload, +{ + pub fn transfer( + &self, + ) -> &SafeTransfer<'static, Peripheral, Memory, TransferOngoing> { + &self.state.transfer + } + + pub fn transfer_mut( + &mut self, + ) -> &mut SafeTransfer<'static, Peripheral, Memory, TransferOngoing> + { + &mut self.state.transfer + } + + pub fn mux(&self) -> &DmaMux { + &self.state.mux + } + + pub fn stop( + self, + isr: &mut StreamIsr, + ) -> SerialDmaRx> { + let stream = self.state.transfer.stop().clear_isr(isr); + let channel = Channel { + stream, + mux: self.state.mux, + }; + + SerialDmaRx { + serial: self.serial, + state: Start { channel }, + } + } +} diff --git a/src/serial.rs b/src/serial/mod.rs similarity index 73% rename from src/serial.rs rename to src/serial/mod.rs index dfd34f98..6412f7c1 100644 --- a/src/serial.rs +++ b/src/serial/mod.rs @@ -1,5 +1,8 @@ //! Serial +#[cfg(feature = "dma")] +pub mod dma; + use core::fmt; use core::marker::PhantomData; use core::ptr; @@ -13,7 +16,6 @@ use crate::stm32::rcc::d2ccip2r; use crate::stm32::usart1::cr1::{M0_A as M0, PCE_A as PCE, PS_A as PS}; use stm32h7::Variant::Val; -use crate::stm32::usart1::RegisterBlock; use crate::stm32::{UART4, UART5, UART7, UART8}; use crate::stm32::{USART1, USART2, USART3, USART6}; @@ -36,23 +38,7 @@ use crate::gpio::{Alternate, AF11, AF14, AF4, AF6, AF7, AF8}; use crate::rcc::Ccdr; use crate::time::Hertz; -use crate::dma::mux::request_ids::{ - RequestIdSome, Uart4RxDma, Uart4TxDma, Uart5RxDma, Uart5TxDma, Uart7RxDma, - Uart7TxDma, Uart8RxDma, Uart8TxDma, Usart1RxDma, Usart1TxDma, Usart2RxDma, - Usart2TxDma, Usart3RxDma, Usart3TxDma, Usart6RxDma, Usart6TxDma, -}; -use crate::dma::mux::{EgED as IEgED, SyncED as ISyncED}; -use crate::dma::safe_transfer::{ - FixedBuffer, FixedBufferR, MemoryBufferStatic, Ongoing as TransferOngoing, - Payload, PeripheralBuffer, Start as TransferStart, -}; - -use crate::dma::stream::{ - Disabled as StreamDisabled, IsrCleared as StreamIsrCleared, StreamIsr, -}; -use crate::dma::{Channel, ChannelId, DmaMux, SafeTransfer}; use crate::Never; -use core::ops::Deref; /// Serial error #[derive(Debug)] @@ -718,312 +704,3 @@ where Ok(()) } } - -pub trait SerialRequest: RequestIdSome {} - -impl SerialRequest for Usart1RxDma {} -impl SerialRequest for Usart1TxDma {} -impl SerialRequest for Usart2RxDma {} -impl SerialRequest for Usart2TxDma {} -impl SerialRequest for Usart3RxDma {} -impl SerialRequest for Usart3TxDma {} -impl SerialRequest for Usart6RxDma {} -impl SerialRequest for Usart6TxDma {} - -impl SerialRequest for Uart4RxDma {} -impl SerialRequest for Uart4TxDma {} -impl SerialRequest for Uart5RxDma {} -impl SerialRequest for Uart5TxDma {} -impl SerialRequest for Uart7RxDma {} -impl SerialRequest for Uart7TxDma {} -impl SerialRequest for Uart8RxDma {} -impl SerialRequest for Uart8TxDma {} - -pub trait SerialChannelDma { - type Rx: SerialRequest; - type Tx: SerialRequest; -} - -impl SerialChannelDma for USART1 { - type Rx = Usart1RxDma; - type Tx = Usart1TxDma; -} - -impl SerialChannelDma for USART2 { - type Rx = Usart2RxDma; - type Tx = Usart2TxDma; -} - -impl SerialChannelDma for USART3 { - type Rx = Usart3RxDma; - type Tx = Usart3TxDma; -} - -impl SerialChannelDma for USART6 { - type Rx = Usart6RxDma; - type Tx = Usart6TxDma; -} - -impl SerialChannelDma for UART4 { - type Rx = Uart4RxDma; - type Tx = Uart4TxDma; -} - -impl SerialChannelDma for UART5 { - type Rx = Uart5RxDma; - type Tx = Uart5TxDma; -} - -impl SerialChannelDma for UART7 { - type Rx = Uart7RxDma; - type Tx = Uart7TxDma; -} - -impl SerialChannelDma for UART8 { - type Rx = Uart8RxDma; - type Tx = Uart8TxDma; -} - -pub trait IState {} - -pub struct Start -where - CXX: ChannelId, - ReqId: SerialRequest, - SyncED: ISyncED, - EgED: IEgED, -{ - channel: - Channel, -} - -pub struct Initialized -where - CXX: ChannelId, - ReqId: SerialRequest, - SyncED: ISyncED, - EgED: IEgED, - Peripheral: Payload, - Memory: Payload, -{ - channel: - Channel, - transfer: SafeTransfer<'static, Peripheral, Memory, TransferStart>, -} - -pub struct Ongoing -where - CXX: ChannelId, - ReqId: SerialRequest, - SyncED: ISyncED, - EgED: IEgED, - Peripheral: Payload, - Memory: Payload, -{ - mux: DmaMux, - transfer: SafeTransfer<'static, Peripheral, Memory, TransferOngoing>, -} - -impl IState for Start -where - CXX: ChannelId, - ReqId: SerialRequest, - SyncED: ISyncED, - EgED: IEgED, -{ -} - -impl IState - for Initialized -where - CXX: ChannelId, - ReqId: SerialRequest, - SyncED: ISyncED, - EgED: IEgED, - Peripheral: Payload, - Memory: Payload, -{ -} - -impl IState - for Ongoing -where - CXX: ChannelId, - ReqId: SerialRequest, - SyncED: ISyncED, - EgED: IEgED, - Peripheral: Payload, - Memory: Payload, -{ -} - -pub struct SerialDmaRx -where - USART: SerialChannelDma + Deref, - State: IState, -{ - serial: Serial, - state: State, -} - -impl - SerialDmaRx> -where - USART: SerialChannelDma + Deref, - CXX: ChannelId, - SyncED: ISyncED, - EgED: IEgED, -{ - pub fn new( - serial: Serial, - channel: Channel< - CXX, - StreamDisabled, - StreamIsrCleared, - USART::Rx, - SyncED, - EgED, - >, - ) -> Self { - let mut s = Self { - serial, - state: Start { channel }, - }; - - s.enable_dma_mode(); - - s - } - - pub fn init( - self, - memory: MemoryBufferStatic, - ) -> SerialDmaRx< - USART, - PINS, - Initialized, - > - where - Peripheral: Payload, - Memory: Payload, - { - if !memory.is_write() { - panic!("The memory buffer must be a Write-Buffer."); - } - - let pa = &self.serial.usart.rdr as *const _ as *const Peripheral; - let peripheral = PeripheralBuffer::Fixed(FixedBuffer::Read( - FixedBufferR::new(unsafe { &*pa }), - )); - - let transfer = SafeTransfer::new(peripheral, memory); - - SerialDmaRx { - serial: self.serial, - state: Initialized { - transfer, - channel: self.state.channel, - }, - } - } - - pub fn free( - mut self, - ) -> ( - Serial, - Channel, - ) { - self.disable_dma_mode(); - - (self.serial, self.state.channel) - } - - fn enable_dma_mode(&mut self) { - self.serial.usart.cr3.modify(|_, w| w.dmar().set_bit()); - } - - fn disable_dma_mode(&mut self) { - self.serial.usart.cr3.modify(|_, w| w.dmar().clear_bit()); - } -} - -impl - SerialDmaRx< - USART, - PINS, - Initialized, - > -where - USART: SerialChannelDma + Deref, - CXX: ChannelId, - SyncED: ISyncED, - EgED: IEgED, - Peripheral: Payload, - Memory: Payload, -{ - pub fn start( - self, - ) -> SerialDmaRx< - USART, - PINS, - Ongoing, - > { - let transfer = self.state.transfer.start(self.state.channel.stream); - - SerialDmaRx { - serial: self.serial, - state: Ongoing { - mux: self.state.channel.mux, - transfer, - }, - } - } -} - -impl - SerialDmaRx< - USART, - PINS, - Ongoing, - > -where - USART: SerialChannelDma + Deref, - CXX: ChannelId, - SyncED: ISyncED, - EgED: IEgED, - Peripheral: Payload, - Memory: Payload, -{ - pub fn transfer( - &self, - ) -> &SafeTransfer<'static, Peripheral, Memory, TransferOngoing> { - &self.state.transfer - } - - pub fn transfer_mut( - &mut self, - ) -> &mut SafeTransfer<'static, Peripheral, Memory, TransferOngoing> - { - &mut self.state.transfer - } - - pub fn mux(&self) -> &DmaMux { - &self.state.mux - } - - pub fn stop( - self, - isr: &mut StreamIsr, - ) -> SerialDmaRx> { - let stream = self.state.transfer.stop().clear_isr(isr); - let channel = Channel { - stream, - mux: self.state.mux, - }; - - SerialDmaRx { - serial: self.serial, - state: Start { channel }, - } - } -} From 33380a7094a2e3b0980b361c3541c6a9f29d6d06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ad=C3=A4?= Date: Mon, 13 Apr 2020 02:38:22 +0200 Subject: [PATCH 081/103] Implemented safe_transfer transfer directions with buffers --- src/dma/mod.rs | 8 +- src/dma/safe_transfer.rs | 382 +++++++++++++++++++++++++++++++++++++-- 2 files changed, 368 insertions(+), 22 deletions(-) diff --git a/src/dma/mod.rs b/src/dma/mod.rs index 4c364eea..765ba374 100644 --- a/src/dma/mod.rs +++ b/src/dma/mod.rs @@ -22,9 +22,9 @@ use self::mux::{ }; use self::safe_transfer::{ check_buffer, check_double_buffer, configure_safe_transfer, mut_ptr_memory, - mut_ptr_peripheral, set_memory_impl, set_peripheral_impl, DoubleBuffer, + mut_ptr_peripheral, set_memory_impl, set_peripheral_impl, MemoryBufferStatic, Ongoing, Payload, PayloadPort, PeripheralBufferStatic, - PointerPort, Start, TransferState, + PointerPort, Start, TransferState, WhichBuffer, }; use self::stream::{ BufferMode, BufferModeConf, CircularMode, CircularModeConf, Config, @@ -1807,7 +1807,7 @@ where pub unsafe fn set_dest( &mut self, index: Option, - double_buffer: Option, + double_buffer: Option, payload: PayloadPort, ) { if self.peripheral.is_write() { @@ -1829,7 +1829,7 @@ where pub fn dest_ptr( &mut self, index: Option, - double_buffer: Option, + double_buffer: Option, ) -> PointerPort { if self.peripheral.is_write() { let ptr = mut_ptr_peripheral(&mut self.peripheral, index); diff --git a/src/dma/safe_transfer.rs b/src/dma/safe_transfer.rs index 98412102..004c1246 100644 --- a/src/dma/safe_transfer.rs +++ b/src/dma/safe_transfer.rs @@ -1,12 +1,12 @@ //! Safe DMA Transfers use super::stream::{ - CircularMode, Disabled, Enabled, IsrCleared, IsrUncleared, M0a, MSize, - Minc, Ndt, PSize, Pa, Pinc, Pincos, TransferDirection, TransferMode, + BufferMode, CircularMode, Disabled, Enabled, IsrCleared, IsrUncleared, M0a, + MSize, Minc, Ndt, PSize, Pa, Pinc, Pincos, TransferDirection, TransferMode, }; use super::{ChannelId, Stream}; use crate::private; -use core::convert::{TryFrom, TryInto}; +use core::convert::TryFrom; use core::fmt::Debug; use core::marker::PhantomData; use core::{mem, ptr}; @@ -31,9 +31,11 @@ impl TransferState for Ongoing where CXX: ChannelId {} /// # Safety /// /// * `Self` must be valid for any bit representation +/// * `Self::Size` must be pub unsafe trait Payload: Sized + Clone + Copy + Send + Sync + 'static { + type Size: IPayloadSize; } // Maps Payload size to number of bytes @@ -90,27 +92,371 @@ impl PayloadSize { where P: Payload, { - let size_bytes: usize = mem::size_of::

(); + let size = P::Size::SIZE; - size_bytes.try_into().unwrap_or_else(|_| { - panic!("The size of the buffer type must be either 1, 2 or 4 bytes") - }) + debug_assert_eq!(mem::size_of::

(), size.into()); + + size + } +} + +pub trait IPayloadSize { + const SIZE: PayloadSize; +} + +pub struct Byte; +pub struct HalfWord; +pub struct Word; + +impl IPayloadSize for Byte { + const SIZE: PayloadSize = PayloadSize::Byte; +} +impl IPayloadSize for HalfWord { + const SIZE: PayloadSize = PayloadSize::HalfWord; +} +impl IPayloadSize for Word { + const SIZE: PayloadSize = PayloadSize::Word; +} + +unsafe impl Payload for u8 { + type Size = Byte; +} + +unsafe impl Payload for i8 { + type Size = Byte; +} + +unsafe impl Payload for u16 { + type Size = HalfWord; +} + +unsafe impl Payload for i16 { + type Size = HalfWord; +} + +unsafe impl Payload for u32 { + type Size = Word; +} + +unsafe impl Payload for i32 { + type Size = Word; +} + +unsafe impl Payload for f32 { + type Size = Word; +} + +pub trait IMemoryBuffer { + type Memory: Payload; + + const BUFFER_MODE: BufferMode; + + fn first(&self) -> &MemoryBuffer; +} + +pub struct SingleBuffer<'buf, Memory> +where + Memory: Payload, +{ + pub memory: MemoryBuffer<'buf, Memory>, +} + +impl IMemoryBuffer for SingleBuffer<'_, Memory> +where + Memory: Payload, +{ + type Memory = Memory; + + const BUFFER_MODE: BufferMode = BufferMode::Regular; + + fn first(&self) -> &MemoryBuffer { + &self.memory + } +} + +pub struct DoubleBuffer<'buf0, 'buf1, Memory> +where + Memory: Payload, +{ + pub memory_0: MemoryBuffer<'buf0, Memory>, + pub memory_1: MemoryBuffer<'buf1, Memory>, +} + +impl IMemoryBuffer for DoubleBuffer<'_, '_, Memory> +where + Memory: Payload, +{ + type Memory = Memory; + + const BUFFER_MODE: BufferMode = BufferMode::DoubleBuffer; + + fn first(&self) -> &MemoryBuffer { + &self.memory_0 } } -unsafe impl Payload for u8 {} +pub trait IBuffers<'p_buf, 'wo> { + type Peripheral: Payload; + type MemoryBuffer: IMemoryBuffer; + + const TRANSFER_MODE: TransferMode; + + fn buffers( + self, + ) -> Buffers<'p_buf, 'wo, Self::Peripheral, Self::MemoryBuffer>; + + fn buffers_ref( + &self, + ) -> BuffersRef<'_, 'p_buf, 'wo, Self::Peripheral, Self::MemoryBuffer>; +} + +pub struct Buffers<'p_buf, 'wo, Peripheral, MemoryBuffer> +where + Peripheral: Payload, + MemoryBuffer: IMemoryBuffer, +{ + pub peripheral_buffer: PeripheralBuffer<'p_buf, 'wo, Peripheral>, + pub memory_buffer: MemoryBuffer, +} + +pub struct BuffersRef<'r, 'p_buf, 'wo, Peripheral, MemoryBuffer> +where + Peripheral: Payload, + MemoryBuffer: IMemoryBuffer, +{ + pub peripheral_buffer: &'r PeripheralBuffer<'p_buf, 'wo, Peripheral>, + pub memory_buffer: &'r MemoryBuffer, +} +pub struct FifoBuffers<'p_buf, 'wo, Peripheral, MemoryBuffer> +where + Peripheral: Payload, + MemoryBuffer: IMemoryBuffer, +{ + peripheral_buffer: PeripheralBuffer<'p_buf, 'wo, Peripheral>, + memory_buffer: MemoryBuffer, +} -unsafe impl Payload for i8 {} +impl<'p_buf, 'wo, Peripheral, MemoryBuffer> + FifoBuffers<'p_buf, 'wo, Peripheral, MemoryBuffer> +where + Peripheral: Payload, + MemoryBuffer: IMemoryBuffer, +{ + pub fn new( + peripheral: PeripheralBuffer<'p_buf, 'wo, Peripheral>, + memory_buffer: MemoryBuffer, + ) -> Self { + assert_ne!(peripheral.is_read(), memory_buffer.first().is_read()); -unsafe impl Payload for u16 {} + Self { + peripheral_buffer: peripheral, + memory_buffer, + } + } +} -unsafe impl Payload for i16 {} +impl<'p_buf, 'wo, Peripheral, MemoryBuffer> IBuffers<'p_buf, 'wo> + for FifoBuffers<'p_buf, 'wo, Peripheral, MemoryBuffer> +where + Peripheral: Payload, + MemoryBuffer: IMemoryBuffer, +{ + type Peripheral = Peripheral; + type MemoryBuffer = MemoryBuffer; -unsafe impl Payload for u32 {} + const TRANSFER_MODE: TransferMode = TransferMode::Fifo; -unsafe impl Payload for i32 {} + fn buffers(self) -> Buffers<'p_buf, 'wo, Peripheral, MemoryBuffer> { + Buffers { + peripheral_buffer: self.peripheral_buffer, + memory_buffer: self.memory_buffer, + } + } -unsafe impl Payload for f32 {} + fn buffers_ref( + &self, + ) -> BuffersRef<'_, 'p_buf, 'wo, Peripheral, MemoryBuffer> { + BuffersRef { + peripheral_buffer: &self.peripheral_buffer, + memory_buffer: &self.memory_buffer, + } + } +} + +pub struct DirectBuffers<'p_buf, 'wo, Peripheral, MemoryBuffer> +where + Peripheral: Payload::Size>, + MemoryBuffer: IMemoryBuffer, +{ + peripheral_buffer: PeripheralBuffer<'p_buf, 'wo, Peripheral>, + memory_buffer: MemoryBuffer, +} + +impl<'p_buf, 'wo, Peripheral, Memory, MemoryBuffer> + DirectBuffers<'p_buf, 'wo, Peripheral, MemoryBuffer> +where + Peripheral: Payload, + Memory: Payload, + MemoryBuffer: IMemoryBuffer, +{ + pub fn new( + peripheral: PeripheralBuffer<'p_buf, 'wo, Peripheral>, + memory_buffer: MemoryBuffer, + ) -> Self { + assert_ne!(peripheral.is_read(), memory_buffer.first().is_read()); + + Self { + peripheral_buffer: peripheral, + memory_buffer, + } + } +} + +impl<'p_buf, 'wo, Peripheral, Memory, MemoryBuffer> IBuffers<'p_buf, 'wo> + for DirectBuffers<'p_buf, 'wo, Peripheral, MemoryBuffer> +where + Peripheral: Payload, + Memory: Payload, + MemoryBuffer: IMemoryBuffer, +{ + type Peripheral = Peripheral; + type MemoryBuffer = MemoryBuffer; + + const TRANSFER_MODE: TransferMode = TransferMode::Direct; + + fn buffers(self) -> Buffers<'p_buf, 'wo, Peripheral, MemoryBuffer> { + Buffers { + peripheral_buffer: self.peripheral_buffer, + memory_buffer: self.memory_buffer, + } + } + + fn buffers_ref( + &self, + ) -> BuffersRef<'_, 'p_buf, 'wo, Peripheral, MemoryBuffer> { + BuffersRef { + peripheral_buffer: &self.peripheral_buffer, + memory_buffer: &self.memory_buffer, + } + } +} + +pub trait ITransferDirection<'p_buf, 'wo> { + type Buffers: IBuffers<'p_buf, 'wo>; + + const TRANSFER_DIRECTION: TransferDirection; + + fn buffers(self) -> Self::Buffers; +} + +pub struct PeripheralToMemory +where + for<'p_buf, 'wo> BUFFERS: IBuffers<'p_buf, 'wo>, +{ + buffers: BUFFERS, +} + +impl PeripheralToMemory +where + for<'p_buf, 'wo> BUFFERS: IBuffers<'p_buf, 'wo>, +{ + pub fn new(buffers: BUFFERS) -> Self { + assert!(buffers.buffers_ref().peripheral_buffer.is_read()); + assert!(buffers.buffers_ref().memory_buffer.first().is_write()); + + Self { buffers } + } +} + +impl<'p_buf, 'wo, BUFFERS> ITransferDirection<'p_buf, 'wo> + for PeripheralToMemory +where + for<'p_buf1, 'wo1> BUFFERS: IBuffers<'p_buf1, 'wo1>, +{ + type Buffers = BUFFERS; + + const TRANSFER_DIRECTION: TransferDirection = TransferDirection::P2M; + + fn buffers(self) -> BUFFERS { + self.buffers + } +} + +pub struct MemoryToPeripheral +where + for<'p_buf, 'wo> BUFFERS: IBuffers<'p_buf, 'wo>, +{ + buffers: BUFFERS, +} + +impl MemoryToPeripheral +where + for<'p_buf, 'wo> BUFFERS: IBuffers<'p_buf, 'wo>, +{ + pub fn new(buffers: BUFFERS) -> Self { + assert!(buffers.buffers_ref().memory_buffer.first().is_read()); + assert!(buffers.buffers_ref().peripheral_buffer.is_write()); + + Self { buffers } + } +} + +impl<'p_buf, 'wo, BUFFERS> ITransferDirection<'p_buf, 'wo> + for MemoryToPeripheral +where + for<'p_buf1, 'wo1> BUFFERS: IBuffers<'p_buf1, 'wo1>, +{ + type Buffers = BUFFERS; + + const TRANSFER_DIRECTION: TransferDirection = TransferDirection::M2P; + + fn buffers(self) -> BUFFERS { + self.buffers + } +} + +pub struct MemoryToMemory<'m_buf, BUFFERS, Memory> +where + for<'p_buf, 'wo> BUFFERS: + IBuffers<'p_buf, 'wo, MemoryBuffer = SingleBuffer<'m_buf, Memory>>, + Memory: Payload, +{ + buffers: BUFFERS, + _phantom: PhantomData<&'m_buf Memory>, +} + +impl<'m_buf, BUFFERS, Memory> MemoryToMemory<'m_buf, BUFFERS, Memory> +where + for<'p_buf, 'wo> BUFFERS: + IBuffers<'p_buf, 'wo, MemoryBuffer = SingleBuffer<'m_buf, Memory>>, + Memory: Payload, +{ + pub fn new(buffers: BUFFERS) -> Self { + assert!(buffers.buffers_ref().peripheral_buffer.is_read()); + assert!(buffers.buffers_ref().memory_buffer.memory.is_write()); + + Self { + buffers, + _phantom: PhantomData, + } + } +} + +impl<'p_buf, 'm_buf, 'wo, BUFFERS, Memory> ITransferDirection<'p_buf, 'wo> + for MemoryToMemory<'m_buf, BUFFERS, Memory> +where + for<'p_buf1, 'wo1> BUFFERS: + IBuffers<'p_buf1, 'wo1, MemoryBuffer = SingleBuffer<'m_buf, Memory>>, + Memory: Payload, +{ + type Buffers = BUFFERS; + + const TRANSFER_DIRECTION: TransferDirection = TransferDirection::M2M; + + fn buffers(self) -> BUFFERS { + self.buffers + } +} #[derive(Clone, Copy)] pub enum PayloadPort @@ -1381,16 +1727,16 @@ where } #[derive(Clone, Copy)] -pub enum DoubleBuffer { +pub enum WhichBuffer { First, Second, } -impl DoubleBuffer { +impl WhichBuffer { pub fn index(self) -> usize { match self { - DoubleBuffer::First => 0, - DoubleBuffer::Second => 1, + WhichBuffer::First => 0, + WhichBuffer::Second => 1, } } } From c6a5a14a6b097e38dc2051fb3903b3f9825e7aaf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ad=C3=A4?= Date: Mon, 13 Apr 2020 02:40:27 +0200 Subject: [PATCH 082/103] Fixed doc --- src/dma/safe_transfer.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dma/safe_transfer.rs b/src/dma/safe_transfer.rs index 004c1246..eff69bbc 100644 --- a/src/dma/safe_transfer.rs +++ b/src/dma/safe_transfer.rs @@ -31,7 +31,7 @@ impl TransferState for Ongoing where CXX: ChannelId {} /// # Safety /// /// * `Self` must be valid for any bit representation -/// * `Self::Size` must be +/// * `Self::Size` must be equal to actual size pub unsafe trait Payload: Sized + Clone + Copy + Send + Sync + 'static { From d58d9b6b4cb10ad75534eed6db6f1bcf2ff0d1b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ad=C3=A4?= Date: Fri, 17 Apr 2020 17:56:39 +0200 Subject: [PATCH 083/103] Reworking SafeTransfer --- src/dma/mod.rs | 416 ++---------- src/dma/safe_transfer.rs | 1326 ++++++++++++++++++-------------------- src/serial/mod.rs | 2 +- 3 files changed, 704 insertions(+), 1040 deletions(-) diff --git a/src/dma/mod.rs b/src/dma/mod.rs index 765ba374..8a1b0411 100644 --- a/src/dma/mod.rs +++ b/src/dma/mod.rs @@ -21,10 +21,8 @@ use self::mux::{ SyncId, SyncOverrunInterrupt, SyncPolarity, }; use self::safe_transfer::{ - check_buffer, check_double_buffer, configure_safe_transfer, mut_ptr_memory, - mut_ptr_peripheral, set_memory_impl, set_peripheral_impl, - MemoryBufferStatic, Ongoing, Payload, PayloadPort, PeripheralBufferStatic, - PointerPort, Start, TransferState, WhichBuffer, + Config as TransferConfig, MemoryBuffer, Ongoing, Payload, PayloadSize, + PeripheralBuffer, Start, TransferState, }; use self::stream::{ BufferMode, BufferModeConf, CircularMode, CircularModeConf, Config, @@ -37,7 +35,8 @@ use self::stream::{ TransferDirectionConf, TransferErrorInterrupt, TransferMode, TransferModeConf, ED as IED, }; -use crate::nb::{self, block, Error as NbError}; +use crate::dma::safe_transfer::Buffer; +use crate::nb::{self, Error as NbError}; use crate::private; use crate::rcc::Ccdr; use crate::stm32::dma1::ST; @@ -45,7 +44,6 @@ use crate::stm32::dmamux1::CCR; use crate::stm32::{DMA1, DMA2, RCC}; use core::convert::{Infallible, TryFrom, TryInto}; use core::marker::PhantomData; -use core::mem; use stm32h7::stm32h743::DMAMUX1; /// Marker Trait for DMA peripherals @@ -1583,378 +1581,84 @@ where { } -/// Memory-safe DMA transfer for single-buffer -pub struct SafeTransfer<'wo, Peripheral, Memory, State> -where - Peripheral: Payload, - Memory: Payload, - State: TransferState, -{ - peripheral: PeripheralBufferStatic<'wo, Peripheral>, - memory: MemoryBufferStatic, +pub struct Transfer<'wo, State: TransferState<'wo>> { state: State, + _phantom: PhantomData<&'wo ()>, } -impl<'wo, Peripheral, Memory> SafeTransfer<'wo, Peripheral, Memory, Start> -where - Peripheral: Payload, - Memory: Payload, -{ - /// Initializes new DMA transfer without starting it yet - pub fn new( - peripheral: PeripheralBufferStatic<'wo, Peripheral>, - memory: MemoryBufferStatic, - ) -> Self { - check_buffer(&peripheral, &memory); - - SafeTransfer { - peripheral, - memory, - state: Start, - } - } -} - -impl<'wo, Peripheral, Memory, State> - SafeTransfer<'wo, Peripheral, Memory, State> +impl<'wo, Peripheral, Memory> Transfer<'wo, Start<'wo, Peripheral, Memory>> where Peripheral: Payload, Memory: Payload, - State: TransferState, { - /// Returns peripheral buffer - pub fn peripheral(&self) -> &PeripheralBufferStatic<'wo, Peripheral> { - &self.peripheral - } - - /// Returns memory buffer - pub fn memory(&self) -> &MemoryBufferStatic { - &self.memory - } - - /// Sets the content of destination buffer - /// - /// # Safety - /// - /// The caller must ensure, that the DMA is currently not modifying this address. - pub unsafe fn set_dest( - &mut self, - index: Option, - payload: PayloadPort, - ) { - if self.peripheral.is_write() { - set_peripheral_impl( - &mut self.peripheral, - index, - payload.peripheral(), - ); - } else { - set_memory_impl(&mut self.memory, index, payload.memory()); - } - } - - /// Returns pointer to destination buffer - pub fn dest_ptr( - &mut self, - index: Option, - ) -> PointerPort { - if self.peripheral.is_write() { - let ptr = mut_ptr_peripheral(&mut self.peripheral, index); - - PointerPort::Peripheral(ptr) - } else { - let ptr = mut_ptr_memory(&mut self.memory, index); - - PointerPort::Memory(ptr) + pub fn new(conf: TransferConfig<'wo, Peripheral, Memory>) -> Self { + Self { + state: Start { conf }, + _phantom: PhantomData, } } -} -impl<'wo, Source, Dest> SafeTransfer<'wo, Source, Dest, Start> -where - Source: Payload, - Dest: Payload, -{ - /// Starts the transfer - pub fn start( + pub fn start( self, mut stream: Stream, - ) -> SafeTransfer<'wo, Source, Dest, Ongoing> - where - CXX: ChannelId, - { - configure_safe_transfer(&mut stream, &self.peripheral, &self.memory); - stream.set_buffer_mode(BufferMode::Regular); + ) -> Transfer<'wo, Ongoing<'wo, Peripheral, Memory, CXX>> { + self.configure_stream(&mut stream); - SafeTransfer { - peripheral: self.peripheral, - memory: self.memory, + Transfer { state: Ongoing { stream: unsafe { stream.enable() }, + buffers: self.state.conf.free(), }, + _phantom: PhantomData, } } -} - -impl SafeTransfer<'_, Source, Dest, Ongoing> -where - Source: Payload, - Dest: Payload, - CXX: ChannelId, -{ - /// Returns the stream assigned to the transfer - pub fn stream(&self) -> &Stream { - &self.state.stream - } - - /// Sets the Transfer Complete Interrupt config flag of the assigned stream - pub fn set_transfer_complete_interrupt( - &mut self, - tc_intrpt: TransferCompleteInterrupt, - ) { - self.state.stream.set_transfer_complete_interrupt(tc_intrpt); - } - - /// Sets the Half Transfer Interrupt config flag of the assigned stream - pub fn set_half_transfer_interrupt( - &mut self, - ht_intrpt: HalfTransferInterrupt, - ) { - self.state.stream.set_half_transfer_interrupt(ht_intrpt); - } - - /// Sets the Transfer Error Interrupt config flag of the assigned stream - pub fn set_transfer_error_interrupt( - &mut self, - te_intrpt: TransferErrorInterrupt, - ) { - self.state.stream.set_transfer_error_interrupt(te_intrpt); - } - - /// Sets the Direct Mode Error Interrupt config flag of the assigned stream - pub fn set_direct_mode_error_interrupt( - &mut self, - dme_intrpt: DirectModeErrorInterrupt, - ) { - self.state - .stream - .set_direct_mode_error_interrupt(dme_intrpt); - } - - /// Sets the Fifo Error Interrupt config flag of the assigned stream - pub fn set_fifo_error_interrupt(&mut self, fe_intrpt: FifoErrorInterrupt) { - self.state.stream.set_fifo_error_interrupt(fe_intrpt); - } - - /// Stops the transfer, returning the stream - pub fn stop(self) -> Stream { - self.state.stream.disable() - } -} - -/// Memory-safe DMA transfer for double buffer -pub struct SafeTransferDoubleBuffer<'wo, Peripheral, Memory, State> -where - Peripheral: Payload, - Memory: Payload, - State: TransferState, -{ - peripheral: PeripheralBufferStatic<'wo, Peripheral>, - memories: [MemoryBufferStatic; 2], - state: State, -} - -impl<'wo, Peripheral, Memory> - SafeTransferDoubleBuffer<'wo, Peripheral, Memory, Start> -where - Peripheral: Payload, - Memory: Payload, -{ - /// Initializes new DMA transfer without starting it yet - pub fn new( - peripheral: PeripheralBufferStatic<'wo, Peripheral>, - memories: [MemoryBufferStatic; 2], - ) -> Self { - check_buffer(&peripheral, &memories[0]); - check_double_buffer(&memories); - - SafeTransferDoubleBuffer { - peripheral, - memories, - state: Start, - } - } -} - -impl<'wo, Peripheral, Memory, State> - SafeTransferDoubleBuffer<'wo, Peripheral, Memory, State> -where - Peripheral: Payload, - Memory: Payload, - State: TransferState, -{ - /// Returns peripheral buffer - pub fn peripheral(&self) -> &PeripheralBufferStatic<'wo, Peripheral> { - &self.peripheral - } - /// Returns memory buffers - pub fn memories(&self) -> &[MemoryBufferStatic; 2] { - &self.memories - } - - /// Sets the content of destination buffer - pub unsafe fn set_dest( - &mut self, - index: Option, - double_buffer: Option, - payload: PayloadPort, + fn configure_stream( + &self, + stream: &mut Stream, ) { - if self.peripheral.is_write() { - set_peripheral_impl( - &mut self.peripheral, - index, - payload.peripheral(), - ); - } else { - set_memory_impl( - &mut self.memories[double_buffer.unwrap().index()], - index, - payload.memory(), - ); - } - } - - /// Returns a pointer to the destination buffer - pub fn dest_ptr( - &mut self, - index: Option, - double_buffer: Option, - ) -> PointerPort { - if self.peripheral.is_write() { - let ptr = mut_ptr_peripheral(&mut self.peripheral, index); - - PointerPort::Peripheral(ptr) - } else { - let ptr = mut_ptr_memory( - &mut self.memories[double_buffer.unwrap().index()], - index, - ); - - PointerPort::Memory(ptr) - } - } -} - -impl<'wo, Peripheral, Memory> - SafeTransferDoubleBuffer<'wo, Peripheral, Memory, Start> -where - Peripheral: Payload, - Memory: Payload, -{ - /// Starts the transfer - pub fn start( - self, - mut stream: Stream, - ) -> SafeTransferDoubleBuffer<'wo, Peripheral, Memory, Ongoing> - where - CXX: ChannelId, - { - stream.set_buffer_mode(BufferMode::DoubleBuffer); - stream.set_m1a(M1a(self.memories[1].as_ptr(Some(0)) as u32)); - - configure_safe_transfer( - &mut stream, - &self.peripheral, - &self.memories[0], - ); - - SafeTransferDoubleBuffer { - peripheral: self.peripheral, - memories: self.memories, - state: Ongoing { - stream: unsafe { stream.enable() }, - }, + let mut conf = stream.config(); + conf.transfer_direction = self.state.conf.transfer_direction_conf(); + + // Configure ndt + + let buffers = self.state.buffers().get(); + + match buffers.peripheral_buffer { + Buffer::Peripheral(PeripheralBuffer::Fixed(_)) + | Buffer::Memory(MemoryBuffer::Fixed(_)) => { + match buffers.memory_buffer.m0a() { + MemoryBuffer::Fixed(_) => { + // NDT must be configured in advance + } + MemoryBuffer::Incremented(buffer) => { + let p_size: usize = + PayloadSize::from_payload::().into(); + let m_size: usize = + PayloadSize::from_payload::().into(); + + let memory_bytes = buffer.len() * m_size; + + if memory_bytes % p_size != 0 { + panic!("Last transfer may be incomplete."); + } + + let ndt = u16::try_from(memory_bytes / p_size).unwrap(); + conf.ndt = Ndt(ndt); + } + } + } + Buffer::Peripheral(PeripheralBuffer::Incremented(buffer)) => { + let ndt = u16::try_from(buffer.len()).unwrap(); + conf.ndt = Ndt(ndt); + } + Buffer::Memory(MemoryBuffer::Incremented(buffer)) => { + let ndt = u16::try_from(buffer.len()).unwrap(); + conf.ndt = Ndt(ndt); + } } - } -} - -impl - SafeTransferDoubleBuffer<'_, Peripheral, Memory, Ongoing> -where - Peripheral: Payload, - Memory: Payload, - CXX: ChannelId, -{ - /// Returns the stream assigned to the transfer - pub fn stream(&self) -> &Stream { - &self.state.stream - } - - /// Sets the Transfer Complete Interrupt config flag - pub fn set_transfer_complete_interrupt( - &mut self, - tc_intrpt: TransferCompleteInterrupt, - ) { - self.state.stream.set_transfer_complete_interrupt(tc_intrpt); - } - - /// Sets the Half Transfer Interrupt config flag - pub fn set_half_transfer_interrupt( - &mut self, - ht_intrpt: HalfTransferInterrupt, - ) { - self.state.stream.set_half_transfer_interrupt(ht_intrpt); - } - - /// Sets the Transfer Error Interrupt config flag - pub fn set_transfer_error_interrupt( - &mut self, - te_intrpt: TransferErrorInterrupt, - ) { - self.state.stream.set_transfer_error_interrupt(te_intrpt); - } - - /// Sets the Direct Mode Error Interrupt config flag - pub fn set_direct_mode_error_interrupt( - &mut self, - dme_intrpt: DirectModeErrorInterrupt, - ) { - self.state - .stream - .set_direct_mode_error_interrupt(dme_intrpt); - } - - /// Sets the Fifo Error Interrupt config flag - pub fn set_fifo_error_interrupt(&mut self, fe_intrpt: FifoErrorInterrupt) { - self.state.stream.set_fifo_error_interrupt(fe_intrpt); - } - - /// Sets the memory-0 address - pub fn set_m0a(&mut self, m0a: MemoryBufferStatic) { - let ptr = m0a.as_ptr(Some(0)); - - mem::replace(&mut self.memories[0], m0a); - - check_double_buffer(&self.memories); - - block!(self.state.stream.set_m0a(M0a(ptr as u32))).unwrap(); - } - - /// Sets the memory-1 address - pub fn set_m1a(&mut self, m1a: MemoryBufferStatic) { - let ptr = m1a.as_ptr(Some(0)); - - mem::replace(&mut self.memories[1], m1a); - - check_double_buffer(&self.memories); - - block!(self.state.stream.set_m1a(M1a(ptr as u32))).unwrap(); - } - /// Stops the transfer - pub fn stop(self) -> Stream { - self.state.stream.disable() + stream.apply_config(conf); } } diff --git a/src/dma/safe_transfer.rs b/src/dma/safe_transfer.rs index eff69bbc..eb43aa7f 100644 --- a/src/dma/safe_transfer.rs +++ b/src/dma/safe_transfer.rs @@ -1,32 +1,96 @@ //! Safe DMA Transfers use super::stream::{ - BufferMode, CircularMode, Disabled, Enabled, IsrCleared, IsrUncleared, M0a, - MSize, Minc, Ndt, PSize, Pa, Pinc, Pincos, TransferDirection, TransferMode, + BufferModeConf, CircularModeConf, Enabled, FlowControllerConf, + IsrUncleared, M0a, M1a, MSize, NotM2MConf, PSize, Pa, TransferDirection, + TransferDirectionConf, TransferModeConf, }; use super::{ChannelId, Stream}; use crate::private; -use core::convert::TryFrom; +use core::convert::TryInto; use core::fmt::Debug; -use core::marker::PhantomData; use core::{mem, ptr}; -pub trait TransferState: Send + Sync + private::Sealed {} +pub trait TransferState<'wo>: Send + Sync + private::Sealed { + type Peripheral: Payload; + type Memory: Payload; -pub struct Start; -impl private::Sealed for Start {} -impl TransferState for Start {} + fn buffers(&self) -> &Buffers<'wo, Self::Peripheral, Self::Memory>; + unsafe fn buffers_mut( + &mut self, + ) -> &mut Buffers<'wo, Self::Peripheral, Self::Memory>; +} + +pub struct Start<'wo, Peripheral, Memory> +where + Peripheral: Payload, + Memory: Payload, +{ + pub(super) conf: Config<'wo, Peripheral, Memory>, +} + +impl private::Sealed for Start<'_, Peripheral, Memory> +where + Peripheral: Payload, + Memory: Payload, +{ +} -pub struct Ongoing +impl<'wo, Peripheral, Memory> TransferState<'wo> + for Start<'wo, Peripheral, Memory> where + Peripheral: Payload, + Memory: Payload, +{ + type Peripheral = Peripheral; + type Memory = Memory; + + fn buffers(&self) -> &Buffers<'wo, Peripheral, Memory> { + &self.conf.buffers + } + + unsafe fn buffers_mut(&mut self) -> &mut Buffers<'wo, Peripheral, Memory> { + self.conf.buffers_mut_unchecked() + } +} + +pub struct Ongoing<'wo, Peripheral, Memory, CXX> +where + Peripheral: Payload, + Memory: Payload, CXX: ChannelId, { pub(super) stream: Stream, + pub(super) buffers: Buffers<'wo, Peripheral, Memory>, } -impl private::Sealed for Ongoing where CXX: ChannelId {} +impl private::Sealed + for Ongoing<'_, Peripheral, Memory, CXX> +where + Peripheral: Payload, + Memory: Payload, + CXX: ChannelId, +{ +} -impl TransferState for Ongoing where CXX: ChannelId {} +impl<'wo, Peripheral, Memory, CXX> TransferState<'wo> + for Ongoing<'wo, Peripheral, Memory, CXX> +where + Peripheral: Payload, + Memory: Payload, + CXX: ChannelId, +{ + type Peripheral = Peripheral; + type Memory = Memory; + + fn buffers(&self) -> &Buffers<'wo, Peripheral, Memory> { + &self.buffers + } + + unsafe fn buffers_mut(&mut self) -> &mut Buffers<'wo, Peripheral, Memory> { + &mut self.buffers + } +} /// # Safety /// @@ -88,10 +152,7 @@ impl From for PayloadSize { } impl PayloadSize { - pub fn from_payload

() -> Self - where - P: Payload, - { + pub fn from_payload() -> Self { let size = P::Size::SIZE; debug_assert_eq!(mem::size_of::

(), size.into()); @@ -146,318 +207,434 @@ unsafe impl Payload for f32 { type Size = Word; } -pub trait IMemoryBuffer { - type Memory: Payload; - - const BUFFER_MODE: BufferMode; - - fn first(&self) -> &MemoryBuffer; -} - -pub struct SingleBuffer<'buf, Memory> -where - Memory: Payload, -{ - pub memory: MemoryBuffer<'buf, Memory>, +pub enum MemoryBufferType { + SingleBuffer(SingleBuffer), + DoubleBuffer(DoubleBuffer), } -impl IMemoryBuffer for SingleBuffer<'_, Memory> -where - Memory: Payload, -{ - type Memory = Memory; +impl MemoryBufferType { + pub fn is_single_buffer(&self) -> bool { + self.as_single_buffer().is_some() + } - const BUFFER_MODE: BufferMode = BufferMode::Regular; + pub fn is_double_buffer(&self) -> bool { + self.as_double_buffer().is_some() + } - fn first(&self) -> &MemoryBuffer { - &self.memory + pub fn into_single_buffer(self) -> Option> { + if let Self::SingleBuffer(buffer) = self { + Some(buffer) + } else { + None + } } -} -pub struct DoubleBuffer<'buf0, 'buf1, Memory> -where - Memory: Payload, -{ - pub memory_0: MemoryBuffer<'buf0, Memory>, - pub memory_1: MemoryBuffer<'buf1, Memory>, -} + pub fn as_single_buffer(&self) -> Option<&SingleBuffer> { + if let Self::SingleBuffer(buffer) = self { + Some(buffer) + } else { + None + } + } -impl IMemoryBuffer for DoubleBuffer<'_, '_, Memory> -where - Memory: Payload, -{ - type Memory = Memory; + pub fn as_single_buffer_mut( + &mut self, + ) -> Option<&mut SingleBuffer> { + if let Self::SingleBuffer(buffer) = self { + Some(buffer) + } else { + None + } + } - const BUFFER_MODE: BufferMode = BufferMode::DoubleBuffer; + pub fn into_double_buffer(self) -> Option> { + if let Self::DoubleBuffer(buffer) = self { + Some(buffer) + } else { + None + } + } - fn first(&self) -> &MemoryBuffer { - &self.memory_0 + pub fn as_double_buffer(&self) -> Option<&DoubleBuffer> { + if let Self::DoubleBuffer(buffer) = self { + Some(buffer) + } else { + None + } } -} -pub trait IBuffers<'p_buf, 'wo> { - type Peripheral: Payload; - type MemoryBuffer: IMemoryBuffer; + pub fn as_double_buffer_mut( + &mut self, + ) -> Option<&mut DoubleBuffer> { + if let Self::DoubleBuffer(buffer) = self { + Some(buffer) + } else { + None + } + } - const TRANSFER_MODE: TransferMode; + pub fn is_read(&self) -> bool { + match self { + MemoryBufferType::SingleBuffer(buffer) => buffer.memory.is_read(), + MemoryBufferType::DoubleBuffer(buffer) => { + buffer.memories[0].is_read() + } + } + } - fn buffers( - self, - ) -> Buffers<'p_buf, 'wo, Self::Peripheral, Self::MemoryBuffer>; + pub fn is_write(&self) -> bool { + !self.is_read() + } - fn buffers_ref( - &self, - ) -> BuffersRef<'_, 'p_buf, 'wo, Self::Peripheral, Self::MemoryBuffer>; + pub fn m0a(&self) -> &MemoryBuffer { + match self { + Self::SingleBuffer(buffer) => &buffer.memory, + Self::DoubleBuffer(buffer) => &buffer.memories()[0], + } + } } -pub struct Buffers<'p_buf, 'wo, Peripheral, MemoryBuffer> +pub struct SingleBuffer where - Peripheral: Payload, - MemoryBuffer: IMemoryBuffer, + Memory: Payload, { - pub peripheral_buffer: PeripheralBuffer<'p_buf, 'wo, Peripheral>, - pub memory_buffer: MemoryBuffer, + pub memory: MemoryBuffer, } -pub struct BuffersRef<'r, 'p_buf, 'wo, Peripheral, MemoryBuffer> +pub struct DoubleBuffer where - Peripheral: Payload, - MemoryBuffer: IMemoryBuffer, -{ - pub peripheral_buffer: &'r PeripheralBuffer<'p_buf, 'wo, Peripheral>, - pub memory_buffer: &'r MemoryBuffer, -} -pub struct FifoBuffers<'p_buf, 'wo, Peripheral, MemoryBuffer> -where - Peripheral: Payload, - MemoryBuffer: IMemoryBuffer, + Memory: Payload, { - peripheral_buffer: PeripheralBuffer<'p_buf, 'wo, Peripheral>, - memory_buffer: MemoryBuffer, + memories: [MemoryBuffer; 2], } -impl<'p_buf, 'wo, Peripheral, MemoryBuffer> - FifoBuffers<'p_buf, 'wo, Peripheral, MemoryBuffer> -where - Peripheral: Payload, - MemoryBuffer: IMemoryBuffer, -{ - pub fn new( - peripheral: PeripheralBuffer<'p_buf, 'wo, Peripheral>, - memory_buffer: MemoryBuffer, - ) -> Self { - assert_ne!(peripheral.is_read(), memory_buffer.first().is_read()); +impl DoubleBuffer { + pub fn new(memories: [MemoryBuffer; 2]) -> Self { + let s = Self { memories }; - Self { - peripheral_buffer: peripheral, - memory_buffer, - } + s.check_self(); + + s } -} -impl<'p_buf, 'wo, Peripheral, MemoryBuffer> IBuffers<'p_buf, 'wo> - for FifoBuffers<'p_buf, 'wo, Peripheral, MemoryBuffer> -where - Peripheral: Payload, - MemoryBuffer: IMemoryBuffer, -{ - type Peripheral = Peripheral; - type MemoryBuffer = MemoryBuffer; + pub fn memories(&self) -> &[MemoryBuffer; 2] { + &self.memories + } + + /// Exposes a mutable reference to the double buffer inside a closure. + /// The **same** reference must be returned in the closure, or this method panics. + /// This prevents the caller to move the reference out of the closure. + /// + /// At the end, the double buffer will be checked. + /// + /// If the closure is too limiting, consider using the unchecked version. + pub fn memories_mut(&mut self, op: F) + where + for<'a> F: FnOnce( + &'a mut [MemoryBuffer; 2], + ) -> &'a mut [MemoryBuffer; 2], + { + let ptr_before = &mut self.memories as *mut _; + let ptr_after = op(&mut self.memories) as *mut _; - const TRANSFER_MODE: TransferMode = TransferMode::Fifo; + assert_eq!(ptr_before, ptr_after); - fn buffers(self) -> Buffers<'p_buf, 'wo, Peripheral, MemoryBuffer> { - Buffers { - peripheral_buffer: self.peripheral_buffer, - memory_buffer: self.memory_buffer, - } + self.check_self(); } - fn buffers_ref( - &self, - ) -> BuffersRef<'_, 'p_buf, 'wo, Peripheral, MemoryBuffer> { - BuffersRef { - peripheral_buffer: &self.peripheral_buffer, - memory_buffer: &self.memory_buffer, + /// Returns mutable reference to the double buffer. + /// + /// # Safety + /// + /// This is unsafe because - by `mem::replace`ing the buffers - the api contract of both buffers + /// having the same characteristics (fixed/incremented, read/write) can be violated. + /// This may result in breaking the aliasing rules and subsequently undefined behaviour. + /// + /// This is safe as long as you don't `mem::replace` the buffers, or at least ensure that + /// both buffers have the same characteristics afterwards. + pub unsafe fn memories_mut_unchecked( + &mut self, + ) -> &mut [MemoryBuffer; 2] { + &mut self.memories + } + + pub fn free(self) -> [MemoryBuffer; 2] { + self.memories + } + + fn check_self(&self) { + assert_eq!(self.memories[0].is_read(), self.memories[1].is_read()); + assert_eq!(self.memories[0].is_fixed(), self.memories[1].is_fixed()); + + if self.memories[0].is_incremented() { + assert_eq!( + self.memories[0].as_incremented().unwrap().len(), + self.memories[1].as_incremented().unwrap().len() + ); } } } -pub struct DirectBuffers<'p_buf, 'wo, Peripheral, MemoryBuffer> +pub struct Config<'wo, Peripheral, Memory> where - Peripheral: Payload::Size>, - MemoryBuffer: IMemoryBuffer, + Peripheral: Payload, + Memory: Payload, { - peripheral_buffer: PeripheralBuffer<'p_buf, 'wo, Peripheral>, - memory_buffer: MemoryBuffer, + buffers: Buffers<'wo, Peripheral, Memory>, + stream_config: StreamConfig, } -impl<'p_buf, 'wo, Peripheral, Memory, MemoryBuffer> - DirectBuffers<'p_buf, 'wo, Peripheral, MemoryBuffer> +impl<'wo, Peripheral, Memory> Config<'wo, Peripheral, Memory> where Peripheral: Payload, - Memory: Payload, - MemoryBuffer: IMemoryBuffer, + Memory: Payload, { pub fn new( - peripheral: PeripheralBuffer<'p_buf, 'wo, Peripheral>, - memory_buffer: MemoryBuffer, + buffers: Buffers<'wo, Peripheral, Memory>, + stream_config: StreamConfig, ) -> Self { - assert_ne!(peripheral.is_read(), memory_buffer.first().is_read()); + let s = Self { + buffers, + stream_config, + }; - Self { - peripheral_buffer: peripheral, - memory_buffer, + s.check_self(); + + s + } + + pub fn stream_config(&self) -> StreamConfig { + self.stream_config + } + + pub fn transfer_direction(&self) -> TransferDirection { + if self.buffers.get().peripheral_buffer.is_peripheral() { + if self.buffers.get().peripheral_buffer.is_read() { + TransferDirection::P2M + } else { + TransferDirection::M2P + } + } else { + TransferDirection::M2M } } -} -impl<'p_buf, 'wo, Peripheral, Memory, MemoryBuffer> IBuffers<'p_buf, 'wo> - for DirectBuffers<'p_buf, 'wo, Peripheral, MemoryBuffer> -where - Peripheral: Payload, - Memory: Payload, - MemoryBuffer: IMemoryBuffer, -{ - type Peripheral = Peripheral; - type MemoryBuffer = MemoryBuffer; + pub fn transfer_direction_conf(&self) -> TransferDirectionConf { + match self.transfer_direction() { + dir @ TransferDirection::P2M | dir @ TransferDirection::M2P => { + TransferDirectionConf::NotM2M(NotM2MConf { + transfer_dir: dir.try_into().unwrap(), + transfer_mode: self.stream_config.transfer_mode, + flow: self.stream_config.flow_controller, + }) + } + TransferDirection::M2M => { + if let TransferModeConf::Fifo(fifo_conf) = + self.stream_config.transfer_mode + { + TransferDirectionConf::M2M(fifo_conf) + } else { + unreachable!() + } + } + } + } - const TRANSFER_MODE: TransferMode = TransferMode::Direct; + pub fn pa(&self) -> Pa { + Pa(self.buffers.get().peripheral_buffer.as_ptr(Some(0)) as u32) + } - fn buffers(self) -> Buffers<'p_buf, 'wo, Peripheral, MemoryBuffer> { - Buffers { - peripheral_buffer: self.peripheral_buffer, - memory_buffer: self.memory_buffer, + pub fn m0a(&self) -> M0a { + match &self.buffers.get().memory_buffer { + MemoryBufferType::SingleBuffer(single) => { + M0a(single.memory.as_ptr(Some(0)) as u32) + } + MemoryBufferType::DoubleBuffer(double) => { + M0a(double.memories()[0].as_ptr(Some(0)) as u32) + } } } - fn buffers_ref( - &self, - ) -> BuffersRef<'_, 'p_buf, 'wo, Peripheral, MemoryBuffer> { - BuffersRef { - peripheral_buffer: &self.peripheral_buffer, - memory_buffer: &self.memory_buffer, + pub fn m1a(&self) -> Option { + if let MemoryBufferType::DoubleBuffer(buffer) = + &self.buffers.get().memory_buffer + { + Some(M1a(buffer.memories()[1].as_ptr(Some(0)) as u32)) + } else { + None } } -} -pub trait ITransferDirection<'p_buf, 'wo> { - type Buffers: IBuffers<'p_buf, 'wo>; + pub fn buffers(&self) -> &Buffers<'wo, Peripheral, Memory> { + &self.buffers + } - const TRANSFER_DIRECTION: TransferDirection; + pub fn buffers_mut(&mut self, op: F) + where + for<'a> F: FnOnce( + &'a mut Buffers<'wo, Peripheral, Memory>, + ) -> &'a mut Buffers<'wo, Peripheral, Memory>, + { + let ptr_before = &self.buffers as *const _; + let ptr_after = op(&mut self.buffers) as *const _; - fn buffers(self) -> Self::Buffers; -} + assert_eq!(ptr_before, ptr_after); -pub struct PeripheralToMemory -where - for<'p_buf, 'wo> BUFFERS: IBuffers<'p_buf, 'wo>, -{ - buffers: BUFFERS, -} + self.check_self(); + } -impl PeripheralToMemory -where - for<'p_buf, 'wo> BUFFERS: IBuffers<'p_buf, 'wo>, -{ - pub fn new(buffers: BUFFERS) -> Self { - assert!(buffers.buffers_ref().peripheral_buffer.is_read()); - assert!(buffers.buffers_ref().memory_buffer.first().is_write()); + pub unsafe fn buffers_mut_unchecked( + &mut self, + ) -> &mut Buffers<'wo, Peripheral, Memory> { + &mut self.buffers + } - Self { buffers } + pub fn free(self) -> Buffers<'wo, Peripheral, Memory> { + self.buffers } -} -impl<'p_buf, 'wo, BUFFERS> ITransferDirection<'p_buf, 'wo> - for PeripheralToMemory -where - for<'p_buf1, 'wo1> BUFFERS: IBuffers<'p_buf1, 'wo1>, -{ - type Buffers = BUFFERS; + fn check_self(&self) { + if matches!( + self.stream_config.flow_controller, + FlowControllerConf::Dma( + CircularModeConf::Enabled(BufferModeConf::DoubleBuffer(_)), + ) + ) { + assert!(self.buffers.get().memory_buffer.is_double_buffer()); + } else { + assert!(self.buffers.get().memory_buffer.is_single_buffer()); + } - const TRANSFER_DIRECTION: TransferDirection = TransferDirection::P2M; + if self.transfer_direction() == TransferDirection::M2M { + assert!(matches!( + self.stream_config.transfer_mode, + TransferModeConf::Fifo(_) + )); + assert!(matches!( + self.stream_config.flow_controller, + FlowControllerConf::Dma(CircularModeConf::Disabled) + )); + } - fn buffers(self) -> BUFFERS { - self.buffers + if matches!(self.stream_config.transfer_mode, TransferModeConf::Direct) + { + assert_eq!(Peripheral::Size::SIZE, Memory::Size::SIZE); + } } } -pub struct MemoryToPeripheral -where - for<'p_buf, 'wo> BUFFERS: IBuffers<'p_buf, 'wo>, -{ - buffers: BUFFERS, -} - -impl MemoryToPeripheral +pub struct Buffers<'wo, Peripheral, Memory> where - for<'p_buf, 'wo> BUFFERS: IBuffers<'p_buf, 'wo>, + Peripheral: Payload, + Memory: Payload, { - pub fn new(buffers: BUFFERS) -> Self { - assert!(buffers.buffers_ref().memory_buffer.first().is_read()); - assert!(buffers.buffers_ref().peripheral_buffer.is_write()); - - Self { buffers } - } + peripheral_buffer: Buffer<'wo, Peripheral>, + memory_buffer: MemoryBufferType, } -impl<'p_buf, 'wo, BUFFERS> ITransferDirection<'p_buf, 'wo> - for MemoryToPeripheral +pub struct BuffersView<'a, 'wo, Peripheral, Memory> where - for<'p_buf1, 'wo1> BUFFERS: IBuffers<'p_buf1, 'wo1>, + Peripheral: Payload, + Memory: Payload, { - type Buffers = BUFFERS; - - const TRANSFER_DIRECTION: TransferDirection = TransferDirection::M2P; - - fn buffers(self) -> BUFFERS { - self.buffers - } + pub peripheral_buffer: &'a Buffer<'wo, Peripheral>, + pub memory_buffer: &'a MemoryBufferType, } -pub struct MemoryToMemory<'m_buf, BUFFERS, Memory> +pub struct BuffersViewMut<'a, 'wo, Peripheral, Memory> where - for<'p_buf, 'wo> BUFFERS: - IBuffers<'p_buf, 'wo, MemoryBuffer = SingleBuffer<'m_buf, Memory>>, + Peripheral: Payload, Memory: Payload, { - buffers: BUFFERS, - _phantom: PhantomData<&'m_buf Memory>, + pub peripheral_buffer: &'a mut Buffer<'wo, Peripheral>, + pub memory_buffer: &'a mut MemoryBufferType, } -impl<'m_buf, BUFFERS, Memory> MemoryToMemory<'m_buf, BUFFERS, Memory> +impl<'wo, Peripheral, Memory> Buffers<'wo, Peripheral, Memory> where - for<'p_buf, 'wo> BUFFERS: - IBuffers<'p_buf, 'wo, MemoryBuffer = SingleBuffer<'m_buf, Memory>>, + Peripheral: Payload, Memory: Payload, { - pub fn new(buffers: BUFFERS) -> Self { - assert!(buffers.buffers_ref().peripheral_buffer.is_read()); - assert!(buffers.buffers_ref().memory_buffer.memory.is_write()); + /// # Args + /// + /// * `peripheral_buffer`: Usually `Buffer::Peripheral`, except for `M2M`-transfers (Memory to Memory), where the source buffer is `Buffer::Memory`. + /// * `memory_buffer`: The `MemoryBuffer` of the transfer. + pub fn new( + peripheral_buffer: Buffer<'wo, Peripheral>, + memory_buffer: MemoryBufferType, + ) -> Self { + let s = Self { + peripheral_buffer, + memory_buffer, + }; - Self { - buffers, - _phantom: PhantomData, + s.check_self(); + + s + } + + pub fn get(&self) -> BuffersView { + BuffersView { + peripheral_buffer: &self.peripheral_buffer, + memory_buffer: &self.memory_buffer, } } -} -impl<'p_buf, 'm_buf, 'wo, BUFFERS, Memory> ITransferDirection<'p_buf, 'wo> - for MemoryToMemory<'m_buf, BUFFERS, Memory> -where - for<'p_buf1, 'wo1> BUFFERS: - IBuffers<'p_buf1, 'wo1, MemoryBuffer = SingleBuffer<'m_buf, Memory>>, - Memory: Payload, -{ - type Buffers = BUFFERS; + pub fn get_mut(&mut self, op: F) + where + for<'a> F: FnOnce( + BuffersViewMut<'a, 'wo, Peripheral, Memory>, + ) + -> BuffersViewMut<'a, 'wo, Peripheral, Memory>, + { + let peripheral_before = &self.peripheral_buffer as *const _; + let memory_before = &self.memory_buffer as *const _; - const TRANSFER_DIRECTION: TransferDirection = TransferDirection::M2M; + let view = op(BuffersViewMut { + peripheral_buffer: &mut self.peripheral_buffer, + memory_buffer: &mut self.memory_buffer, + }); - fn buffers(self) -> BUFFERS { - self.buffers + let peripheral_after = view.peripheral_buffer as *const _; + let memory_after = view.memory_buffer as *const _; + + assert_eq!(peripheral_before, peripheral_after); + assert_eq!(memory_before, memory_after); + + self.check_self(); + } + + pub unsafe fn get_mut_unchecked( + &mut self, + ) -> BuffersViewMut<'_, 'wo, Peripheral, Memory> { + BuffersViewMut { + peripheral_buffer: &mut self.peripheral_buffer, + memory_buffer: &mut self.memory_buffer, + } + } + + pub fn free(self) -> (Buffer<'wo, Peripheral>, MemoryBufferType) { + (self.peripheral_buffer, self.memory_buffer) + } + + fn check_self(&self) { + assert_ne!( + self.peripheral_buffer.is_read(), + self.memory_buffer.is_read() + ); + + if self.peripheral_buffer.is_memory() { + assert!(self.peripheral_buffer.is_read()); + } } } +#[derive(Clone, Copy)] +pub struct StreamConfig { + pub transfer_mode: TransferModeConf, + pub flow_controller: FlowControllerConf, +} + #[derive(Clone, Copy)] pub enum PayloadPort where @@ -499,15 +676,15 @@ where Memory(*mut Memory), } -pub enum Buffer<'buf, 'wo, P> +pub enum Buffer<'wo, P> where P: Payload, { - Peripheral(PeripheralBuffer<'buf, 'wo, P>), - Memory(MemoryBuffer<'buf, P>), + Peripheral(PeripheralBuffer<'wo, P>), + Memory(MemoryBuffer

), } -impl<'buf, 'wo, P> Buffer<'buf, 'wo, P> +impl<'wo, P> Buffer<'wo, P> where P: Payload, { @@ -527,51 +704,53 @@ where } } - pub fn into_peripheral(self) -> PeripheralBuffer<'buf, 'wo, P> { - if let Buffer::Peripheral(buffer) = self { - buffer + pub fn into_peripheral(self) -> Option> { + if let Self::Peripheral(buffer) = self { + Some(buffer) } else { - panic!("The buffer is a memory buffer."); + None } } - pub fn as_peripheral(&self) -> &PeripheralBuffer<'buf, 'wo, P> { - if let Buffer::Peripheral(buffer) = self { - buffer + pub fn as_peripheral(&self) -> Option<&PeripheralBuffer<'wo, P>> { + if let Self::Peripheral(buffer) = self { + Some(buffer) } else { - panic!("The buffer is a memory buffer."); + None } } - pub fn as_mut_peripheral(&mut self) -> &mut PeripheralBuffer<'buf, 'wo, P> { - if let Buffer::Peripheral(buffer) = self { - buffer + pub fn as_peripheral_mut( + &mut self, + ) -> Option<&mut PeripheralBuffer<'wo, P>> { + if let Self::Peripheral(buffer) = self { + Some(buffer) } else { - panic!("The buffer is a memory buffer."); + None } } - pub fn into_memory(self) -> MemoryBuffer<'buf, P> { - if let Buffer::Memory(buffer) = self { - buffer + pub fn into_memory(self) -> Option> { + if let Self::Memory(buffer) = self { + Some(buffer) } else { - panic!("The buffer is a peripheral puffer."); + None } } - pub fn as_memory(&self) -> &MemoryBuffer<'buf, P> { - if let Buffer::Memory(buffer) = self { - buffer + pub fn as_memory(&self) -> Option<&MemoryBuffer

> { + if let Self::Memory(buffer) = self { + Some(buffer) } else { - panic!("The buffer is a peripheral puffer."); + None } } - pub fn as_mut_memory(&mut self) -> &mut MemoryBuffer<'buf, P> { - if let Buffer::Memory(buffer) = self { - buffer + pub fn as_memory_mut(&mut self) -> Option<&mut MemoryBuffer

> { + if let Self::Memory(buffer) = self { + Some(buffer) } else { - panic!("The buffer is a peripheral puffer."); + None } } @@ -618,17 +797,15 @@ where } } -pub type BufferStatic<'wo, P> = Buffer<'static, 'wo, P>; - -pub enum MemoryBuffer<'buf, P> +pub enum MemoryBuffer

where P: Payload, { - Fixed(FixedBuffer<'buf, P>), - Incremented(RegularOffsetBuffer<'buf, P>), + Fixed(FixedBuffer

), + Incremented(RegularOffsetBuffer

), } -impl<'buf, P> MemoryBuffer<'buf, P> +impl

MemoryBuffer

where P: Payload, { @@ -648,51 +825,53 @@ where } } - pub fn into_fixed(self) -> FixedBuffer<'buf, P> { - if let MemoryBuffer::Fixed(buffer) = self { - buffer + pub fn into_fixed(self) -> Option> { + if let Self::Fixed(buffer) = self { + Some(buffer) } else { - panic!("The buffer is incremented."); + None } } - pub fn as_fixed(&self) -> &FixedBuffer<'buf, P> { - if let MemoryBuffer::Fixed(buffer) = self { - buffer + pub fn as_fixed(&self) -> Option<&FixedBuffer

> { + if let Self::Fixed(buffer) = self { + Some(buffer) } else { - panic!("The buffer is incremented."); + None } } - pub fn as_mut_fixed(&mut self) -> &mut FixedBuffer<'buf, P> { - if let MemoryBuffer::Fixed(buffer) = self { - buffer + pub fn as_fixed_mut(&mut self) -> Option<&mut FixedBuffer

> { + if let Self::Fixed(buffer) = self { + Some(buffer) } else { - panic!("The buffer is incremented."); + None } } - pub fn into_incremented(self) -> RegularOffsetBuffer<'buf, P> { - if let MemoryBuffer::Incremented(buffer) = self { - buffer + pub fn into_incremented(self) -> Option> { + if let Self::Incremented(buffer) = self { + Some(buffer) } else { - panic!("The buffer is fixed."); + None } } - pub fn as_incremented(&self) -> &RegularOffsetBuffer<'buf, P> { - if let MemoryBuffer::Incremented(buffer) = self { - buffer + pub fn as_incremented(&self) -> Option<&RegularOffsetBuffer

> { + if let Self::Incremented(buffer) = self { + Some(buffer) } else { - panic!("The buffer is fixed."); + None } } - pub fn as_mut_incremented(&mut self) -> &mut RegularOffsetBuffer<'buf, P> { - if let MemoryBuffer::Incremented(buffer) = self { - buffer + pub fn as_incremented_mut( + &mut self, + ) -> Option<&mut RegularOffsetBuffer

> { + if let Self::Incremented(buffer) = self { + Some(buffer) } else { - panic!("The buffer is fixed."); + None } } @@ -725,17 +904,15 @@ where } } -pub type MemoryBufferStatic

= MemoryBuffer<'static, P>; - -pub enum PeripheralBuffer<'buf, 'wo, P> +pub enum PeripheralBuffer<'wo, P> where P: Payload, { - Fixed(FixedBuffer<'buf, P>), - Incremented(IncrementedBuffer<'buf, 'wo, P>), + Fixed(FixedBuffer

), + Incremented(IncrementedBuffer<'wo, P>), } -impl<'buf, 'wo, P> PeripheralBuffer<'buf, 'wo, P> +impl<'wo, P> PeripheralBuffer<'wo, P> where P: Payload, { @@ -755,53 +932,53 @@ where } } - pub fn into_fixed(self) -> FixedBuffer<'buf, P> { - if let PeripheralBuffer::Fixed(buffer) = self { - buffer + pub fn into_fixed(self) -> Option> { + if let Self::Fixed(buffer) = self { + Some(buffer) } else { - panic!("The buffer is incremented."); + None } } - pub fn as_fixed(&self) -> &FixedBuffer<'buf, P> { - if let PeripheralBuffer::Fixed(buffer) = self { - buffer + pub fn as_fixed(&self) -> Option<&FixedBuffer

> { + if let Self::Fixed(buffer) = self { + Some(buffer) } else { - panic!("The buffer is incremented."); + None } } - pub fn as_mut_fixed(&mut self) -> &mut FixedBuffer<'buf, P> { - if let PeripheralBuffer::Fixed(buffer) = self { - buffer + pub fn as_fixed_mut(&mut self) -> Option<&mut FixedBuffer

> { + if let Self::Fixed(buffer) = self { + Some(buffer) } else { - panic!("The buffer is incremented."); + None } } - pub fn into_incremented(self) -> IncrementedBuffer<'buf, 'wo, P> { - if let PeripheralBuffer::Incremented(buffer) = self { - buffer + pub fn into_incremented(self) -> Option> { + if let Self::Incremented(buffer) = self { + Some(buffer) } else { - panic!("The buffer is fixed."); + None } } - pub fn as_incremented(&self) -> &IncrementedBuffer<'buf, 'wo, P> { - if let PeripheralBuffer::Incremented(buffer) = self { - buffer + pub fn as_incremented(&self) -> Option<&IncrementedBuffer<'wo, P>> { + if let Self::Incremented(buffer) = self { + Some(buffer) } else { - panic!("The buffer is fixed."); + None } } - pub fn as_mut_incremented( + pub fn as_incremented_mut( &mut self, - ) -> &mut IncrementedBuffer<'buf, 'wo, P> { - if let PeripheralBuffer::Incremented(buffer) = self { - buffer + ) -> Option<&mut IncrementedBuffer<'wo, P>> { + if let Self::Incremented(buffer) = self { + Some(buffer) } else { - panic!("The buffer is fixed."); + None } } @@ -836,17 +1013,15 @@ where } } -pub type PeripheralBufferStatic<'wo, P> = PeripheralBuffer<'static, 'wo, P>; - -pub enum IncrementedBuffer<'buf, 'wo, P> +pub enum IncrementedBuffer<'wo, P> where P: Payload, { - RegularOffset(RegularOffsetBuffer<'buf, P>), - WordOffset(WordOffsetBuffer<'buf, 'wo, P>), + RegularOffset(RegularOffsetBuffer

), + WordOffset(WordOffsetBuffer<'wo, P>), } -impl<'buf, 'wo, P> IncrementedBuffer<'buf, 'wo, P> +impl<'wo, P> IncrementedBuffer<'wo, P> where P: Payload, { @@ -866,55 +1041,55 @@ where } } - pub fn into_regular_offset(self) -> RegularOffsetBuffer<'buf, P> { - if let IncrementedBuffer::RegularOffset(buffer) = self { - buffer + pub fn into_regular_offset(self) -> Option> { + if let Self::RegularOffset(buffer) = self { + Some(buffer) } else { - panic!("The buffer has word offset."); + None } } - pub fn as_regular_offset(&self) -> &RegularOffsetBuffer<'buf, P> { - if let IncrementedBuffer::RegularOffset(buffer) = self { - buffer + pub fn as_regular_offset(&self) -> Option<&RegularOffsetBuffer

> { + if let Self::RegularOffset(buffer) = self { + Some(buffer) } else { - panic!("The buffer has word offset."); + None } } - pub fn as_mut_regular_offset( + pub fn as_regular_offset_mut( &mut self, - ) -> &mut RegularOffsetBuffer<'buf, P> { - if let IncrementedBuffer::RegularOffset(buffer) = self { - buffer + ) -> Option<&mut RegularOffsetBuffer

> { + if let Self::RegularOffset(buffer) = self { + Some(buffer) } else { - panic!("The buffer has word offset."); + None } } - pub fn into_word_offset(self) -> WordOffsetBuffer<'buf, 'wo, P> { - if let IncrementedBuffer::WordOffset(buffer) = self { - buffer + pub fn into_word_offset(self) -> Option> { + if let Self::WordOffset(buffer) = self { + Some(buffer) } else { - panic!("The buffer has regular offset."); + None } } - pub fn as_word_offset(&self) -> &WordOffsetBuffer<'buf, 'wo, P> { - if let IncrementedBuffer::WordOffset(buffer) = self { - buffer + pub fn as_word_offset(&self) -> Option<&WordOffsetBuffer<'wo, P>> { + if let Self::WordOffset(buffer) = self { + Some(buffer) } else { - panic!("The buffer has regular offset."); + None } } - pub fn as_mut_word_offset( + pub fn as_word_offset_mut( &mut self, - ) -> &mut WordOffsetBuffer<'buf, 'wo, P> { - if let IncrementedBuffer::WordOffset(buffer) = self { - buffer + ) -> Option<&mut WordOffsetBuffer<'wo, P>> { + if let Self::WordOffset(buffer) = self { + Some(buffer) } else { - panic!("The buffer has regular offset."); + None } } @@ -954,17 +1129,15 @@ where } } -pub type IncrementedBufferStatic<'wo, P> = IncrementedBuffer<'static, 'wo, P>; - -pub enum FixedBuffer<'buf, P> +pub enum FixedBuffer

where P: Payload, { - Read(FixedBufferR<'buf, P>), - Write(FixedBufferW<'buf, P>), + Read(FixedBufferR

), + Write(FixedBufferW

), } -impl<'buf, P> FixedBuffer<'buf, P> +impl

FixedBuffer

where P: Payload, { @@ -982,35 +1155,51 @@ where } } - pub fn as_read(&self) -> FixedBufferR<'buf, P> { - if let &FixedBuffer::Read(buffer) = self { - buffer + pub fn into_read(self) -> Option> { + if let Self::Read(buffer) = self { + Some(buffer) } else { - panic!("The buffer is a write buffer."); + None } } - pub fn into_write(self) -> FixedBufferW<'buf, P> { - if let FixedBuffer::Write(buffer) = self { - buffer + pub fn as_read(&self) -> Option<&FixedBufferR

> { + if let Self::Read(buffer) = self { + Some(buffer) } else { - panic!("The buffer is a read buffer."); + None } } - pub fn as_write(&self) -> &FixedBufferW<'buf, P> { - if let FixedBuffer::Write(buffer) = self { - buffer + pub fn as_read_mut(&mut self) -> Option<&mut FixedBufferR

> { + if let Self::Read(buffer) = self { + Some(buffer) } else { - panic!("The buffer is a read buffer."); + None } } - pub fn as_mut_write(&mut self) -> &mut FixedBufferW<'buf, P> { - if let FixedBuffer::Write(buffer) = self { - buffer + pub fn into_write(self) -> Option> { + if let Self::Write(buffer) = self { + Some(buffer) } else { - panic!("The buffer is a read buffer."); + None + } + } + + pub fn as_write(&self) -> Option<&FixedBufferW

> { + if let Self::Write(buffer) = self { + Some(buffer) + } else { + None + } + } + + pub fn as_write_mut(&mut self) -> Option<&mut FixedBufferW

> { + if let Self::Write(buffer) = self { + Some(buffer) + } else { + None } } @@ -1029,19 +1218,17 @@ where } } -pub type FixedBufferStatic

= FixedBuffer<'static, P>; - #[derive(Clone, Copy)] -pub struct FixedBufferR<'buf, P>(*const P, PhantomData<&'buf P>) +pub struct FixedBufferR

(*const P) where P: Payload; -impl<'buf, P> FixedBufferR<'buf, P> +impl

FixedBufferR

where P: Payload, { - pub fn new(buffer: &'buf P) -> Self { - FixedBufferR(buffer, PhantomData) + pub fn new(buffer: &'static P) -> Self { + FixedBufferR(buffer) } pub fn get(self) -> P { @@ -1053,22 +1240,20 @@ where } } -unsafe impl

Send for FixedBufferR<'_, P> where P: Payload {} - -unsafe impl

Sync for FixedBufferR<'_, P> where P: Payload {} +unsafe impl

Send for FixedBufferR

where P: Payload {} -pub type FixedBufferRStatic

= FixedBufferR<'static, P>; +unsafe impl

Sync for FixedBufferR

where P: Payload {} -pub struct FixedBufferW<'buf, P>(*mut P, PhantomData<&'buf mut P>) +pub struct FixedBufferW

(*mut P) where P: Payload; -impl<'buf, P> FixedBufferW<'buf, P> +impl

FixedBufferW

where P: Payload, { - pub fn new(buffer: &'buf mut P) -> Self { - FixedBufferW(buffer, PhantomData) + pub fn new(buffer: &'static mut P) -> Self { + FixedBufferW(buffer) } /// # Safety @@ -1094,21 +1279,19 @@ where } } -unsafe impl

Send for FixedBufferW<'_, P> where P: Payload {} +unsafe impl

Send for FixedBufferW

where P: Payload {} -unsafe impl

Sync for FixedBufferW<'_, P> where P: Payload {} +unsafe impl

Sync for FixedBufferW

where P: Payload {} -pub type FixedBufferWStatic

= FixedBufferW<'static, P>; - -pub enum RegularOffsetBuffer<'buf, P> +pub enum RegularOffsetBuffer

where P: Payload, { - Read(RegularOffsetBufferR<'buf, P>), - Write(RegularOffsetBufferW<'buf, P>), + Read(RegularOffsetBufferR

), + Write(RegularOffsetBufferW

), } -impl<'buf, P> RegularOffsetBuffer<'buf, P> +impl

RegularOffsetBuffer

where P: Payload, { @@ -1126,35 +1309,51 @@ where } } - pub fn as_read(&self) -> RegularOffsetBufferR<'buf, P> { - if let &RegularOffsetBuffer::Read(buffer) = self { - buffer + pub fn into_read(self) -> Option> { + if let RegularOffsetBuffer::Read(buffer) = self { + Some(buffer) } else { - panic!("The buffer is a write buffer."); + None + } + } + + pub fn as_read(&self) -> Option<&RegularOffsetBufferR

> { + if let RegularOffsetBuffer::Read(buffer) = self { + Some(buffer) + } else { + None + } + } + + pub fn as_read_mut(&mut self) -> Option<&mut RegularOffsetBufferR

> { + if let RegularOffsetBuffer::Read(buffer) = self { + Some(buffer) + } else { + None } } - pub fn into_write(self) -> RegularOffsetBufferW<'buf, P> { + pub fn into_write(self) -> Option> { if let RegularOffsetBuffer::Write(buffer) = self { - buffer + Some(buffer) } else { - panic!("The buffer is a read buffer."); + None } } - pub fn as_write(&self) -> &RegularOffsetBufferW<'buf, P> { + pub fn as_write(&self) -> Option<&RegularOffsetBufferW

> { if let RegularOffsetBuffer::Write(buffer) = self { - buffer + Some(buffer) } else { - panic!("The buffer is a read buffer."); + None } } - pub fn as_mut_write(&mut self) -> &mut RegularOffsetBufferW<'buf, P> { + pub fn as_write_mut(&mut self) -> Option<&mut RegularOffsetBufferW

> { if let RegularOffsetBuffer::Write(buffer) = self { - buffer + Some(buffer) } else { - panic!("The buffer is a read buffer."); + None } } @@ -1182,22 +1381,20 @@ where } } -pub type RegularOffsetBufferStatic

= RegularOffsetBuffer<'static, P>; - #[derive(Clone, Copy)] -pub struct RegularOffsetBufferR<'buf, P>(*const [P], PhantomData<&'buf P>) +pub struct RegularOffsetBufferR

(*const [P]) where P: Payload; #[allow(clippy::len_without_is_empty)] -impl<'buf, P> RegularOffsetBufferR<'buf, P> +impl

RegularOffsetBufferR

where P: Payload, { - pub fn new(buffer: &'buf [P]) -> Self { + pub fn new(buffer: &'static [P]) -> Self { check_buffer_not_empty(buffer); - RegularOffsetBufferR(buffer, PhantomData) + RegularOffsetBufferR(buffer) } pub fn get(self, index: usize) -> P { @@ -1219,25 +1416,23 @@ where } } -unsafe impl

Send for RegularOffsetBufferR<'_, P> where P: Payload {} - -unsafe impl

Sync for RegularOffsetBufferR<'_, P> where P: Payload {} +unsafe impl

Send for RegularOffsetBufferR

where P: Payload {} -pub type RegularOffsetBufferRStatic

= RegularOffsetBufferR<'static, P>; +unsafe impl

Sync for RegularOffsetBufferR

where P: Payload {} -pub struct RegularOffsetBufferW<'buf, P>(*mut [P], PhantomData<&'buf mut P>) +pub struct RegularOffsetBufferW

(*mut [P]) where P: Payload; #[allow(clippy::len_without_is_empty)] -impl<'buf, P> RegularOffsetBufferW<'buf, P> +impl

RegularOffsetBufferW

where P: Payload, { - pub fn new(buffer: &'buf mut [P]) -> Self { + pub fn new(buffer: &'static mut [P]) -> Self { check_buffer_not_empty(buffer); - RegularOffsetBufferW(buffer, PhantomData) + RegularOffsetBufferW(buffer) } /// # Safety @@ -1277,11 +1472,9 @@ where } } -unsafe impl

Send for RegularOffsetBufferW<'_, P> where P: Payload {} +unsafe impl

Send for RegularOffsetBufferW

where P: Payload {} -unsafe impl

Sync for RegularOffsetBufferW<'_, P> where P: Payload {} - -pub type RegularOffsetBufferWStatic

= RegularOffsetBufferW<'static, P>; +unsafe impl

Sync for RegularOffsetBufferW

where P: Payload {} unsafe fn read_volatile_slice_buffer

( slice_ptr: *const [P], @@ -1294,15 +1487,15 @@ where ptr::read_volatile(&slice[index] as *const _) } -pub enum WordOffsetBuffer<'buf, 'wo, P> +pub enum WordOffsetBuffer<'wo, P> where P: Payload, { - Read(WordOffsetBufferR<'buf, 'wo, P>), - Write(WordOffsetBufferW<'buf, 'wo, P>), + Read(WordOffsetBufferR<'wo, P>), + Write(WordOffsetBufferW<'wo, P>), } -impl<'buf, 'wo, P> WordOffsetBuffer<'buf, 'wo, P> +impl<'wo, P> WordOffsetBuffer<'wo, P> where P: Payload, { @@ -1320,7 +1513,7 @@ where } } - pub fn as_read(&self) -> WordOffsetBufferR<'buf, 'wo, P> { + pub fn as_read(&self) -> WordOffsetBufferR<'wo, P> { if let &WordOffsetBuffer::Read(buffer) = self { buffer } else { @@ -1328,7 +1521,7 @@ where } } - pub fn into_write(self) -> WordOffsetBufferW<'buf, 'wo, P> { + pub fn into_write(self) -> WordOffsetBufferW<'wo, P> { if let WordOffsetBuffer::Write(buffer) = self { buffer } else { @@ -1336,7 +1529,7 @@ where } } - pub fn as_write(&self) -> &WordOffsetBufferW<'buf, 'wo, P> { + pub fn as_write(&self) -> &WordOffsetBufferW<'wo, P> { if let WordOffsetBuffer::Write(buffer) = self { buffer } else { @@ -1344,7 +1537,7 @@ where } } - pub fn as_mut_write(&mut self) -> &mut WordOffsetBufferW<'buf, 'wo, P> { + pub fn as_mut_write(&mut self) -> &mut WordOffsetBufferW<'wo, P> { if let WordOffsetBuffer::Write(buffer) = self { buffer } else { @@ -1374,29 +1567,24 @@ where } } -pub type WordOffsetBufferStatic<'wo, P> = WordOffsetBuffer<'static, 'wo, P>; - #[derive(Clone, Copy)] -pub struct WordOffsetBufferR<'buf, 'wo, P>( - &'wo [*const P], - PhantomData<&'buf P>, -) +pub struct WordOffsetBufferR<'wo, P>(&'wo [*const P]) where P: Payload; #[allow(clippy::len_without_is_empty)] -impl<'buf, 'wo, P> WordOffsetBufferR<'buf, 'wo, P> +impl<'wo, P> WordOffsetBufferR<'wo, P> where P: Payload, { - pub fn new(buffer: &'wo [&'buf P]) -> Self { + pub fn new(buffer: &'wo [&'static P]) -> Self { check_buffer_not_empty(buffer); let buffer = unsafe { &*(buffer as *const _ as *const _) }; check_word_offset(buffer); - WordOffsetBufferR(buffer, PhantomData) + WordOffsetBufferR(buffer) } pub fn get(self, index: usize) -> P { @@ -1412,37 +1600,26 @@ where } } -unsafe impl<'buf, 'wo, P> Send for WordOffsetBufferR<'buf, 'wo, P> where - P: Payload -{ -} +unsafe impl

Send for WordOffsetBufferR<'_, P> where P: Payload {} -unsafe impl<'buf, 'wo, P> Sync for WordOffsetBufferR<'buf, 'wo, P> where - P: Payload -{ -} +unsafe impl

Sync for WordOffsetBufferR<'_, P> where P: Payload {} -pub type WordOffsetBufferRStatic<'wo, P> = WordOffsetBufferR<'static, 'wo, P>; - -pub struct WordOffsetBufferW<'buf, 'wo, P>( - &'wo mut [*mut P], - PhantomData<&'buf mut P>, -) +pub struct WordOffsetBufferW<'wo, P>(&'wo mut [*mut P]) where P: Payload; #[allow(clippy::len_without_is_empty)] -impl<'buf, 'wo, P> WordOffsetBufferW<'buf, 'wo, P> +impl<'wo, P> WordOffsetBufferW<'wo, P> where P: Payload, { - pub fn new(buffer: &'wo mut [&'buf mut P]) -> Self { + pub fn new(buffer: &'wo mut [&'static mut P]) -> Self { check_buffer_not_empty(buffer); unsafe { check_word_offset::

(&*(buffer as *const _ as *const _)); - WordOffsetBufferW(&mut *(buffer as *mut _ as *mut _), PhantomData) + WordOffsetBufferW(&mut *(buffer as *mut _ as *mut _)) } } @@ -1473,11 +1650,9 @@ where } } -unsafe impl

Send for WordOffsetBufferW<'_, '_, P> where P: Payload {} - -unsafe impl

Sync for WordOffsetBufferW<'_, '_, P> where P: Payload {} +unsafe impl

Send for WordOffsetBufferW<'_, P> where P: Payload {} -pub type WordOffsetBufferWStatic<'wo, P> = WordOffsetBufferW<'static, 'wo, P>; +unsafe impl

Sync for WordOffsetBufferW<'_, P> where P: Payload {} fn check_buffer_not_empty

(buffer: &[P]) { if buffer.is_empty() { @@ -1511,221 +1686,6 @@ where } } -pub(super) fn configure_safe_transfer( - stream: &mut Stream, - peripheral: &PeripheralBuffer, - memory: &MemoryBuffer, -) where - CXX: ChannelId, - Peripheral: Payload, - Memory: Payload, -{ - let p_size = PayloadSize::from_payload::(); - let m_size = PayloadSize::from_payload::(); - - if stream.transfer_mode() == TransferMode::Direct && p_size != m_size { - panic!("The buffer sizes must match if the stream is configured in direct mode."); - } - - stream.set_p_size(p_size.into()); - stream.set_m_size(m_size.into()); - - match peripheral { - PeripheralBuffer::Fixed(buffer) => { - stream.set_pa(Pa(buffer.as_ptr() as u32)); - stream.set_pinc(Pinc::Fixed); - } - PeripheralBuffer::Incremented(buffer) => match buffer { - IncrementedBuffer::RegularOffset(buffer) => { - stream.set_pa(Pa(buffer.as_ptr(0) as u32)); - stream.set_pinc(Pinc::Incremented); - stream.set_pincos(Pincos::PSize); - } - IncrementedBuffer::WordOffset(buffer) => { - stream.set_pa(Pa(buffer.as_ptr(0) as u32)); - stream.set_pinc(Pinc::Incremented); - stream.set_pincos(Pincos::Word); - } - }, - } - - match memory { - MemoryBuffer::Fixed(buffer) => { - stream.set_m0a(M0a(buffer.as_ptr() as u32)); - stream.set_minc(Minc::Fixed); - } - MemoryBuffer::Incremented(buffer) => { - stream.set_m0a(M0a(buffer.as_ptr(0) as u32)); - stream.set_minc(Minc::Incremented); - } - } - - if stream.circular_mode() == CircularMode::Enabled { - if peripheral.is_write() { - stream.set_transfer_direction(TransferDirection::M2P); - } else { - stream.set_transfer_direction(TransferDirection::P2M); - } - } else if peripheral.is_write() { - stream.set_transfer_direction(TransferDirection::M2P); - } else if stream.transfer_direction() == TransferDirection::M2P { - panic!("If memory is the destination, the stream transfer direction must be configured in advance to either `P2M` or `M2M`."); - } - - configure_ndt(stream, peripheral, memory); -} - -fn configure_ndt( - stream: &mut Stream, - peripheral: &PeripheralBuffer, - memory: &MemoryBuffer, -) where - CXX: ChannelId, - Peripheral: Payload, - Memory: Payload, -{ - match peripheral { - PeripheralBuffer::Fixed(_) => { - match memory { - MemoryBuffer::Fixed(_) => { - // NDT must be configured in advance - } - MemoryBuffer::Incremented(buffer) => { - let p_size: usize = - PayloadSize::from_payload::().into(); - let m_size: usize = - PayloadSize::from_payload::().into(); - - let memory_bytes = buffer.len() * m_size; - - if memory_bytes % p_size != 0 { - panic!("Last transfer may be incomplete."); - } - - let ndt = u16::try_from(memory_bytes / p_size).unwrap(); - stream.set_ndt(ndt.into()); - } - } - } - PeripheralBuffer::Incremented(buffer) => { - let ndt = u16::try_from(buffer.len()).unwrap(); - stream.set_ndt(Ndt(ndt)); - } - } -} - -pub(super) fn check_buffer( - peripheral: &PeripheralBuffer, - memory: &MemoryBuffer, -) where - Peripheral: Payload, - Memory: Payload, -{ - if peripheral.is_write() == memory.is_write() { - panic!("One buffer mut be read, one must be write."); - } -} - -pub(super) fn check_double_buffer( - double_buffer: &[MemoryBuffer; 2], -) where - Memory: Payload, -{ - if double_buffer[0].is_fixed() { - if double_buffer[1].is_incremented() { - panic!("Invalid double buffer config: First buffer `Fixed`, second buffer `Incremented`."); - } - } else { - if double_buffer[1].is_fixed() { - panic!("Invalid double buffer config: First buffer `Incremented`, second buffer `Fixed`."); - } - - let len_0 = double_buffer[0].as_incremented().len(); - let len_1 = double_buffer[1].as_incremented().len(); - - if len_0 != len_1 { - panic!( - "Invalid double buffer config: len_0 ({}) != len_1 ({})", - len_0, len_1 - ); - } - } - - if double_buffer[0].is_write() != double_buffer[1].is_write() { - panic!("Both buffers must be either both read or write."); - } -} - -pub(super) unsafe fn set_peripheral_impl( - peripheral: &mut PeripheralBuffer, - index: Option, - payload: Peripheral, -) where - Peripheral: Payload, -{ - match peripheral { - PeripheralBuffer::Fixed(buffer) => buffer.as_mut_write().set(payload), - PeripheralBuffer::Incremented(buffer) => match buffer { - IncrementedBuffer::RegularOffset(buffer) => { - buffer.as_mut_write().set(index.unwrap(), payload) - } - IncrementedBuffer::WordOffset(buffer) => { - buffer.as_mut_write().set(index.unwrap(), payload) - } - }, - } -} - -pub(super) unsafe fn set_memory_impl( - memory: &mut MemoryBuffer, - index: Option, - payload: Memory, -) where - Memory: Payload, -{ - match memory { - MemoryBuffer::Fixed(buffer) => buffer.as_mut_write().set(payload), - MemoryBuffer::Incremented(buffer) => { - buffer.as_mut_write().set(index.unwrap(), payload) - } - } -} - -pub(super) fn mut_ptr_peripheral( - peripheral: &mut PeripheralBuffer, - index: Option, -) -> *mut Peripheral -where - Peripheral: Payload, -{ - match peripheral { - PeripheralBuffer::Fixed(buffer) => buffer.as_mut_write().as_mut_ptr(), - PeripheralBuffer::Incremented(buffer) => match buffer { - IncrementedBuffer::RegularOffset(buffer) => { - buffer.as_mut_write().as_mut_ptr(index.unwrap()) - } - IncrementedBuffer::WordOffset(buffer) => { - buffer.as_mut_write().as_mut_ptr(index.unwrap()) - } - }, - } -} - -pub(super) fn mut_ptr_memory( - memory: &mut MemoryBuffer, - index: Option, -) -> *mut Memory -where - Memory: Payload, -{ - match memory { - MemoryBuffer::Fixed(buffer) => buffer.as_mut_write().as_mut_ptr(), - MemoryBuffer::Incremented(buffer) => { - buffer.as_mut_write().as_mut_ptr(index.unwrap()) - } - } -} - #[derive(Clone, Copy)] pub enum WhichBuffer { First, diff --git a/src/serial/mod.rs b/src/serial/mod.rs index 6412f7c1..7a830794 100644 --- a/src/serial/mod.rs +++ b/src/serial/mod.rs @@ -1,6 +1,6 @@ //! Serial -#[cfg(feature = "dma")] +#[cfg(all(test, feature = "dma"))] pub mod dma; use core::fmt; From 4dab86ae574e91254f7956a31f4dc9725d51244b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ad=C3=A4?= Date: Sat, 18 Apr 2020 12:43:00 +0200 Subject: [PATCH 084/103] Added enum-as-inner dependency to remove some bloat --- Cargo.toml | 2 + src/dma/safe_transfer.rs | 413 +++------------------------------------ 2 files changed, 27 insertions(+), 388 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index f7e28f80..a68385f0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -29,6 +29,8 @@ stm32h7 = "0.10.0" void = { version = "1.0.2", default-features = false } cast = { version = "0.2.2", default-features = false } nb = "0.1.2" +# FIXME: Change to crates.io when next version (> 0.3.2) gets released +enum-as-inner = { git = "https://github.com/bluejekyll/enum-as-inner", rev = "9670594f29ade6feba581ee746736087e335210b" } [dependencies.bare-metal] version = "0.2.4" features = ["const-fn"] diff --git a/src/dma/safe_transfer.rs b/src/dma/safe_transfer.rs index eb43aa7f..b2b06b35 100644 --- a/src/dma/safe_transfer.rs +++ b/src/dma/safe_transfer.rs @@ -10,6 +10,7 @@ use crate::private; use core::convert::TryInto; use core::fmt::Debug; use core::{mem, ptr}; +use enum_as_inner::EnumAsInner; pub trait TransferState<'wo>: Send + Sync + private::Sealed { type Peripheral: Payload; @@ -207,6 +208,7 @@ unsafe impl Payload for f32 { type Size = Word; } +#[derive(Debug, EnumAsInner)] pub enum MemoryBufferType { SingleBuffer(SingleBuffer), DoubleBuffer(DoubleBuffer), @@ -221,58 +223,6 @@ impl MemoryBufferType { self.as_double_buffer().is_some() } - pub fn into_single_buffer(self) -> Option> { - if let Self::SingleBuffer(buffer) = self { - Some(buffer) - } else { - None - } - } - - pub fn as_single_buffer(&self) -> Option<&SingleBuffer> { - if let Self::SingleBuffer(buffer) = self { - Some(buffer) - } else { - None - } - } - - pub fn as_single_buffer_mut( - &mut self, - ) -> Option<&mut SingleBuffer> { - if let Self::SingleBuffer(buffer) = self { - Some(buffer) - } else { - None - } - } - - pub fn into_double_buffer(self) -> Option> { - if let Self::DoubleBuffer(buffer) = self { - Some(buffer) - } else { - None - } - } - - pub fn as_double_buffer(&self) -> Option<&DoubleBuffer> { - if let Self::DoubleBuffer(buffer) = self { - Some(buffer) - } else { - None - } - } - - pub fn as_double_buffer_mut( - &mut self, - ) -> Option<&mut DoubleBuffer> { - if let Self::DoubleBuffer(buffer) = self { - Some(buffer) - } else { - None - } - } - pub fn is_read(&self) -> bool { match self { MemoryBufferType::SingleBuffer(buffer) => buffer.memory.is_read(), @@ -294,6 +244,7 @@ impl MemoryBufferType { } } +#[derive(Debug)] pub struct SingleBuffer where Memory: Payload, @@ -301,6 +252,7 @@ where pub memory: MemoryBuffer, } +#[derive(Debug)] pub struct DoubleBuffer where Memory: Payload, @@ -375,6 +327,7 @@ impl DoubleBuffer { } } +#[derive(Debug)] pub struct Config<'wo, Peripheral, Memory> where Peripheral: Payload, @@ -523,6 +476,7 @@ where } } +#[derive(Debug)] pub struct Buffers<'wo, Peripheral, Memory> where Peripheral: Payload, @@ -532,6 +486,7 @@ where memory_buffer: MemoryBufferType, } +#[derive(Debug)] pub struct BuffersView<'a, 'wo, Peripheral, Memory> where Peripheral: Payload, @@ -541,6 +496,7 @@ where pub memory_buffer: &'a MemoryBufferType, } +#[derive(Debug)] pub struct BuffersViewMut<'a, 'wo, Peripheral, Memory> where Peripheral: Payload, @@ -629,13 +585,13 @@ where } } -#[derive(Clone, Copy)] +#[derive(Debug, Clone, Copy)] pub struct StreamConfig { pub transfer_mode: TransferModeConf, pub flow_controller: FlowControllerConf, } -#[derive(Clone, Copy)] +#[derive(Debug, Clone, Copy)] pub enum PayloadPort where Peripheral: Payload, @@ -667,6 +623,7 @@ where } } +#[derive(Debug, EnumAsInner)] pub enum PointerPort where Peripheral: Payload, @@ -676,6 +633,7 @@ where Memory(*mut Memory), } +#[derive(Debug, EnumAsInner)] pub enum Buffer<'wo, P> where P: Payload, @@ -704,56 +662,6 @@ where } } - pub fn into_peripheral(self) -> Option> { - if let Self::Peripheral(buffer) = self { - Some(buffer) - } else { - None - } - } - - pub fn as_peripheral(&self) -> Option<&PeripheralBuffer<'wo, P>> { - if let Self::Peripheral(buffer) = self { - Some(buffer) - } else { - None - } - } - - pub fn as_peripheral_mut( - &mut self, - ) -> Option<&mut PeripheralBuffer<'wo, P>> { - if let Self::Peripheral(buffer) = self { - Some(buffer) - } else { - None - } - } - - pub fn into_memory(self) -> Option> { - if let Self::Memory(buffer) = self { - Some(buffer) - } else { - None - } - } - - pub fn as_memory(&self) -> Option<&MemoryBuffer

> { - if let Self::Memory(buffer) = self { - Some(buffer) - } else { - None - } - } - - pub fn as_memory_mut(&mut self) -> Option<&mut MemoryBuffer

> { - if let Self::Memory(buffer) = self { - Some(buffer) - } else { - None - } - } - pub unsafe fn get(&self, index: Option) -> P { match self { Buffer::Peripheral(buffer) => buffer.get(index), @@ -797,6 +705,7 @@ where } } +#[derive(Debug, EnumAsInner)] pub enum MemoryBuffer

where P: Payload, @@ -825,56 +734,6 @@ where } } - pub fn into_fixed(self) -> Option> { - if let Self::Fixed(buffer) = self { - Some(buffer) - } else { - None - } - } - - pub fn as_fixed(&self) -> Option<&FixedBuffer

> { - if let Self::Fixed(buffer) = self { - Some(buffer) - } else { - None - } - } - - pub fn as_fixed_mut(&mut self) -> Option<&mut FixedBuffer

> { - if let Self::Fixed(buffer) = self { - Some(buffer) - } else { - None - } - } - - pub fn into_incremented(self) -> Option> { - if let Self::Incremented(buffer) = self { - Some(buffer) - } else { - None - } - } - - pub fn as_incremented(&self) -> Option<&RegularOffsetBuffer

> { - if let Self::Incremented(buffer) = self { - Some(buffer) - } else { - None - } - } - - pub fn as_incremented_mut( - &mut self, - ) -> Option<&mut RegularOffsetBuffer

> { - if let Self::Incremented(buffer) = self { - Some(buffer) - } else { - None - } - } - pub unsafe fn get(&self, index: Option) -> P { match self { MemoryBuffer::Fixed(buffer) => buffer.get(), @@ -904,6 +763,7 @@ where } } +#[derive(Debug, EnumAsInner)] pub enum PeripheralBuffer<'wo, P> where P: Payload, @@ -932,56 +792,6 @@ where } } - pub fn into_fixed(self) -> Option> { - if let Self::Fixed(buffer) = self { - Some(buffer) - } else { - None - } - } - - pub fn as_fixed(&self) -> Option<&FixedBuffer

> { - if let Self::Fixed(buffer) = self { - Some(buffer) - } else { - None - } - } - - pub fn as_fixed_mut(&mut self) -> Option<&mut FixedBuffer

> { - if let Self::Fixed(buffer) = self { - Some(buffer) - } else { - None - } - } - - pub fn into_incremented(self) -> Option> { - if let Self::Incremented(buffer) = self { - Some(buffer) - } else { - None - } - } - - pub fn as_incremented(&self) -> Option<&IncrementedBuffer<'wo, P>> { - if let Self::Incremented(buffer) = self { - Some(buffer) - } else { - None - } - } - - pub fn as_incremented_mut( - &mut self, - ) -> Option<&mut IncrementedBuffer<'wo, P>> { - if let Self::Incremented(buffer) = self { - Some(buffer) - } else { - None - } - } - pub unsafe fn get(&self, index: Option) -> P { match self { PeripheralBuffer::Fixed(buffer) => buffer.get(), @@ -1013,6 +823,7 @@ where } } +#[derive(Debug, EnumAsInner)] pub enum IncrementedBuffer<'wo, P> where P: Payload, @@ -1041,58 +852,6 @@ where } } - pub fn into_regular_offset(self) -> Option> { - if let Self::RegularOffset(buffer) = self { - Some(buffer) - } else { - None - } - } - - pub fn as_regular_offset(&self) -> Option<&RegularOffsetBuffer

> { - if let Self::RegularOffset(buffer) = self { - Some(buffer) - } else { - None - } - } - - pub fn as_regular_offset_mut( - &mut self, - ) -> Option<&mut RegularOffsetBuffer

> { - if let Self::RegularOffset(buffer) = self { - Some(buffer) - } else { - None - } - } - - pub fn into_word_offset(self) -> Option> { - if let Self::WordOffset(buffer) = self { - Some(buffer) - } else { - None - } - } - - pub fn as_word_offset(&self) -> Option<&WordOffsetBuffer<'wo, P>> { - if let Self::WordOffset(buffer) = self { - Some(buffer) - } else { - None - } - } - - pub fn as_word_offset_mut( - &mut self, - ) -> Option<&mut WordOffsetBuffer<'wo, P>> { - if let Self::WordOffset(buffer) = self { - Some(buffer) - } else { - None - } - } - pub fn len(&self) -> usize { match self { IncrementedBuffer::RegularOffset(buffer) => buffer.len(), @@ -1129,6 +888,7 @@ where } } +#[derive(Debug, EnumAsInner)] pub enum FixedBuffer

where P: Payload, @@ -1155,54 +915,6 @@ where } } - pub fn into_read(self) -> Option> { - if let Self::Read(buffer) = self { - Some(buffer) - } else { - None - } - } - - pub fn as_read(&self) -> Option<&FixedBufferR

> { - if let Self::Read(buffer) = self { - Some(buffer) - } else { - None - } - } - - pub fn as_read_mut(&mut self) -> Option<&mut FixedBufferR

> { - if let Self::Read(buffer) = self { - Some(buffer) - } else { - None - } - } - - pub fn into_write(self) -> Option> { - if let Self::Write(buffer) = self { - Some(buffer) - } else { - None - } - } - - pub fn as_write(&self) -> Option<&FixedBufferW

> { - if let Self::Write(buffer) = self { - Some(buffer) - } else { - None - } - } - - pub fn as_write_mut(&mut self) -> Option<&mut FixedBufferW

> { - if let Self::Write(buffer) = self { - Some(buffer) - } else { - None - } - } - pub unsafe fn get(&self) -> P { match self { FixedBuffer::Read(buffer) => buffer.get(), @@ -1218,7 +930,7 @@ where } } -#[derive(Clone, Copy)] +#[derive(Debug, Clone, Copy)] pub struct FixedBufferR

(*const P) where P: Payload; @@ -1244,6 +956,7 @@ unsafe impl

Send for FixedBufferR

where P: Payload {} unsafe impl

Sync for FixedBufferR

where P: Payload {} +#[derive(Debug)] pub struct FixedBufferW

(*mut P) where P: Payload; @@ -1283,6 +996,7 @@ unsafe impl

Send for FixedBufferW

where P: Payload {} unsafe impl

Sync for FixedBufferW

where P: Payload {} +#[derive(Debug, EnumAsInner)] pub enum RegularOffsetBuffer

where P: Payload, @@ -1309,54 +1023,6 @@ where } } - pub fn into_read(self) -> Option> { - if let RegularOffsetBuffer::Read(buffer) = self { - Some(buffer) - } else { - None - } - } - - pub fn as_read(&self) -> Option<&RegularOffsetBufferR

> { - if let RegularOffsetBuffer::Read(buffer) = self { - Some(buffer) - } else { - None - } - } - - pub fn as_read_mut(&mut self) -> Option<&mut RegularOffsetBufferR

> { - if let RegularOffsetBuffer::Read(buffer) = self { - Some(buffer) - } else { - None - } - } - - pub fn into_write(self) -> Option> { - if let RegularOffsetBuffer::Write(buffer) = self { - Some(buffer) - } else { - None - } - } - - pub fn as_write(&self) -> Option<&RegularOffsetBufferW

> { - if let RegularOffsetBuffer::Write(buffer) = self { - Some(buffer) - } else { - None - } - } - - pub fn as_write_mut(&mut self) -> Option<&mut RegularOffsetBufferW

> { - if let RegularOffsetBuffer::Write(buffer) = self { - Some(buffer) - } else { - None - } - } - // Methods both variants implement pub unsafe fn get(&self, index: usize) -> P { @@ -1381,7 +1047,7 @@ where } } -#[derive(Clone, Copy)] +#[derive(Debug, Clone, Copy)] pub struct RegularOffsetBufferR

(*const [P]) where P: Payload; @@ -1420,6 +1086,7 @@ unsafe impl

Send for RegularOffsetBufferR

where P: Payload {} unsafe impl

Sync for RegularOffsetBufferR

where P: Payload {} +#[derive(Debug)] pub struct RegularOffsetBufferW

(*mut [P]) where P: Payload; @@ -1487,6 +1154,7 @@ where ptr::read_volatile(&slice[index] as *const _) } +#[derive(Debug, EnumAsInner)] pub enum WordOffsetBuffer<'wo, P> where P: Payload, @@ -1513,38 +1181,6 @@ where } } - pub fn as_read(&self) -> WordOffsetBufferR<'wo, P> { - if let &WordOffsetBuffer::Read(buffer) = self { - buffer - } else { - panic!("The buffer is a write buffer."); - } - } - - pub fn into_write(self) -> WordOffsetBufferW<'wo, P> { - if let WordOffsetBuffer::Write(buffer) = self { - buffer - } else { - panic!("The buffer is a read buffer."); - } - } - - pub fn as_write(&self) -> &WordOffsetBufferW<'wo, P> { - if let WordOffsetBuffer::Write(buffer) = self { - buffer - } else { - panic!("The buffer is a read buffer."); - } - } - - pub fn as_mut_write(&mut self) -> &mut WordOffsetBufferW<'wo, P> { - if let WordOffsetBuffer::Write(buffer) = self { - buffer - } else { - panic!("The buffer is a read buffer."); - } - } - pub unsafe fn get(&self, index: usize) -> P { match self { WordOffsetBuffer::Read(buffer) => buffer.get(index), @@ -1567,7 +1203,7 @@ where } } -#[derive(Clone, Copy)] +#[derive(Debug, Clone, Copy)] pub struct WordOffsetBufferR<'wo, P>(&'wo [*const P]) where P: Payload; @@ -1604,6 +1240,7 @@ unsafe impl

Send for WordOffsetBufferR<'_, P> where P: Payload {} unsafe impl

Sync for WordOffsetBufferR<'_, P> where P: Payload {} +#[derive(Debug)] pub struct WordOffsetBufferW<'wo, P>(&'wo mut [*mut P]) where P: Payload; @@ -1686,7 +1323,7 @@ where } } -#[derive(Clone, Copy)] +#[derive(Debug, Clone, Copy)] pub enum WhichBuffer { First, Second, From ad9fc7e9f6e7c8e84530bb9e98c36d89a5a277f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ad=C3=A4?= Date: Mon, 20 Apr 2020 11:09:14 +0200 Subject: [PATCH 085/103] many things --- src/dma/macros.rs | 4 +- src/dma/mod.rs | 116 +- src/dma/stream.rs | 1771 ++++----------------- src/dma/{safe_transfer.rs => transfer.rs} | 1067 +++++++++---- src/dma/utils.rs | 4 +- src/serial/dma.rs | 8 +- 6 files changed, 1135 insertions(+), 1835 deletions(-) rename src/dma/{safe_transfer.rs => transfer.rs} (50%) diff --git a/src/dma/macros.rs b/src/dma/macros.rs index 81f6149d..c3d4e92c 100644 --- a/src/dma/macros.rs +++ b/src/dma/macros.rs @@ -2,10 +2,10 @@ macro_rules! type_state { ($trait:ident, $($type_state:ident),*) => { - pub trait $trait: core::fmt::Debug + PartialEq + Eq + Clone + Copy + Send + Sync + crate::private::Sealed {} + pub trait $trait: Copy + Clone + PartialEq + Eq + core::fmt::Debug + crate::private::Sealed {} $( - #[derive(Debug, PartialEq, Eq, Clone, Copy)] + #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] pub struct $type_state; impl crate::private::Sealed for $type_state {} diff --git a/src/dma/mod.rs b/src/dma/mod.rs index 8a1b0411..80c5193f 100644 --- a/src/dma/mod.rs +++ b/src/dma/mod.rs @@ -6,8 +6,8 @@ #[macro_use] mod macros; pub mod mux; -pub mod safe_transfer; pub mod stream; +pub mod transfer; mod utils; use self::mux::request_gen::{ @@ -20,22 +20,20 @@ use self::mux::{ RequestGenerator, RequestId, SyncDisabled, SyncED as ISyncED, SyncEnabled, SyncId, SyncOverrunInterrupt, SyncPolarity, }; -use self::safe_transfer::{ - Config as TransferConfig, MemoryBuffer, Ongoing, Payload, PayloadSize, - PeripheralBuffer, Start, TransferState, -}; use self::stream::{ BufferMode, BufferModeConf, CircularMode, CircularModeConf, Config, - CurrentTarget, DirectModeErrorInterrupt, Disabled, DoubleBufferConf, - Enabled, Error, Event, FifoConf, FifoErrorInterrupt, FifoThreshold, - FlowController, FlowControllerConf, HalfTransferInterrupt, IntoNum, - IsrCleared, IsrState as IIsrState, IsrUncleared, M0a, M1a, MBurst, MSize, - Minc, Ndt, NotM2MConf, PBurst, PBurstConf, PSize, Pa, Pinc, Pincos, - PriorityLevel, StreamIsr, TransferCompleteInterrupt, TransferDirection, - TransferDirectionConf, TransferErrorInterrupt, TransferMode, - TransferModeConf, ED as IED, + CurrentTarget, DirectConf, DirectModeErrorInterrupt, Disabled, + DoubleBufferConf, Enabled, Error, Event, FifoConf, FifoErrorInterrupt, + FifoThreshold, FlowController, FlowControllerConf, HalfTransferInterrupt, + IntoNum, IsrCleared, IsrState as IIsrState, IsrUncleared, M0a, M1a, MBurst, + MSize, Minc, Ndt, NotM2MConf, PBurst, PBurstConf, PSize, Pa, Pinc, + PincConf, Pincos, PriorityLevel, StreamIsr, TransferCompleteInterrupt, + TransferDirection, TransferDirectionConf, TransferErrorInterrupt, + TransferMode, TransferModeConf, ED as IED, +}; +use self::transfer::{ + Config as TransferConfig, Ongoing, Payload, Start, TransferState, }; -use crate::dma::safe_transfer::Buffer; use crate::nb::{self, Error as NbError}; use crate::private; use crate::rcc::Ccdr; @@ -47,7 +45,7 @@ use core::marker::PhantomData; use stm32h7::stm32h743::DMAMUX1; /// Marker Trait for DMA peripherals -pub trait DmaPeripheral: Send + private::Sealed {} +pub trait DmaPeripheral: private::Sealed {} impl DmaPeripheral for DMA1 {} impl DmaPeripheral for DMA2 {} @@ -202,7 +200,6 @@ where transfer_error_interrupt: self.transfer_error_interrupt(), direct_mode_error_interrupt: self.direct_mode_error_interrupt(), fifo_error_interrupt: self.fifo_error_interrupt(), - pinc: self.pinc(), minc: self.minc(), priority_level: self.priority_level(), p_size: self.p_size(), @@ -215,8 +212,11 @@ where fn transfer_direction_config(&self) -> TransferDirectionConf { match self.transfer_direction() { - TransferDirection::P2M | TransferDirection::M2P => { - TransferDirectionConf::NotM2M(self.not_m2m_config()) + TransferDirection::P2M => { + TransferDirectionConf::P2M(self.not_m2m_config()) + } + TransferDirection::M2P => { + TransferDirectionConf::M2P(self.not_m2m_config()) } TransferDirection::M2M => { TransferDirectionConf::M2M(self.fifo_config()) @@ -226,15 +226,16 @@ where fn not_m2m_config(&self) -> NotM2MConf { NotM2MConf { - transfer_dir: self.transfer_direction().try_into().unwrap(), transfer_mode: self.transfer_mode_config(), - flow: self.flow_controller_config(), + flow_controller: self.flow_controller_config(), } } fn transfer_mode_config(&self) -> TransferModeConf { match self.transfer_mode() { - TransferMode::Direct => TransferModeConf::Direct, + TransferMode::Direct => { + TransferModeConf::Direct(self.direct_conf()) + } TransferMode::Fifo => TransferModeConf::Fifo(self.fifo_config()), } } @@ -273,6 +274,10 @@ where } } + fn direct_conf(&self) -> DirectConf { + DirectConf { pinc: self.pinc() } + } + fn fifo_config(&self) -> FifoConf { FifoConf { fifo_threshold: self.fifo_threshold().unwrap(), @@ -284,10 +289,17 @@ where fn p_burst_config(&self) -> PBurstConf { match self.p_burst() { - PBurst::Single => PBurstConf::Single(self.pincos()), - PBurst::Incr4 => PBurstConf::Incr4, - PBurst::Incr8 => PBurstConf::Incr8, - PBurst::Incr16 => PBurstConf::Incr16, + PBurst::Single => PBurstConf::Single(self.pinc_conf()), + PBurst::Incr4 => PBurstConf::Incr4(self.pinc()), + PBurst::Incr8 => PBurstConf::Incr8(self.pinc()), + PBurst::Incr16 => PBurstConf::Incr16(self.pinc()), + } + } + + fn pinc_conf(&self) -> PincConf { + match self.pinc() { + Pinc::Fixed => PincConf::Fixed, + Pinc::Incremented => PincConf::Incremented(self.pincos()), } } @@ -510,7 +522,7 @@ where config.direct_mode_error_interrupt, ); self.set_fifo_error_interrupt(config.fifo_error_interrupt); - self.set_pinc(config.pinc); + self.set_pinc(config.pinc()); self.set_minc(config.minc); self.set_priority_level(config.priority_level); self.set_p_size(config.p_size); @@ -530,7 +542,10 @@ where self.set_p_burst(config.p_burst()); self.set_m_burst(config.m_burst()); self.set_m_size(config.m_size()); - self.set_pincos(config.pincos()); + + if let Some(pincos) = config.pincos() { + self.set_pincos(pincos); + } self.set_current_target(config.current_target()); if let Some(m1a) = config.m1a() { @@ -1607,7 +1622,7 @@ where Transfer { state: Ongoing { stream: unsafe { stream.enable() }, - buffers: self.state.conf.free(), + buffers: self.state.conf.free().free(), }, _phantom: PhantomData, } @@ -1618,45 +1633,8 @@ where stream: &mut Stream, ) { let mut conf = stream.config(); - conf.transfer_direction = self.state.conf.transfer_direction_conf(); - - // Configure ndt - - let buffers = self.state.buffers().get(); - - match buffers.peripheral_buffer { - Buffer::Peripheral(PeripheralBuffer::Fixed(_)) - | Buffer::Memory(MemoryBuffer::Fixed(_)) => { - match buffers.memory_buffer.m0a() { - MemoryBuffer::Fixed(_) => { - // NDT must be configured in advance - } - MemoryBuffer::Incremented(buffer) => { - let p_size: usize = - PayloadSize::from_payload::().into(); - let m_size: usize = - PayloadSize::from_payload::().into(); - - let memory_bytes = buffer.len() * m_size; - - if memory_bytes % p_size != 0 { - panic!("Last transfer may be incomplete."); - } - - let ndt = u16::try_from(memory_bytes / p_size).unwrap(); - conf.ndt = Ndt(ndt); - } - } - } - Buffer::Peripheral(PeripheralBuffer::Incremented(buffer)) => { - let ndt = u16::try_from(buffer.len()).unwrap(); - conf.ndt = Ndt(ndt); - } - Buffer::Memory(MemoryBuffer::Incremented(buffer)) => { - let ndt = u16::try_from(buffer.len()).unwrap(); - conf.ndt = Ndt(ndt); - } - } + + self.state.conf.stream_config(&mut conf); stream.apply_config(conf); } @@ -1934,6 +1912,10 @@ impl Dma { .set_bit() }); } + + pub fn free(self) -> (DMA1, DMA2, DMAMUX1) { + (self._dma_1, self._dma_2, self._dma_mux) + } } pub trait DmaExt: DmaPeripheral { diff --git a/src/dma/stream.rs b/src/dma/stream.rs index bed6842a..03c5c22d 100644 --- a/src/dma/stream.rs +++ b/src/dma/stream.rs @@ -1,10 +1,7 @@ //! DMA Stream -use super::utils::DefaultTraits; use super::DmaPeripheral; -use crate::private; use crate::stm32::dma1::{HIFCR, HISR, LIFCR, LISR}; -use core::convert::TryFrom; use core::marker::PhantomData; type_state! { @@ -263,7 +260,6 @@ pub struct Config { pub transfer_error_interrupt: TransferErrorInterrupt, pub direct_mode_error_interrupt: DirectModeErrorInterrupt, pub fifo_error_interrupt: FifoErrorInterrupt, - pub pinc: Pinc, pub minc: Minc, pub priority_level: PriorityLevel, pub p_size: PSize, @@ -279,145 +275,51 @@ impl Config { } pub fn transfer_mode(self) -> TransferMode { - match self.transfer_direction { - TransferDirectionConf::NotM2M(NotM2MConf { - transfer_mode, .. - }) => transfer_mode.into(), - TransferDirectionConf::M2M(_) => TransferMode::Fifo, - } + self.transfer_direction.transfer_mode() } pub fn flow_controller(self) -> FlowController { - match self.transfer_direction { - TransferDirectionConf::NotM2M(NotM2MConf { flow, .. }) => { - flow.into() - } - TransferDirectionConf::M2M(_) => FlowController::Dma, - } + self.transfer_direction.flow_controller() } pub fn circular_mode(self) -> CircularMode { - match self.transfer_direction { - TransferDirectionConf::NotM2M(NotM2MConf { - flow: FlowControllerConf::Dma(circular_mode), - .. - }) => circular_mode.into(), - _ => CircularMode::Disabled, - } + self.transfer_direction.circular_mode() } pub fn buffer_mode(self) -> BufferMode { - match self.transfer_direction { - TransferDirectionConf::NotM2M(NotM2MConf { - flow: - FlowControllerConf::Dma(CircularModeConf::Enabled(buffer_mode)), - .. - }) => buffer_mode.into(), - _ => BufferMode::Regular, - } + self.transfer_direction.buffer_mode() } pub fn fifo_threshold(self) -> Option { - match self.transfer_direction { - TransferDirectionConf::NotM2M(NotM2MConf { - transfer_mode: - TransferModeConf::Fifo(FifoConf { fifo_threshold, .. }), - .. - }) => Some(fifo_threshold), - TransferDirectionConf::M2M(FifoConf { fifo_threshold, .. }) => { - Some(fifo_threshold) - } - _ => None, - } + self.transfer_direction.fifo_threshold() } pub fn p_burst(self) -> PBurst { - match self.transfer_direction { - TransferDirectionConf::NotM2M(NotM2MConf { - transfer_mode: TransferModeConf::Fifo(FifoConf { p_burst, .. }), - .. - }) => p_burst.into(), - TransferDirectionConf::M2M(FifoConf { p_burst, .. }) => { - p_burst.into() - } - _ => PBurst::Single, - } + self.transfer_direction.p_burst() } pub fn m_burst(self) -> MBurst { - match self.transfer_direction { - TransferDirectionConf::NotM2M(NotM2MConf { - transfer_mode: TransferModeConf::Fifo(FifoConf { m_burst, .. }), - .. - }) => m_burst, - TransferDirectionConf::M2M(FifoConf { m_burst, .. }) => m_burst, - _ => MBurst::Single, - } + self.transfer_direction.m_burst() } pub fn m_size(self) -> MSize { - match self.transfer_direction { - TransferDirectionConf::NotM2M(NotM2MConf { - transfer_mode: TransferModeConf::Fifo(FifoConf { m_size, .. }), - .. - }) => m_size, - TransferDirectionConf::M2M(FifoConf { m_size, .. }) => m_size, - _ => match self.p_size { - PSize::Byte => MSize::Byte, - PSize::HalfWord => MSize::HalfWord, - PSize::Word => MSize::Word, - }, - } + self.transfer_direction.m_size(Some(self.p_size)) } - pub fn pincos(self) -> Pincos { - match self.transfer_direction { - TransferDirectionConf::NotM2M(NotM2MConf { - transfer_mode: - TransferModeConf::Fifo(FifoConf { - p_burst: PBurstConf::Single(pincos), - .. - }), - .. - }) => pincos, - TransferDirectionConf::M2M(FifoConf { - p_burst: PBurstConf::Single(pincos), - .. - }) => pincos, - _ => Pincos::PSize, - } + pub fn pinc(self) -> Pinc { + self.transfer_direction.pinc() + } + + pub fn pincos(self) -> Option { + self.transfer_direction.pincos() } pub fn current_target(self) -> CurrentTarget { - match self.transfer_direction { - TransferDirectionConf::NotM2M(NotM2MConf { - flow: - FlowControllerConf::Dma(CircularModeConf::Enabled( - BufferModeConf::DoubleBuffer(DoubleBufferConf { - current_target, - .. - }), - )), - .. - }) => current_target, - _ => CurrentTarget::M0a, - } + self.transfer_direction.current_target() } pub fn m1a(self) -> Option { - match self.transfer_direction { - TransferDirectionConf::NotM2M(NotM2MConf { - flow: - FlowControllerConf::Dma(CircularModeConf::Enabled( - BufferModeConf::DoubleBuffer(DoubleBufferConf { - m1a, - .. - }), - )), - .. - }) => Some(m1a), - _ => None, - } + self.transfer_direction.m1a() } } @@ -427,1505 +329,476 @@ impl Config { #[derive(Debug, PartialEq, Eq, Clone, Copy)] pub enum TransferDirectionConf { + P2M(NotM2MConf), + M2P(NotM2MConf), M2M(FifoConf), - NotM2M(NotM2MConf), } -impl From for TransferDirection { - fn from(conf: TransferDirectionConf) -> TransferDirection { - match conf { - TransferDirectionConf::NotM2M(NotM2MConf { - transfer_dir, .. - }) => transfer_dir.into(), - TransferDirectionConf::M2M(_) => TransferDirection::M2M, +impl TransferDirectionConf { + pub fn transfer_mode(self) -> TransferMode { + match self { + Self::P2M(conf) | Self::M2P(conf) => conf.transfer_mode(), + Self::M2M(_) => TransferMode::Fifo, } } -} - -///////////////////////////////////////////////////////////////////////// -// # NOT-M2M CONFIG -///////////////////////////////////////////////////////////////////////// - -#[derive(Debug, PartialEq, Eq, Clone, Copy)] -pub struct NotM2MConf { - pub transfer_dir: TransferDirectionNotM2M, - pub transfer_mode: TransferModeConf, - pub flow: FlowControllerConf, -} - -///////////////////////////////////////////////////////////////////////// -// # TRANSFER DIRECTION NOT M2M -///////////////////////////////////////////////////////////////////////// - -#[derive(Debug, PartialEq, Eq, Clone, Copy)] -pub enum TransferDirectionNotM2M { - P2M, - M2P, -} -impl From for TransferDirection { - fn from(dir: TransferDirectionNotM2M) -> Self { - match dir { - TransferDirectionNotM2M::P2M => Self::P2M, - TransferDirectionNotM2M::M2P => Self::M2P, + pub fn flow_controller(self) -> FlowController { + match self { + Self::P2M(conf) | Self::M2P(conf) => conf.flow_controller(), + Self::M2M(_) => FlowController::Dma, } } -} -impl TryFrom for TransferDirectionNotM2M { - type Error = (); - - fn try_from(value: TransferDirection) -> Result { - match value { - TransferDirection::P2M => Ok(TransferDirectionNotM2M::P2M), - TransferDirection::M2P => Ok(TransferDirectionNotM2M::M2P), - _ => Err(()), + pub fn pinc(self) -> Pinc { + match self { + Self::P2M(conf) | Self::M2P(conf) => conf.pinc(), + Self::M2M(conf) => conf.pinc(), } } -} - -///////////////////////////////////////////////////////////////////////// -// # TRANSFER MODE CONFIG -///////////////////////////////////////////////////////////////////////// -#[derive(Debug, PartialEq, Eq, Clone, Copy)] -pub enum TransferModeConf { - Direct, - Fifo(FifoConf), -} - -impl From for TransferMode { - fn from(conf: TransferModeConf) -> Self { - match conf { - TransferModeConf::Fifo(_) => Self::Fifo, - TransferModeConf::Direct => Self::Direct, + pub fn pincos(self) -> Option { + match self { + Self::P2M(conf) | Self::M2P(conf) => conf.pincos(), + Self::M2M(conf) => conf.pincos(), } } -} - -///////////////////////////////////////////////////////////////////////// -// # FLOW CONTROLLER CONFIG -///////////////////////////////////////////////////////////////////////// -#[derive(Debug, PartialEq, Eq, Clone, Copy)] -pub enum FlowControllerConf { - Dma(CircularModeConf), - Peripheral, -} - -impl From for FlowController { - fn from(conf: FlowControllerConf) -> Self { - match conf { - FlowControllerConf::Dma(_) => Self::Dma, - FlowControllerConf::Peripheral => Self::Peripheral, + pub fn fifo_threshold(self) -> Option { + match self { + Self::P2M(conf) | Self::M2P(conf) => conf.fifo_threshold(), + Self::M2M(conf) => Some(conf.fifo_threshold), } } -} - -///////////////////////////////////////////////////////////////////////// -// # FIFO CONFIG -///////////////////////////////////////////////////////////////////////// - -#[derive(Debug, PartialEq, Eq, Clone, Copy)] -pub struct FifoConf { - pub fifo_threshold: FifoThreshold, - pub p_burst: PBurstConf, - pub m_burst: MBurst, - pub m_size: MSize, -} - -///////////////////////////////////////////////////////////////////////// -// # PBURST CONFIG -///////////////////////////////////////////////////////////////////////// -#[derive(Debug, PartialEq, Eq, Clone, Copy)] -pub enum PBurstConf { - Single(Pincos), - Incr4, - Incr8, - Incr16, -} + pub fn p_burst(self) -> PBurst { + match self { + Self::P2M(conf) | Self::M2P(conf) => conf.p_burst(), + Self::M2M(conf) => conf.p_burst(), + } + } -impl From for PBurst { - fn from(conf: PBurstConf) -> Self { - match conf { - PBurstConf::Single(_) => Self::Single, - PBurstConf::Incr4 => Self::Incr4, - PBurstConf::Incr8 => Self::Incr8, - PBurstConf::Incr16 => Self::Incr16, + pub fn m_burst(self) -> MBurst { + match self { + Self::P2M(conf) | Self::M2P(conf) => conf.m_burst(), + Self::M2M(conf) => conf.m_burst, } } -} -///////////////////////////////////////////////////////////////////////// -// # CIRCULAR CONFIG -///////////////////////////////////////////////////////////////////////// + pub fn m_size(self, p_size: Option) -> MSize { + match self { + Self::P2M(conf) | Self::M2P(conf) => conf.m_size(p_size), + Self::M2M(conf) => conf.m_size, + } + } -#[derive(Debug, PartialEq, Eq, Clone, Copy)] -pub enum CircularModeConf { - Disabled, - Enabled(BufferModeConf), -} + pub fn circular_mode(self) -> CircularMode { + match self { + Self::P2M(conf) | Self::M2P(conf) => conf.circular_mode(), + Self::M2M(_) => CircularMode::Disabled, + } + } -impl From for CircularMode { - fn from(conf: CircularModeConf) -> Self { - match conf { - CircularModeConf::Disabled => Self::Disabled, - CircularModeConf::Enabled(_) => Self::Enabled, + pub fn buffer_mode(self) -> BufferMode { + match self { + Self::P2M(conf) | Self::M2P(conf) => conf.buffer_mode(), + Self::M2M(_) => CircularModeConf::Disabled.buffer_mode(), } } -} -///////////////////////////////////////////////////////////////////////// -// # BUFFER MODE CONFIG -///////////////////////////////////////////////////////////////////////// + pub fn current_target(self) -> CurrentTarget { + match self { + Self::P2M(conf) | Self::M2P(conf) => conf.current_target(), + Self::M2M(_) => CircularModeConf::Disabled.current_target(), + } + } -#[derive(Debug, PartialEq, Eq, Clone, Copy)] -pub enum BufferModeConf { - Regular, - DoubleBuffer(DoubleBufferConf), + pub fn m1a(self) -> Option { + match self { + Self::P2M(conf) | Self::M2P(conf) => conf.m1a(), + Self::M2M(_) => CircularModeConf::Disabled.m1a(), + } + } } -impl From for BufferMode { - fn from(conf: BufferModeConf) -> Self { +impl From for TransferDirection { + fn from(conf: TransferDirectionConf) -> TransferDirection { match conf { - BufferModeConf::Regular => Self::Regular, - BufferModeConf::DoubleBuffer(_) => Self::DoubleBuffer, + TransferDirectionConf::P2M(_) => TransferDirection::P2M, + TransferDirectionConf::M2P(_) => TransferDirection::M2P, + TransferDirectionConf::M2M(_) => TransferDirection::M2M, } } } ///////////////////////////////////////////////////////////////////////// -// # DOUBLE BUFFER CONFIG -///////////////////////////////////////////////////////////////////////// - -#[derive(Debug, PartialEq, Eq, Clone, Copy)] -pub struct DoubleBufferConf { - pub current_target: CurrentTarget, - pub m1a: M1a, -} - -///////////////////////////////////////////////////////////////////////// -// CONFIG BUILDER -///////////////////////////////////////////////////////////////////////// - -///////////////////////////////////////////////////////////////////////// -// # CONFIG BUILDER +// # NOT-M2M CONFIG ///////////////////////////////////////////////////////////////////////// #[derive(Debug, PartialEq, Eq, Clone, Copy)] -pub struct ConfigBuilder< - C_TransferDir, - C_TransferMode, - C_FlowController, - C_CircularMode, - C_BufferMode, - C_PBurst, -> where - C_TransferDir: MaybeNotConfigured, - C_TransferMode: MaybeNotConfigured, - C_FlowController: MaybeNotConfigured, - C_CircularMode: MaybeNotConfigured, - C_BufferMode: MaybeNotConfigured, - C_PBurst: MaybeNotConfigured, -{ - tc_intrpt: Option, - ht_intrpt: Option, - te_intrpt: Option, - dme_intrpt: Option, - fe_intrpt: Option, - pinc: Option, - minc: Option, - priority: Option, - p_size: Option, - ndt: Option, - pa: Option, - m0a: Option, - transfer_mode: C_TransferMode, - buffer_mode: C_BufferMode, - p_burst: C_PBurst, - _phantom: PhantomData<(C_TransferDir, C_FlowController, C_CircularMode)>, +pub struct NotM2MConf { + pub transfer_mode: TransferModeConf, + pub flow_controller: FlowControllerConf, } -///////////////////////////////////////////////////////////////////////// -// ## GENERIC IMPLEMENTATION -///////////////////////////////////////////////////////////////////////// - -impl - ConfigBuilder< - NotConfigured, - NotConfigured, - NotConfigured, - NotConfigured, - NotConfigured, - NotConfigured, - > -{ - pub fn new() -> Self { - Self { - tc_intrpt: None, - ht_intrpt: None, - te_intrpt: None, - dme_intrpt: None, - fe_intrpt: None, - pinc: None, - minc: None, - priority: None, - p_size: None, - ndt: None, - pa: None, - m0a: None, - transfer_mode: NotConfigured, - buffer_mode: NotConfigured, - p_burst: NotConfigured, - _phantom: PhantomData, - } +impl NotM2MConf { + pub fn transfer_mode(self) -> TransferMode { + self.transfer_mode.into() } -} - -impl< - C_TransferDir, - C_TransferMode, - C_FlowController, - C_CircularMode, - C_BufferMode, - C_PBurst, - > - ConfigBuilder< - C_TransferDir, - C_TransferMode, - C_FlowController, - C_CircularMode, - C_BufferMode, - C_PBurst, - > -where - C_TransferDir: MaybeNotConfigured, - C_TransferMode: MaybeNotConfigured, - C_FlowController: MaybeNotConfigured, - C_CircularMode: MaybeNotConfigured, - C_BufferMode: MaybeNotConfigured, - C_PBurst: MaybeNotConfigured, -{ - pub fn transfer_complete_interrupt( - mut self, - tc_intrpt: TransferCompleteInterrupt, - ) -> Self { - self.tc_intrpt = Some(tc_intrpt); - self + pub fn flow_controller(self) -> FlowController { + self.flow_controller.into() } - pub fn half_transfer_interrupt( - mut self, - ht_intrpt: HalfTransferInterrupt, - ) -> Self { - self.ht_intrpt = Some(ht_intrpt); - - self + pub fn pinc(self) -> Pinc { + self.transfer_mode.pinc() } - pub fn transfer_error_interrupt( - mut self, - te_intrpt: TransferErrorInterrupt, - ) -> Self { - self.te_intrpt = Some(te_intrpt); - - self + pub fn pincos(self) -> Option { + self.transfer_mode.pincos() } - pub fn direct_mode_error_interrupt( - mut self, - dme_intrpt: DirectModeErrorInterrupt, - ) -> Self { - self.dme_intrpt = Some(dme_intrpt); - - self + pub fn fifo_threshold(self) -> Option { + self.transfer_mode.fifo_threshold() } - pub fn fifo_error_interrupt( - mut self, - fe_intrpt: FifoErrorInterrupt, - ) -> Self { - self.fe_intrpt = Some(fe_intrpt); - - self + pub fn p_burst(self) -> PBurst { + self.transfer_mode.p_burst() } - pub fn pinc(mut self, pinc: Pinc) -> Self { - self.pinc = Some(pinc); - - self + pub fn m_burst(self) -> MBurst { + self.transfer_mode.m_burst() } - pub fn minc(mut self, minc: Minc) -> Self { - self.minc = Some(minc); - - self + pub fn m_size(self, p_size: Option) -> MSize { + self.transfer_mode.m_size(p_size) } - pub fn priority_level(mut self, priority: PriorityLevel) -> Self { - self.priority = Some(priority); - - self + pub fn circular_mode(self) -> CircularMode { + self.flow_controller.circular_mode() } - pub fn p_size(mut self, p_size: PSize) -> Self { - self.p_size = Some(p_size); - - self + pub fn buffer_mode(self) -> BufferMode { + self.flow_controller.buffer_mode() } - pub fn ndt(mut self, ndt: Ndt) -> Self { - self.ndt = Some(ndt); + pub fn current_target(self) -> CurrentTarget { + self.flow_controller.current_target() + } - self + pub fn m1a(self) -> Option { + self.flow_controller.m1a() } +} + +///////////////////////////////////////////////////////////////////////// +// # TRANSFER MODE CONFIG +///////////////////////////////////////////////////////////////////////// - pub fn pa(mut self, pa: Pa) -> Self { - self.pa = Some(pa); +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +pub enum TransferModeConf { + Direct(DirectConf), + Fifo(FifoConf), +} - self +impl TransferModeConf { + pub fn pinc(self) -> Pinc { + match self { + Self::Fifo(conf) => conf.pinc(), + Self::Direct(conf) => conf.pinc, + } } - pub fn m0a(mut self, m0a: M0a) -> Self { - self.m0a = Some(m0a); - - self + pub fn pincos(self) -> Option { + match self { + TransferModeConf::Fifo(conf) => conf.pincos(), + TransferModeConf::Direct(conf) => match conf.pinc { + Pinc::Fixed => PincConf::Fixed.pincos(), + Pinc::Incremented => Some(Pincos::PSize), + }, + } } - fn transmute( - self, - ) -> ConfigBuilder< - NewC_TransferDir, - C_TransferMode, - NewC_FlowController, - NewC_CircularMode, - C_BufferMode, - C_PBurst, - > - where - NewC_TransferDir: MaybeNotConfigured, - NewC_FlowController: MaybeNotConfigured, - NewC_CircularMode: MaybeNotConfigured, - { - ConfigBuilder { - tc_intrpt: self.tc_intrpt, - ht_intrpt: self.ht_intrpt, - te_intrpt: self.te_intrpt, - dme_intrpt: self.dme_intrpt, - fe_intrpt: self.fe_intrpt, - pinc: self.pinc, - minc: self.minc, - priority: self.priority, - p_size: self.p_size, - ndt: self.ndt, - pa: self.pa, - m0a: self.m0a, - transfer_mode: self.transfer_mode, - buffer_mode: self.buffer_mode, - p_burst: self.p_burst, - _phantom: PhantomData, + pub fn fifo_threshold(self) -> Option { + match self { + Self::Direct(_) => None, + Self::Fifo(conf) => Some(conf.fifo_threshold), } } - fn transmute_transfer_mode( - self, - transfer_mode: NewC_TransferMode, - ) -> ConfigBuilder< - C_TransferDir, - NewC_TransferMode, - C_FlowController, - C_CircularMode, - C_BufferMode, - C_PBurst, - > - where - NewC_TransferMode: MaybeNotConfigured, - { - ConfigBuilder { - tc_intrpt: self.tc_intrpt, - ht_intrpt: self.ht_intrpt, - te_intrpt: self.te_intrpt, - dme_intrpt: self.dme_intrpt, - fe_intrpt: self.fe_intrpt, - pinc: self.pinc, - minc: self.minc, - priority: self.priority, - p_size: self.p_size, - ndt: self.ndt, - pa: self.pa, - m0a: self.m0a, - buffer_mode: self.buffer_mode, - p_burst: self.p_burst, - _phantom: PhantomData, - transfer_mode, + pub fn p_burst(self) -> PBurst { + match self { + Self::Direct(_) => PBurst::Single, + Self::Fifo(conf) => conf.p_burst(), } } - fn transmute_buffer_mode( - self, - buffer_mode: NewC_BufferMode, - ) -> ConfigBuilder< - C_TransferDir, - C_TransferMode, - C_FlowController, - C_CircularMode, - NewC_BufferMode, - C_PBurst, - > - where - NewC_BufferMode: MaybeNotConfigured, - { - ConfigBuilder { - tc_intrpt: self.tc_intrpt, - ht_intrpt: self.ht_intrpt, - te_intrpt: self.te_intrpt, - dme_intrpt: self.dme_intrpt, - fe_intrpt: self.fe_intrpt, - pinc: self.pinc, - minc: self.minc, - priority: self.priority, - p_size: self.p_size, - ndt: self.ndt, - pa: self.pa, - m0a: self.m0a, - transfer_mode: self.transfer_mode, - p_burst: self.p_burst, - _phantom: PhantomData, - buffer_mode, + pub fn m_burst(self) -> MBurst { + match self { + Self::Direct(_) => MBurst::Single, + Self::Fifo(conf) => conf.m_burst, } } - fn transmute_p_burst( - self, - p_burst: NewC_PBurst, - ) -> ConfigBuilder< - C_TransferDir, - C_TransferMode, - C_FlowController, - C_CircularMode, - C_BufferMode, - NewC_PBurst, - > - where - NewC_PBurst: MaybeNotConfigured, - { - ConfigBuilder { - tc_intrpt: self.tc_intrpt, - ht_intrpt: self.ht_intrpt, - te_intrpt: self.te_intrpt, - dme_intrpt: self.dme_intrpt, - fe_intrpt: self.fe_intrpt, - pinc: self.pinc, - minc: self.minc, - priority: self.priority, - p_size: self.p_size, - ndt: self.ndt, - pa: self.pa, - m0a: self.m0a, - transfer_mode: self.transfer_mode, - buffer_mode: self.buffer_mode, - _phantom: PhantomData, - p_burst, + pub fn m_size(self, p_size: Option) -> MSize { + match self { + Self::Direct(_) => match p_size.unwrap() { + PSize::Byte => MSize::Byte, + PSize::HalfWord => MSize::HalfWord, + PSize::Word => MSize::Word, + }, + Self::Fifo(conf) => conf.m_size, } } } -impl< - C_TransferMode, - C_FlowController, - C_CircularMode, - C_BufferMode, - C_PBurst, - > - ConfigBuilder< - NotConfigured, - C_TransferMode, - C_FlowController, - C_CircularMode, - C_BufferMode, - C_PBurst, - > -where - C_TransferMode: MaybeNotConfigured, - C_FlowController: MaybeNotConfigured, - C_CircularMode: MaybeNotConfigured, - C_BufferMode: MaybeNotConfigured, - C_PBurst: MaybeNotConfigured, -{ - pub fn transfer_dir_p2m( - self, - ) -> ConfigBuilder< - P2M, - C_TransferMode, - C_FlowController, - C_CircularMode, - C_BufferMode, - C_PBurst, - > { - self.transmute() - } - - pub fn transfer_dir_m2p( - self, - ) -> ConfigBuilder< - M2P, - C_TransferMode, - C_FlowController, - C_CircularMode, - C_BufferMode, - C_PBurst, - > { - self.transmute() - } - - pub fn transfer_dir_m2m( - self, - ) -> ConfigBuilder - { - self.transmute() - .transmute_transfer_mode(Fifo::default()) - .transmute_buffer_mode(RegularBuffer) - } -} - -impl< - C_TransferDir, - C_FlowController, - C_CircularMode, - C_BufferMode, - C_PBurst, - > - ConfigBuilder< - C_TransferDir, - NotConfigured, - C_FlowController, - C_CircularMode, - C_BufferMode, - C_PBurst, - > -where - C_TransferDir: ITransferDirection, - C_FlowController: MaybeNotConfigured, - C_CircularMode: MaybeNotConfigured, - C_BufferMode: MaybeNotConfigured, - C_PBurst: MaybeNotConfigured, -{ - pub fn transfer_mode_fifo( - self, - ) -> ConfigBuilder< - C_TransferDir, - Fifo, - C_FlowController, - C_CircularMode, - C_BufferMode, - C_PBurst, - > { - self.transmute_transfer_mode(Fifo::default()) - } -} - -impl - ConfigBuilder< - C_NotM2M, - NotConfigured, - C_FlowController, - C_CircularMode, - C_BufferMode, - C_PBurst, - > -where - C_NotM2M: NotM2M, - C_FlowController: MaybeNotConfigured, - C_CircularMode: MaybeNotConfigured, - C_BufferMode: MaybeNotConfigured, - C_PBurst: MaybeNotConfigured, -{ - pub fn transfer_mode_direct( - self, - ) -> ConfigBuilder< - C_NotM2M, - Direct, - C_FlowController, - C_CircularMode, - C_BufferMode, - Single, - > { - self.transmute_transfer_mode(Direct) - .transmute_p_burst(Single::default()) - } -} - -impl - ConfigBuilder< - C_TransferDir, - C_TransferMode, - NotConfigured, - C_CircularMode, - C_BufferMode, - C_PBurst, - > -where - C_TransferDir: ITransferDirection, - C_TransferMode: MaybeNotConfigured, - C_CircularMode: MaybeNotConfigured, - C_BufferMode: MaybeNotConfigured, - C_PBurst: MaybeNotConfigured, -{ - pub fn flow_controller_dma( - self, - ) -> ConfigBuilder< - C_TransferDir, - C_TransferMode, - Dma, - C_CircularMode, - C_BufferMode, - C_PBurst, - > { - self.transmute() - } -} - -impl - ConfigBuilder< - C_NotM2M, - C_TransferMode, - NotConfigured, - C_CircularMode, - C_BufferMode, - C_PBurst, - > -where - C_NotM2M: NotM2M, - C_TransferMode: MaybeNotConfigured, - C_CircularMode: MaybeNotConfigured, - C_BufferMode: MaybeNotConfigured, - C_PBurst: MaybeNotConfigured, -{ - pub fn flow_controller_peripheral( - self, - ) -> ConfigBuilder< - C_NotM2M, - C_TransferMode, - Peripheral, - NotCircular, - RegularBuffer, - C_PBurst, - > { - self.transmute().transmute_buffer_mode(RegularBuffer) - } -} - -impl< - C_TransferDir, - C_TransferMode, - C_FlowController, - C_BufferMode, - C_PBurst, - > - ConfigBuilder< - C_TransferDir, - C_TransferMode, - C_FlowController, - NotConfigured, - C_BufferMode, - C_PBurst, - > -where - C_TransferDir: MaybeNotConfigured, - C_TransferMode: MaybeNotConfigured, - C_FlowController: IFlowController, - C_BufferMode: MaybeNotConfigured, - C_PBurst: MaybeNotConfigured, -{ - pub fn circular_mode_disabled( - self, - ) -> ConfigBuilder< - C_TransferDir, - C_TransferMode, - C_FlowController, - NotCircular, - C_BufferMode, - C_PBurst, - > { - self.transmute() - } -} - -impl - ConfigBuilder< - C_NotM2M, - C_TransferMode, - Dma, - NotConfigured, - C_BufferMode, - C_PBurst, - > -where - C_NotM2M: NotM2M, - C_TransferMode: MaybeNotConfigured, - C_BufferMode: MaybeNotConfigured, - C_PBurst: MaybeNotConfigured, -{ - pub fn circular_mode_enabled( - self, - ) -> ConfigBuilder< - C_NotM2M, - C_TransferMode, - Dma, - Circular, - C_BufferMode, - C_PBurst, - > { - self.transmute() - } -} - -impl< - C_TransferDir, - C_TransferMode, - C_FlowController, - C_CircularMode, - C_PBurst, - > - ConfigBuilder< - C_TransferDir, - C_TransferMode, - C_FlowController, - C_CircularMode, - NotConfigured, - C_PBurst, - > -where - C_TransferDir: MaybeNotConfigured, - C_TransferMode: MaybeNotConfigured, - C_FlowController: MaybeNotConfigured, - C_CircularMode: ICircularMode, - C_PBurst: MaybeNotConfigured, -{ - pub fn buffer_mode_regular( - self, - ) -> ConfigBuilder< - C_TransferDir, - C_TransferMode, - C_FlowController, - C_CircularMode, - RegularBuffer, - C_PBurst, - > { - self.transmute_buffer_mode(RegularBuffer) - } -} - -impl - ConfigBuilder< - C_TransferDir, - C_TransferMode, - C_FlowController, - Circular, - NotConfigured, - C_PBurst, - > -where - C_TransferDir: MaybeNotConfigured, - C_TransferMode: MaybeNotConfigured, - C_FlowController: MaybeNotConfigured, - C_PBurst: MaybeNotConfigured, -{ - pub fn buffer_mode_double_buffer( - self, - ) -> ConfigBuilder< - C_TransferDir, - C_TransferMode, - C_FlowController, - Circular, - DoubleBuffer, - C_PBurst, - > { - self.transmute_buffer_mode(DoubleBuffer::default()) - } -} - -impl< - C_TransferDir, - C_TransferMode, - C_FlowController, - C_CircularMode, - C_BufferMode, - > - ConfigBuilder< - C_TransferDir, - C_TransferMode, - C_FlowController, - C_CircularMode, - C_BufferMode, - NotConfigured, - > -where - C_TransferDir: MaybeNotConfigured, - C_TransferMode: ITransferMode, - C_FlowController: MaybeNotConfigured, - C_CircularMode: MaybeNotConfigured, - C_BufferMode: MaybeNotConfigured, -{ +impl From for TransferMode { + fn from(conf: TransferModeConf) -> Self { + match conf { + TransferModeConf::Fifo(_) => Self::Fifo, + TransferModeConf::Direct(_) => Self::Direct, + } + } } -impl - ConfigBuilder< - C_TransferDir, - Fifo, - C_FlowController, - C_CircularMode, - C_BufferMode, - NotConfigured, - > -where - C_TransferDir: MaybeNotConfigured, - C_FlowController: MaybeNotConfigured, - C_CircularMode: MaybeNotConfigured, - C_BufferMode: MaybeNotConfigured, -{ - pub fn p_burst_single( - self, - ) -> ConfigBuilder< - C_TransferDir, - Fifo, - C_FlowController, - C_CircularMode, - C_BufferMode, - Single, - > { - self.transmute_p_burst(Single::default()) - } - - pub fn p_burst_incr4( - self, - ) -> ConfigBuilder< - C_TransferDir, - Fifo, - C_FlowController, - C_CircularMode, - C_BufferMode, - Incr4, - > { - self.transmute_p_burst(Incr4) - } - - pub fn p_burst_incr8( - self, - ) -> ConfigBuilder< - C_TransferDir, - Fifo, - C_FlowController, - C_CircularMode, - C_BufferMode, - Incr8, - > { - self.transmute_p_burst(Incr8) - } - - pub fn p_burst_incr16( - self, - ) -> ConfigBuilder< - C_TransferDir, - Fifo, - C_FlowController, - C_CircularMode, - C_BufferMode, - Incr16, - > { - self.transmute_p_burst(Incr16) - } -} - -impl Default - for ConfigBuilder< - NotConfigured, - NotConfigured, - NotConfigured, - NotConfigured, - NotConfigured, - NotConfigured, - > -{ - fn default() -> Self { - Self::new() - } -} - -impl< - C_TransferDir, - C_FlowController, - C_CircularMode, - C_BufferMode, - C_PBurst, - > - ConfigBuilder< - C_TransferDir, - Fifo, - C_FlowController, - C_CircularMode, - C_BufferMode, - C_PBurst, - > -where - C_TransferDir: MaybeNotConfigured, - C_FlowController: MaybeNotConfigured, - C_CircularMode: MaybeNotConfigured, - C_BufferMode: MaybeNotConfigured, - C_PBurst: MaybeNotConfigured, -{ - pub fn fifo_threshold(mut self, fifo_threshold: FifoThreshold) -> Self { - self.transfer_mode.fifo_threshold = Some(fifo_threshold); - - self - } +///////////////////////////////////////////////////////////////////////// +// # FLOW CONTROLLER CONFIG +///////////////////////////////////////////////////////////////////////// - pub fn m_burst(mut self, m_burst: MBurst) -> Self { - self.transfer_mode.m_burst = Some(m_burst); +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +pub enum FlowControllerConf { + Dma(CircularModeConf), + Peripheral, +} - self +impl FlowControllerConf { + pub fn circular_mode(self) -> CircularMode { + match self { + Self::Dma(circ) => circ.into(), + Self::Peripheral => CircularMode::Disabled, + } } - pub fn m_size(mut self, m_size: MSize) -> Self { - self.transfer_mode.m_size = Some(m_size); - - self + pub fn buffer_mode(self) -> BufferMode { + match self { + Self::Dma(circ) => circ.buffer_mode(), + Self::Peripheral => CircularModeConf::Disabled.buffer_mode(), + } } -} - -impl< - C_TransferDir, - C_TransferMode, - C_FlowController, - C_CircularMode, - C_PBurst, - > - ConfigBuilder< - C_TransferDir, - C_TransferMode, - C_FlowController, - C_CircularMode, - DoubleBuffer, - C_PBurst, - > -where - C_TransferDir: MaybeNotConfigured, - C_TransferMode: MaybeNotConfigured, - C_FlowController: MaybeNotConfigured, - C_CircularMode: MaybeNotConfigured, - C_PBurst: MaybeNotConfigured, -{ - pub fn current_target(mut self, current_target: CurrentTarget) -> Self { - self.buffer_mode.current_target = Some(current_target); - self + pub fn current_target(self) -> CurrentTarget { + match self { + Self::Dma(circ) => circ.current_target(), + Self::Peripheral => CircularModeConf::Disabled.current_target(), + } } - pub fn m1a(mut self, m1a: M1a) -> Self { - self.buffer_mode.m1a = Some(m1a); - - self + pub fn m1a(self) -> Option { + match self { + Self::Dma(circ) => circ.m1a(), + Self::Peripheral => CircularModeConf::Disabled.m1a(), + } } } -impl< - C_TransferDir, - C_TransferMode, - C_FlowController, - C_CircularMode, - C_BufferMode, - > - ConfigBuilder< - C_TransferDir, - C_TransferMode, - C_FlowController, - C_CircularMode, - C_BufferMode, - Single, - > -where - C_TransferDir: MaybeNotConfigured, - C_TransferMode: MaybeNotConfigured, - C_FlowController: MaybeNotConfigured, - C_CircularMode: MaybeNotConfigured, - C_BufferMode: MaybeNotConfigured, -{ - pub fn pincos(mut self, pincos: Pincos) -> Self { - self.p_burst.pincos = Some(pincos); - - self - } -} - -impl< - C_TransferDir, - C_TransferMode, - C_FlowController, - C_CircularMode, - C_BufferMode, - C_PBurst, - > - ConfigBuilder< - C_TransferDir, - C_TransferMode, - C_FlowController, - C_CircularMode, - C_BufferMode, - C_PBurst, - > -where - C_TransferDir: ITransferDirection, - C_TransferMode: ITransferMode, - C_FlowController: IFlowController, - C_CircularMode: ICircularMode, - C_BufferMode: IBufferMode, - C_PBurst: IPBurst, -{ - pub fn build(self) -> Config { - let transfer_direction_conf = - C_TransferDir::build::<_, C_FlowController, C_CircularMode, _, _>( - self.transfer_mode, - self.buffer_mode, - self.p_burst, - ); - - Config { - transfer_complete_interrupt: self.tc_intrpt.unwrap(), - half_transfer_interrupt: self.ht_intrpt.unwrap(), - transfer_error_interrupt: self.te_intrpt.unwrap(), - direct_mode_error_interrupt: self.dme_intrpt.unwrap(), - fifo_error_interrupt: self.fe_intrpt.unwrap(), - pinc: self.pinc.unwrap(), - minc: self.minc.unwrap(), - priority_level: self.priority.unwrap(), - p_size: self.p_size.unwrap(), - ndt: self.ndt.unwrap(), - pa: self.pa.unwrap(), - m0a: self.m0a.unwrap(), - transfer_direction: transfer_direction_conf, +impl From for FlowController { + fn from(conf: FlowControllerConf) -> Self { + match conf { + FlowControllerConf::Dma(_) => Self::Dma, + FlowControllerConf::Peripheral => Self::Peripheral, } } } ///////////////////////////////////////////////////////////////////////// -// # TRANSFER DIRECTION +// # PINC CONFIG ///////////////////////////////////////////////////////////////////////// -pub trait ITransferDirection: DefaultTraits + private::Sealed { - const TRANSFER_DIRECTION: TransferDirection; - - #[doc(hidden)] - fn build< - C_TransferMode, - C_FlowController, - C_CircularMode, - C_BufferMode, - C_PBurst, - >( - transfer_mode: C_TransferMode, - buffer_mode: C_BufferMode, - p_burst: C_PBurst, - ) -> TransferDirectionConf - where - C_TransferMode: ITransferMode, - C_FlowController: IFlowController, - C_CircularMode: ICircularMode, - C_BufferMode: IBufferMode, - C_PBurst: IPBurst; -} - -#[derive(Debug, PartialEq, Eq, Clone, Copy)] -pub struct P2M; -#[derive(Debug, PartialEq, Eq, Clone, Copy)] -pub struct M2P; -#[derive(Debug, PartialEq, Eq, Clone, Copy)] -pub struct M2M; - -impl private::Sealed for P2M {} -impl private::Sealed for M2P {} -impl private::Sealed for M2M {} - -impl ITransferDirection for P2M { - const TRANSFER_DIRECTION: TransferDirection = TransferDirection::P2M; - - #[doc(hidden)] - fn build< - C_TransferMode, - C_FlowController, - C_CircularMode, - C_BufferMode, - C_PBurst, - >( - transfer_mode: C_TransferMode, - buffer_mode: C_BufferMode, - p_burst: C_PBurst, - ) -> TransferDirectionConf - where - C_TransferMode: ITransferMode, - C_FlowController: IFlowController, - C_CircularMode: ICircularMode, - C_BufferMode: IBufferMode, - C_PBurst: IPBurst, - { - TransferDirectionConf::NotM2M(NotM2MConf { - transfer_dir: TransferDirectionNotM2M::P2M, - transfer_mode: transfer_mode.build(p_burst), - flow: C_FlowController::build::(buffer_mode), - }) - } -} - -impl ITransferDirection for M2P { - const TRANSFER_DIRECTION: TransferDirection = TransferDirection::M2P; - - #[doc(hidden)] - fn build< - C_TransferMode, - C_FlowController, - C_CircularMode, - C_BufferMode, - C_PBurst, - >( - transfer_mode: C_TransferMode, - buffer_mode: C_BufferMode, - p_burst: C_PBurst, - ) -> TransferDirectionConf - where - C_TransferMode: ITransferMode, - C_FlowController: IFlowController, - C_CircularMode: ICircularMode, - C_BufferMode: IBufferMode, - C_PBurst: IPBurst, - { - TransferDirectionConf::NotM2M(NotM2MConf { - transfer_dir: TransferDirectionNotM2M::M2P, - transfer_mode: transfer_mode.build(p_burst), - flow: C_FlowController::build::(buffer_mode), - }) - } -} - -impl ITransferDirection for M2M { - const TRANSFER_DIRECTION: TransferDirection = TransferDirection::M2M; - - #[doc(hidden)] - fn build< - C_TransferMode, - C_FlowController, - C_CircularMode, - C_BufferMode, - C_PBurst, - >( - transfer_mode: C_TransferMode, - _: C_BufferMode, - p_burst: C_PBurst, - ) -> TransferDirectionConf - where - C_TransferMode: ITransferMode, - C_FlowController: IFlowController, - C_CircularMode: ICircularMode, - C_BufferMode: IBufferMode, - C_PBurst: IPBurst, - { - TransferDirectionConf::M2M(match transfer_mode.build(p_burst) { - TransferModeConf::Fifo(fifo_conf) => fifo_conf, - _ => unreachable!(), - }) - } -} - -pub trait NotM2M: ITransferDirection {} - -impl NotM2M for P2M {} -impl NotM2M for M2P {} - -///////////////////////////////////////////////////////////////////////// -// # TRANSFER MODE -///////////////////////////////////////////////////////////////////////// - -pub trait ITransferMode: DefaultTraits + private::Sealed { - const TRANSFER_MODE: TransferMode; - - #[doc(hidden)] - fn build(self, p_burst: C_PBurst) -> TransferModeConf - where - C_PBurst: IPBurst; -} - -#[derive(Debug, PartialEq, Eq, Clone, Copy)] -pub struct Direct; - -#[derive(Default, Debug, PartialEq, Eq, Clone, Copy)] -pub struct Fifo { - fifo_threshold: Option, - m_burst: Option, - m_size: Option, +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +pub enum PincConf { + Fixed, + Incremented(Pincos), } -impl private::Sealed for Direct {} -impl private::Sealed for Fifo {} - -impl ITransferMode for Direct { - const TRANSFER_MODE: TransferMode = TransferMode::Direct; - - #[doc(hidden)] - fn build(self, _: C_PBurst) -> TransferModeConf - where - C_PBurst: IPBurst, - { - TransferModeConf::Direct +impl PincConf { + pub fn pincos(self) -> Option { + match self { + Self::Fixed => None, + Self::Incremented(pincos) => Some(pincos), + } } } -impl ITransferMode for Fifo { - const TRANSFER_MODE: TransferMode = TransferMode::Fifo; - - fn build(self, p_burst: C_PBurst) -> TransferModeConf - where - C_PBurst: IPBurst, - { - let conf = FifoConf { - fifo_threshold: self.fifo_threshold.unwrap(), - p_burst: p_burst.build(), - m_burst: self.m_burst.unwrap(), - m_size: self.m_size.unwrap(), - }; - TransferModeConf::Fifo(conf) +impl From for Pinc { + fn from(x: PincConf) -> Self { + match x { + PincConf::Fixed => Self::Fixed, + PincConf::Incremented(_) => Self::Incremented, + } } } ///////////////////////////////////////////////////////////////////////// -// # FLOW CONTROLLER +// # DIRECT CONFIG ///////////////////////////////////////////////////////////////////////// -pub trait IFlowController: DefaultTraits + private::Sealed { - const FLOW_CONTROLLER: FlowController; - - #[doc(hidden)] - fn build( - buffer_mode: C_BufferMode, - ) -> FlowControllerConf - where - C_CircularMode: ICircularMode, - C_BufferMode: IBufferMode; +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +pub struct DirectConf { + pub pinc: Pinc, } -#[derive(Debug, PartialEq, Eq, Clone, Copy)] -pub struct Dma; -#[derive(Debug, PartialEq, Eq, Clone, Copy)] -pub struct Peripheral; +///////////////////////////////////////////////////////////////////////// +// # FIFO CONFIG +///////////////////////////////////////////////////////////////////////// -impl private::Sealed for Dma {} -impl private::Sealed for Peripheral {} +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +pub struct FifoConf { + pub fifo_threshold: FifoThreshold, + pub p_burst: PBurstConf, + pub m_burst: MBurst, + pub m_size: MSize, +} -impl IFlowController for Dma { - const FLOW_CONTROLLER: FlowController = FlowController::Dma; +impl FifoConf { + pub fn pinc(self) -> Pinc { + self.p_burst.pinc() + } - #[doc(hidden)] - fn build( - buffer_mode: C_BufferMode, - ) -> FlowControllerConf - where - C_CircularMode: ICircularMode, - C_BufferMode: IBufferMode, - { - FlowControllerConf::Dma(C_CircularMode::build(buffer_mode)) + pub fn pincos(self) -> Option { + self.p_burst.pincos() } -} -impl IFlowController for Peripheral { - const FLOW_CONTROLLER: FlowController = FlowController::Peripheral; - fn build( - _: C_BufferMode, - ) -> FlowControllerConf - where - C_CircularMode: ICircularMode, - C_BufferMode: IBufferMode, - { - FlowControllerConf::Peripheral + pub fn p_burst(self) -> PBurst { + self.p_burst.into() } } ///////////////////////////////////////////////////////////////////////// -// # CIRCULAR MODE +// # PBURST CONFIG ///////////////////////////////////////////////////////////////////////// -pub trait ICircularMode: DefaultTraits + private::Sealed { - const CIRCULAR_MODE: CircularMode; - - #[doc(hidden)] - fn build(buffer_mode: C_BufferMode) -> CircularModeConf - where - C_BufferMode: IBufferMode; -} - -#[derive(Debug, PartialEq, Eq, Clone, Copy)] -pub struct Circular; #[derive(Debug, PartialEq, Eq, Clone, Copy)] -pub struct NotCircular; - -impl private::Sealed for Circular {} -impl private::Sealed for NotCircular {} +pub enum PBurstConf { + Single(PincConf), + Incr4(Pinc), + Incr8(Pinc), + Incr16(Pinc), +} -impl ICircularMode for Circular { - const CIRCULAR_MODE: CircularMode = CircularMode::Enabled; +impl PBurstConf { + pub fn pinc(self) -> Pinc { + match self { + Self::Single(pinc_conf) => pinc_conf.into(), + Self::Incr4(pinc) | Self::Incr8(pinc) | Self::Incr16(pinc) => pinc, + } + } - #[doc(hidden)] - fn build(buffer_mode: C_BufferMode) -> CircularModeConf - where - C_BufferMode: IBufferMode, - { - CircularModeConf::Enabled(buffer_mode.build()) + pub fn pincos(self) -> Option { + match self { + Self::Single(pinc_conf) => pinc_conf.pincos(), + Self::Incr4(pinc) | Self::Incr8(pinc) | Self::Incr16(pinc) => { + match pinc { + Pinc::Fixed => PincConf::Fixed.pincos(), + Pinc::Incremented => Some(Pincos::PSize), + } + } + } } } -impl ICircularMode for NotCircular { - const CIRCULAR_MODE: CircularMode = CircularMode::Disabled; - fn build(_: C_BufferMode) -> CircularModeConf - where - C_BufferMode: IBufferMode, - { - CircularModeConf::Disabled +impl From for PBurst { + fn from(conf: PBurstConf) -> Self { + match conf { + PBurstConf::Single(_) => Self::Single, + PBurstConf::Incr4(_) => Self::Incr4, + PBurstConf::Incr8(_) => Self::Incr8, + PBurstConf::Incr16(_) => Self::Incr16, + } } } ///////////////////////////////////////////////////////////////////////// -// # BUFFER MODE +// # CIRCULAR CONFIG ///////////////////////////////////////////////////////////////////////// -pub trait IBufferMode: DefaultTraits + private::Sealed { - const BUFFER_MODE: BufferMode; - - #[doc(hidden)] - fn build(self) -> BufferModeConf; -} - #[derive(Debug, PartialEq, Eq, Clone, Copy)] -pub struct RegularBuffer; -#[derive(Default, Debug, PartialEq, Eq, Clone, Copy)] -pub struct DoubleBuffer { - current_target: Option, - m1a: Option, +pub enum CircularModeConf { + Disabled, + Enabled(BufferModeConf), } -impl private::Sealed for RegularBuffer {} -impl private::Sealed for DoubleBuffer {} +impl CircularModeConf { + pub fn buffer_mode(self) -> BufferMode { + match self { + Self::Disabled => BufferMode::Regular, + Self::Enabled(conf) => conf.into(), + } + } -impl IBufferMode for RegularBuffer { - const BUFFER_MODE: BufferMode = BufferMode::Regular; + pub fn current_target(self) -> CurrentTarget { + match self { + Self::Disabled => BufferModeConf::Regular.current_target(), + Self::Enabled(conf) => conf.current_target(), + } + } - #[doc(hidden)] - fn build(self) -> BufferModeConf { - BufferModeConf::Regular + pub fn m1a(self) -> Option { + match self { + Self::Disabled => BufferModeConf::Regular.m1a(), + Self::Enabled(conf) => conf.m1a(), + } } } -impl IBufferMode for DoubleBuffer { - const BUFFER_MODE: BufferMode = BufferMode::DoubleBuffer; - #[doc(hidden)] - fn build(self) -> BufferModeConf { - let conf = DoubleBufferConf { - current_target: self.current_target.unwrap(), - m1a: self.m1a.unwrap(), - }; - - BufferModeConf::DoubleBuffer(conf) +impl From for CircularMode { + fn from(conf: CircularModeConf) -> Self { + match conf { + CircularModeConf::Disabled => Self::Disabled, + CircularModeConf::Enabled(_) => Self::Enabled, + } } } ///////////////////////////////////////////////////////////////////////// -// # PBURST +// # BUFFER MODE CONFIG ///////////////////////////////////////////////////////////////////////// -pub trait IPBurst: DefaultTraits + private::Sealed { - const P_BURST: PBurst; - - #[doc(hidden)] - fn build(self) -> PBurstConf; -} - -#[derive(Default, Debug, PartialEq, Eq, Clone, Copy)] -pub struct Single { - pincos: Option, -} -#[derive(Debug, PartialEq, Eq, Clone, Copy)] -pub struct Incr4; #[derive(Debug, PartialEq, Eq, Clone, Copy)] -pub struct Incr8; -#[derive(Debug, PartialEq, Eq, Clone, Copy)] -pub struct Incr16; - -impl private::Sealed for Single {} -impl private::Sealed for Incr4 {} -impl private::Sealed for Incr8 {} -impl private::Sealed for Incr16 {} - -impl IPBurst for Single { - const P_BURST: PBurst = PBurst::Single; - - #[doc(hidden)] - fn build(self) -> PBurstConf { - PBurstConf::Single(self.pincos.unwrap()) - } +pub enum BufferModeConf { + Regular, + DoubleBuffer(DoubleBufferConf), } -impl IPBurst for Incr4 { - const P_BURST: PBurst = PBurst::Incr4; - - #[doc(hidden)] - fn build(self) -> PBurstConf { - PBurstConf::Incr4 +impl BufferModeConf { + pub fn current_target(self) -> CurrentTarget { + match self { + Self::Regular => CurrentTarget::M0a, + Self::DoubleBuffer(conf) => conf.current_target, + } } -} -impl IPBurst for Incr8 { - const P_BURST: PBurst = PBurst::Incr8; - - #[doc(hidden)] - fn build(self) -> PBurstConf { - PBurstConf::Incr8 + pub fn m1a(self) -> Option { + match self { + Self::Regular => None, + Self::DoubleBuffer(conf) => Some(conf.m1a), + } } } -impl IPBurst for Incr16 { - const P_BURST: PBurst = PBurst::Incr16; - - #[doc(hidden)] - fn build(self) -> PBurstConf { - PBurstConf::Incr16 +impl From for BufferMode { + fn from(conf: BufferModeConf) -> Self { + match conf { + BufferModeConf::Regular => Self::Regular, + BufferModeConf::DoubleBuffer(_) => Self::DoubleBuffer, + } } } ///////////////////////////////////////////////////////////////////////// -// # NOT CONFIGURED +// # DOUBLE BUFFER CONFIG ///////////////////////////////////////////////////////////////////////// #[derive(Debug, PartialEq, Eq, Clone, Copy)] -pub struct NotConfigured; - -impl private::Sealed for NotConfigured {} - -pub trait MaybeNotConfigured: DefaultTraits + private::Sealed {} - -pub struct S_TransferDir; -pub struct S_TransferMode; -pub struct S_FlowController; -pub struct S_CircularMode; -pub struct S_BufferMode; -pub struct S_PBurst; - -impl MaybeNotConfigured for NotConfigured {} -impl MaybeNotConfigured for NotConfigured {} -impl MaybeNotConfigured for NotConfigured {} -impl MaybeNotConfigured for NotConfigured {} -impl MaybeNotConfigured for NotConfigured {} -impl MaybeNotConfigured for NotConfigured {} - -impl MaybeNotConfigured for T where T: ITransferDirection {} -impl MaybeNotConfigured for T where T: ITransferMode {} -impl MaybeNotConfigured for T where T: IFlowController {} -impl MaybeNotConfigured for T where T: ICircularMode {} -impl MaybeNotConfigured for T where T: IBufferMode {} -impl MaybeNotConfigured for T where T: IPBurst {} +pub struct DoubleBufferConf { + pub current_target: CurrentTarget, + pub m1a: M1a, +} diff --git a/src/dma/safe_transfer.rs b/src/dma/transfer.rs similarity index 50% rename from src/dma/safe_transfer.rs rename to src/dma/transfer.rs index b2b06b35..3d189f1f 100644 --- a/src/dma/safe_transfer.rs +++ b/src/dma/transfer.rs @@ -1,13 +1,15 @@ //! Safe DMA Transfers use super::stream::{ - BufferModeConf, CircularModeConf, Enabled, FlowControllerConf, - IsrUncleared, M0a, M1a, MSize, NotM2MConf, PSize, Pa, TransferDirection, + BufferModeConf, CircularModeConf, Config as StreamConfig, CurrentTarget, + DirectConf, DoubleBufferConf, Enabled, FifoConf, FifoThreshold, + FlowControllerConf, IsrUncleared, M0a, M1a, MBurst, MSize, Minc, Ndt, + NotM2MConf, PBurstConf, PSize, Pa, Pinc, PincConf, Pincos, TransferDirectionConf, TransferModeConf, }; use super::{ChannelId, Stream}; use crate::private; -use core::convert::TryInto; +use core::convert::TryFrom; use core::fmt::Debug; use core::{mem, ptr}; use enum_as_inner::EnumAsInner; @@ -16,10 +18,17 @@ pub trait TransferState<'wo>: Send + Sync + private::Sealed { type Peripheral: Payload; type Memory: Payload; - fn buffers(&self) -> &Buffers<'wo, Self::Peripheral, Self::Memory>; - unsafe fn buffers_mut( + fn buffers(&self) -> &TransferBuffers<'wo, Self::Peripheral, Self::Memory>; + + fn buffers_mut(&mut self, op: F) + where + for<'a> F: FnOnce( + &'a mut TransferBuffers<'wo, Self::Peripheral, Self::Memory>, + ); + + unsafe fn buffers_mut_unchecked( &mut self, - ) -> &mut Buffers<'wo, Self::Peripheral, Self::Memory>; + ) -> &mut TransferBuffers<'wo, Self::Peripheral, Self::Memory>; } pub struct Start<'wo, Peripheral, Memory> @@ -46,12 +55,21 @@ where type Peripheral = Peripheral; type Memory = Memory; - fn buffers(&self) -> &Buffers<'wo, Peripheral, Memory> { - &self.conf.buffers + fn buffers(&self) -> &TransferBuffers<'wo, Peripheral, Memory> { + self.conf.transfer_direction.buffers() } - unsafe fn buffers_mut(&mut self) -> &mut Buffers<'wo, Peripheral, Memory> { - self.conf.buffers_mut_unchecked() + fn buffers_mut(&mut self, op: F) + where + for<'a> F: FnOnce(&'a mut TransferBuffers<'wo, Peripheral, Memory>), + { + self.conf.transfer_direction.buffers_mut(|b| op(b)); + } + + unsafe fn buffers_mut_unchecked( + &mut self, + ) -> &mut TransferBuffers<'wo, Peripheral, Memory> { + self.conf.transfer_direction.buffers_mut_unchecked() } } @@ -62,7 +80,7 @@ where CXX: ChannelId, { pub(super) stream: Stream, - pub(super) buffers: Buffers<'wo, Peripheral, Memory>, + pub(super) buffers: TransferBuffers<'wo, Peripheral, Memory>, } impl private::Sealed @@ -84,11 +102,20 @@ where type Peripheral = Peripheral; type Memory = Memory; - fn buffers(&self) -> &Buffers<'wo, Peripheral, Memory> { + fn buffers(&self) -> &TransferBuffers<'wo, Peripheral, Memory> { &self.buffers } - unsafe fn buffers_mut(&mut self) -> &mut Buffers<'wo, Peripheral, Memory> { + fn buffers_mut(&mut self, op: F) + where + for<'a> F: FnOnce(&'a mut TransferBuffers<'wo, Peripheral, Memory>), + { + op(&mut self.buffers) + } + + unsafe fn buffers_mut_unchecked( + &mut self, + ) -> &mut TransferBuffers<'wo, Peripheral, Memory> { &mut self.buffers } } @@ -208,13 +235,69 @@ unsafe impl Payload for f32 { type Size = Word; } +#[derive(Debug)] +pub struct MemoryBuffer +where + Memory: Payload, +{ + buffer: Buffer<'static, Memory>, +} + +impl MemoryBuffer +where + Memory: Payload, +{ + pub fn new(buffer: Buffer<'static, Memory>) -> Self { + let s = Self { buffer }; + + s.check_self(); + + s + } + + pub fn get(&self) -> &Buffer<'static, Memory> { + &self.buffer + } + + pub fn get_mut(&mut self, op: F) + where + for<'a> F: FnOnce(&'a mut Buffer<'static, Memory>), + { + op(&mut self.buffer); + + self.check_self(); + } + + pub unsafe fn get_mut_unchecked(&mut self) -> &mut Buffer<'static, Memory> { + &mut self.buffer + } + + pub fn free(self) -> Buffer<'static, Memory> { + self.buffer + } + + fn check_self(&self) { + if let Buffer::Incremented(IncrementedBuffer::WordOffset(_)) = + &self.buffer + { + panic!("Memory Buffer can't have word offset."); + } + } +} + #[derive(Debug, EnumAsInner)] -pub enum MemoryBufferType { - SingleBuffer(SingleBuffer), +pub enum MemoryBufferType +where + Memory: Payload, +{ + SingleBuffer(MemoryBuffer), DoubleBuffer(DoubleBuffer), } -impl MemoryBufferType { +impl MemoryBufferType +where + Memory: Payload, +{ pub fn is_single_buffer(&self) -> bool { self.as_single_buffer().is_some() } @@ -225,9 +308,9 @@ impl MemoryBufferType { pub fn is_read(&self) -> bool { match self { - MemoryBufferType::SingleBuffer(buffer) => buffer.memory.is_read(), + MemoryBufferType::SingleBuffer(buffer) => buffer.get().is_read(), MemoryBufferType::DoubleBuffer(buffer) => { - buffer.memories[0].is_read() + buffer.memories[0].get().is_read() } } } @@ -238,29 +321,24 @@ impl MemoryBufferType { pub fn m0a(&self) -> &MemoryBuffer { match self { - Self::SingleBuffer(buffer) => &buffer.memory, + Self::SingleBuffer(buffer) => &buffer, Self::DoubleBuffer(buffer) => &buffer.memories()[0], } } } #[derive(Debug)] -pub struct SingleBuffer +pub struct DoubleBuffer where Memory: Payload, { - pub memory: MemoryBuffer, + memories: [MemoryBuffer; 2], } -#[derive(Debug)] -pub struct DoubleBuffer +impl DoubleBuffer where Memory: Payload, { - memories: [MemoryBuffer; 2], -} - -impl DoubleBuffer { pub fn new(memories: [MemoryBuffer; 2]) -> Self { let s = Self { memories }; @@ -274,22 +352,15 @@ impl DoubleBuffer { } /// Exposes a mutable reference to the double buffer inside a closure. - /// The **same** reference must be returned in the closure, or this method panics. - /// This prevents the caller to move the reference out of the closure. /// /// At the end, the double buffer will be checked. /// /// If the closure is too limiting, consider using the unchecked version. pub fn memories_mut(&mut self, op: F) where - for<'a> F: FnOnce( - &'a mut [MemoryBuffer; 2], - ) -> &'a mut [MemoryBuffer; 2], + for<'a> F: FnOnce(&'a mut [MemoryBuffer; 2]), { - let ptr_before = &mut self.memories as *mut _; - let ptr_after = op(&mut self.memories) as *mut _; - - assert_eq!(ptr_before, ptr_after); + op(&mut self.memories); self.check_self(); } @@ -315,26 +386,268 @@ impl DoubleBuffer { } fn check_self(&self) { - assert_eq!(self.memories[0].is_read(), self.memories[1].is_read()); - assert_eq!(self.memories[0].is_fixed(), self.memories[1].is_fixed()); + assert_eq!( + self.memories[0].get().is_read(), + self.memories[1].get().is_read() + ); + assert_eq!( + self.memories[0].get().is_fixed(), + self.memories[1].get().is_fixed() + ); - if self.memories[0].is_incremented() { + if self.memories[0].get().is_incremented() { assert_eq!( - self.memories[0].as_incremented().unwrap().len(), - self.memories[1].as_incremented().unwrap().len() + self.memories[0].get().as_incremented().unwrap().len(), + self.memories[1].get().as_incremented().unwrap().len() ); } } } +#[derive(Debug, EnumAsInner)] +pub enum TransferDirection<'wo, Peripheral, Memory> +where + Peripheral: Payload, + Memory: Payload, +{ + P2M(PeripheralToMemory<'wo, Peripheral, Memory>), + M2P(MemoryToPeripheral<'wo, Peripheral, Memory>), + M2M(MemoryToMemory<'wo, Peripheral, Memory>), +} + +impl<'wo, Peripheral, Memory> TransferDirection<'wo, Peripheral, Memory> +where + Peripheral: Payload, + Memory: Payload, +{ + pub fn buffers(&self) -> &TransferBuffers<'wo, Peripheral, Memory> { + match self { + TransferDirection::P2M(p2m) => p2m.buffers(), + TransferDirection::M2P(m2p) => m2p.buffers(), + TransferDirection::M2M(m2m) => m2m.buffers(), + } + } + + pub fn buffers_mut(&mut self, op: F) + where + for<'a> F: FnOnce(&'a mut TransferBuffers<'wo, Peripheral, Memory>), + { + match self { + TransferDirection::P2M(p2m) => p2m.buffers_mut(move |b| op(b)), + TransferDirection::M2P(m2p) => m2p.buffers_mut(move |b| op(b)), + TransferDirection::M2M(m2m) => m2m.buffers_mut(move |b| op(b)), + } + } + + pub unsafe fn buffers_mut_unchecked( + &mut self, + ) -> &mut TransferBuffers<'wo, Peripheral, Memory> { + match self { + TransferDirection::P2M(p2m) => p2m.buffers_mut_unchecked(), + TransferDirection::M2P(m2p) => m2p.buffers_mut_unchecked(), + TransferDirection::M2M(m2m) => m2m.buffers_mut_unchecked(), + } + } + + pub fn free(self) -> TransferBuffers<'wo, Peripheral, Memory> { + match self { + TransferDirection::P2M(p2m) => p2m.free(), + TransferDirection::M2P(m2p) => m2p.free(), + TransferDirection::M2M(m2m) => m2m.free(), + } + } +} + +#[derive(Debug)] +pub struct PeripheralToMemory<'wo, Peripheral, Memory> +where + Peripheral: Payload, + Memory: Payload, +{ + buffers: TransferBuffers<'wo, Peripheral, Memory>, +} + +impl<'wo, Peripheral, Memory> PeripheralToMemory<'wo, Peripheral, Memory> +where + Peripheral: Payload, + Memory: Payload, +{ + pub fn new(buffers: TransferBuffers<'wo, Peripheral, Memory>) -> Self { + let s = Self { buffers }; + + s.check_self(); + + s + } + + pub fn buffers(&self) -> &TransferBuffers<'wo, Peripheral, Memory> { + &self.buffers + } + + pub fn buffers_mut(&mut self, op: F) + where + for<'a> F: FnOnce(&'a mut TransferBuffers<'wo, Peripheral, Memory>), + { + op(&mut self.buffers); + + self.check_self(); + } + + pub unsafe fn buffers_mut_unchecked( + &mut self, + ) -> &mut TransferBuffers<'wo, Peripheral, Memory> { + &mut self.buffers + } + + pub fn free(self) -> TransferBuffers<'wo, Peripheral, Memory> { + self.buffers + } + + fn check_self(&self) { + assert!(self.buffers.get().peripheral_buffer.is_read()); + assert!(self.buffers.get().memory_buffer.is_read()); + } +} + +#[derive(Debug)] +pub struct MemoryToPeripheral<'wo, Peripheral, Memory> +where + Peripheral: Payload, + Memory: Payload, +{ + buffers: TransferBuffers<'wo, Peripheral, Memory>, +} + +impl<'wo, Peripheral, Memory> MemoryToPeripheral<'wo, Peripheral, Memory> +where + Peripheral: Payload, + Memory: Payload, +{ + pub fn new(buffers: TransferBuffers<'wo, Peripheral, Memory>) -> Self { + let s = Self { buffers }; + + s.check_self(); + + s + } + + pub fn buffers(&self) -> &TransferBuffers<'wo, Peripheral, Memory> { + &self.buffers + } + + pub fn buffers_mut(&mut self, op: F) + where + for<'a> F: FnOnce(&'a mut TransferBuffers<'wo, Peripheral, Memory>), + { + op(&mut self.buffers); + + self.check_self(); + } + + pub unsafe fn buffers_mut_unchecked( + &mut self, + ) -> &mut TransferBuffers<'wo, Peripheral, Memory> { + &mut self.buffers + } + + pub fn free(self) -> TransferBuffers<'wo, Peripheral, Memory> { + self.buffers + } + + fn check_self(&self) { + assert!(self.buffers.get().peripheral_buffer.is_write()); + assert!(self.buffers.get().memory_buffer.is_read()); + } +} + +#[derive(Debug)] +pub struct MemoryToMemory<'wo, Source, Dest> +where + Source: Payload, + Dest: Payload, +{ + buffers: TransferBuffers<'wo, Source, Dest>, +} + +impl<'wo, Source, Dest> MemoryToMemory<'wo, Source, Dest> +where + Source: Payload, + Dest: Payload, +{ + pub fn new(buffers: TransferBuffers<'wo, Source, Dest>) -> Self { + let s = Self { buffers }; + + s.check_self(); + + s + } + + pub fn buffers(&self) -> &TransferBuffers<'wo, Source, Dest> { + &self.buffers + } + + pub fn buffers_mut(&mut self, op: F) + where + for<'a> F: FnOnce(&'a mut TransferBuffers<'wo, Source, Dest>), + { + op(&mut self.buffers); + + self.check_self(); + } + + pub unsafe fn buffers_mut_unchecked( + &mut self, + ) -> &mut TransferBuffers<'wo, Source, Dest> { + &mut self.buffers + } + + pub fn source_buffer(&self) -> &Buffer<'wo, Source> { + &self.buffers.get().peripheral_buffer + } + + pub fn dest_buffer(&self) -> &MemoryBuffer { + &self.buffers.get().memory_buffer.as_single_buffer().unwrap() + } + + pub fn dest_buffer_mut(&mut self, op: F) + where + for<'a> F: FnOnce(&'a mut MemoryBuffer), + { + self.buffers.get_mut(move |b| { + op(&mut b.memory_buffer.as_single_buffer_mut().unwrap()) + }); + } + + pub unsafe fn dest_buffer_mut_unchecked( + &mut self, + ) -> &mut MemoryBuffer { + self.buffers + .get_mut_unchecked() + .memory_buffer + .as_single_buffer_mut() + .unwrap() + } + + pub fn free(self) -> TransferBuffers<'wo, Source, Dest> { + self.buffers + } + + fn check_self(&self) { + assert!(self.buffers.get().peripheral_buffer.is_read()); + assert!(self.buffers.get().memory_buffer.is_write()); + + assert!(self.buffers.get().memory_buffer.is_single_buffer()); + } +} + #[derive(Debug)] pub struct Config<'wo, Peripheral, Memory> where Peripheral: Payload, Memory: Payload, { - buffers: Buffers<'wo, Peripheral, Memory>, - stream_config: StreamConfig, + transfer_direction: TransferDirection<'wo, Peripheral, Memory>, + additional_config: AdditionalConfig, } impl<'wo, Peripheral, Memory> Config<'wo, Peripheral, Memory> @@ -343,12 +656,12 @@ where Memory: Payload, { pub fn new( - buffers: Buffers<'wo, Peripheral, Memory>, - stream_config: StreamConfig, + transfer_direction: TransferDirection<'wo, Peripheral, Memory>, + additional_config: AdditionalConfig, ) -> Self { let s = Self { - buffers, - stream_config, + transfer_direction, + additional_config, }; s.check_self(); @@ -356,123 +669,238 @@ where s } - pub fn stream_config(&self) -> StreamConfig { - self.stream_config + pub fn additional_config(&self) -> AdditionalConfig { + self.additional_config } - pub fn transfer_direction(&self) -> TransferDirection { - if self.buffers.get().peripheral_buffer.is_peripheral() { - if self.buffers.get().peripheral_buffer.is_read() { - TransferDirection::P2M - } else { - TransferDirection::M2P - } - } else { - TransferDirection::M2M - } + pub fn transfer_direction( + &self, + ) -> &TransferDirection<'wo, Peripheral, Memory> { + &self.transfer_direction } pub fn transfer_direction_conf(&self) -> TransferDirectionConf { match self.transfer_direction() { - dir @ TransferDirection::P2M | dir @ TransferDirection::M2P => { - TransferDirectionConf::NotM2M(NotM2MConf { - transfer_dir: dir.try_into().unwrap(), - transfer_mode: self.stream_config.transfer_mode, - flow: self.stream_config.flow_controller, - }) + TransferDirection::P2M(_) => { + TransferDirectionConf::P2M(self.not_m2m_conf()) } - TransferDirection::M2M => { - if let TransferModeConf::Fifo(fifo_conf) = - self.stream_config.transfer_mode - { - TransferDirectionConf::M2M(fifo_conf) - } else { - unreachable!() - } + TransferDirection::M2P(_) => { + TransferDirectionConf::M2P(self.not_m2m_conf()) + } + TransferDirection::M2M(_) => { + TransferDirectionConf::M2M(self.fifo_conf().unwrap()) } } } + fn not_m2m_conf(&self) -> NotM2MConf { + NotM2MConf { + transfer_mode: self.transfer_mode_conf(), + flow_controller: self.flow_controller_conf(), + } + } + + fn transfer_mode_conf(&self) -> TransferModeConf { + self.additional_config.transfer_mode.into_stream_conf( + Some(self.m_size()), + self.pinc(), + self.pincos(), + ) + } + + fn flow_controller_conf(&self) -> FlowControllerConf { + self.additional_config + .flow_controller + .into_stream_conf(self.m1a()) + } + + fn pinc(&self) -> Pinc { + let buffers = self.buffers().get(); + + if buffers.peripheral_buffer.is_fixed() { + Pinc::Fixed + } else { + Pinc::Incremented + } + } + + fn pincos(&self) -> Option { + let buffers = self.buffers().get(); + + match &buffers.peripheral_buffer { + Buffer::Fixed(_) => None, + Buffer::Incremented(buffer) => match buffer { + IncrementedBuffer::RegularOffset(_) => Some(Pincos::PSize), + IncrementedBuffer::WordOffset(_) => Some(Pincos::Word), + }, + } + } + + fn minc(&self) -> Minc { + let buffers = self.buffers().get(); + + match &buffers.memory_buffer.m0a().get() { + Buffer::Fixed(_) => Minc::Fixed, + Buffer::Incremented(_) => Minc::Incremented, + } + } + + fn m_size(&self) -> MSize { + PayloadSize::from_payload::().into() + } + + fn fifo_conf(&self) -> Option { + if let TransferModeTransferConf::Fifo(conf) = + self.additional_config.transfer_mode + { + Some(conf.into_stream_conf( + self.m_size(), + self.pinc(), + self.pincos(), + )) + } else { + None + } + } + pub fn pa(&self) -> Pa { - Pa(self.buffers.get().peripheral_buffer.as_ptr(Some(0)) as u32) + Pa(self.buffers().get().peripheral_buffer.as_ptr(Some(0)) as u32) } pub fn m0a(&self) -> M0a { - match &self.buffers.get().memory_buffer { - MemoryBufferType::SingleBuffer(single) => { - M0a(single.memory.as_ptr(Some(0)) as u32) + match &self.buffers().get().memory_buffer { + MemoryBufferType::SingleBuffer(memory) => { + M0a(memory.get().as_ptr(Some(0)) as u32) } MemoryBufferType::DoubleBuffer(double) => { - M0a(double.memories()[0].as_ptr(Some(0)) as u32) + M0a(double.memories()[0].get().as_ptr(Some(0)) as u32) } } } pub fn m1a(&self) -> Option { if let MemoryBufferType::DoubleBuffer(buffer) = - &self.buffers.get().memory_buffer + &self.buffers().get().memory_buffer { - Some(M1a(buffer.memories()[1].as_ptr(Some(0)) as u32)) + Some(M1a(buffer.memories()[1].get().as_ptr(Some(0)) as u32)) } else { None } } - pub fn buffers(&self) -> &Buffers<'wo, Peripheral, Memory> { - &self.buffers + pub fn stream_config(&self, conf: &mut StreamConfig) { + conf.transfer_direction = self.transfer_direction_conf(); + + let buffers = self.buffers().get(); + + // Configure ndt + + match &buffers.peripheral_buffer { + Buffer::Fixed(_) => { + match buffers.memory_buffer.m0a().get() { + Buffer::Fixed(_) => { + // NDT must be configured in advance + } + Buffer::Incremented(buffer) => { + let p_size: usize = + PayloadSize::from_payload::().into(); + let m_size: usize = + PayloadSize::from_payload::().into(); + + let memory_bytes = buffer.len() * m_size; + + if memory_bytes % p_size != 0 { + panic!("Last transfer may be incomplete."); + } + + let ndt = u16::try_from(memory_bytes / p_size).unwrap(); + conf.ndt = Ndt(ndt); + } + } + } + Buffer::Incremented(buffer) => { + let ndt = u16::try_from(buffer.len()).unwrap(); + conf.ndt = Ndt(ndt); + } + } + + // Configure addresses + // Note: M1a is already configured in `self.transfer_direction_conf()` + + conf.pa = self.pa(); + conf.m0a = self.m0a(); + + // Configure Incrementing + // Note: Pinc is already configured in `self.transfer_direction_conf()` + + conf.minc = self.minc(); + } + + pub fn buffers(&self) -> &TransferBuffers<'wo, Peripheral, Memory> { + self.transfer_direction.buffers() } pub fn buffers_mut(&mut self, op: F) where - for<'a> F: FnOnce( - &'a mut Buffers<'wo, Peripheral, Memory>, - ) -> &'a mut Buffers<'wo, Peripheral, Memory>, + for<'a> F: FnOnce(&'a mut TransferBuffers<'wo, Peripheral, Memory>), { - let ptr_before = &self.buffers as *const _; - let ptr_after = op(&mut self.buffers) as *const _; - - assert_eq!(ptr_before, ptr_after); + self.transfer_direction.buffers_mut(|b| op(b)); self.check_self(); } pub unsafe fn buffers_mut_unchecked( &mut self, - ) -> &mut Buffers<'wo, Peripheral, Memory> { - &mut self.buffers + ) -> &mut TransferBuffers<'wo, Peripheral, Memory> { + self.transfer_direction.buffers_mut_unchecked() } - pub fn free(self) -> Buffers<'wo, Peripheral, Memory> { - self.buffers + pub fn free(self) -> TransferDirection<'wo, Peripheral, Memory> { + self.transfer_direction } fn check_self(&self) { + let buffers = self.buffers().get(); + // Check Buffer Mode + if matches!( - self.stream_config.flow_controller, - FlowControllerConf::Dma( - CircularModeConf::Enabled(BufferModeConf::DoubleBuffer(_)), + self.additional_config.flow_controller, + FlowControllerTransferConf::Dma( + CircularModeTransferConf::Enabled( + BufferModeTransferConf::DoubleBuffer(_), + ), ) ) { - assert!(self.buffers.get().memory_buffer.is_double_buffer()); + assert!(buffers.memory_buffer.is_double_buffer()); } else { - assert!(self.buffers.get().memory_buffer.is_single_buffer()); + assert!(buffers.memory_buffer.is_single_buffer()); } - if self.transfer_direction() == TransferDirection::M2M { + // Check Transfer Direction + + if matches!(self.transfer_direction(), TransferDirection::M2M(_)) { assert!(matches!( - self.stream_config.transfer_mode, - TransferModeConf::Fifo(_) + self.additional_config.transfer_mode, + TransferModeTransferConf::Fifo(_) )); assert!(matches!( - self.stream_config.flow_controller, - FlowControllerConf::Dma(CircularModeConf::Disabled) + self.additional_config.flow_controller, + FlowControllerTransferConf::Dma( + CircularModeTransferConf::Disabled + ) )); } - if matches!(self.stream_config.transfer_mode, TransferModeConf::Direct) - { + // Check Transfer Mode + + if matches!( + self.additional_config.transfer_mode, + TransferModeTransferConf::Direct + ) { assert_eq!(Peripheral::Size::SIZE, Memory::Size::SIZE); } + + // Check Incrementing } } @@ -482,31 +910,20 @@ where Peripheral: Payload, Memory: Payload, { - peripheral_buffer: Buffer<'wo, Peripheral>, - memory_buffer: MemoryBufferType, -} - -#[derive(Debug)] -pub struct BuffersView<'a, 'wo, Peripheral, Memory> -where - Peripheral: Payload, - Memory: Payload, -{ - pub peripheral_buffer: &'a Buffer<'wo, Peripheral>, - pub memory_buffer: &'a MemoryBufferType, + pub peripheral_buffer: Buffer<'wo, Peripheral>, + pub memory_buffer: MemoryBufferType, } #[derive(Debug)] -pub struct BuffersViewMut<'a, 'wo, Peripheral, Memory> +pub struct TransferBuffers<'wo, Peripheral, Memory> where Peripheral: Payload, Memory: Payload, { - pub peripheral_buffer: &'a mut Buffer<'wo, Peripheral>, - pub memory_buffer: &'a mut MemoryBufferType, + buffers: Buffers<'wo, Peripheral, Memory>, } -impl<'wo, Peripheral, Memory> Buffers<'wo, Peripheral, Memory> +impl<'wo, Peripheral, Memory> TransferBuffers<'wo, Peripheral, Memory> where Peripheral: Payload, Memory: Payload, @@ -515,256 +932,286 @@ where /// /// * `peripheral_buffer`: Usually `Buffer::Peripheral`, except for `M2M`-transfers (Memory to Memory), where the source buffer is `Buffer::Memory`. /// * `memory_buffer`: The `MemoryBuffer` of the transfer. - pub fn new( - peripheral_buffer: Buffer<'wo, Peripheral>, - memory_buffer: MemoryBufferType, - ) -> Self { - let s = Self { - peripheral_buffer, - memory_buffer, - }; + pub fn new(buffers: Buffers<'wo, Peripheral, Memory>) -> Self { + let s = Self { buffers }; s.check_self(); s } - pub fn get(&self) -> BuffersView { - BuffersView { - peripheral_buffer: &self.peripheral_buffer, - memory_buffer: &self.memory_buffer, - } + pub fn get(&self) -> &Buffers<'wo, Peripheral, Memory> { + &self.buffers } pub fn get_mut(&mut self, op: F) where - for<'a> F: FnOnce( - BuffersViewMut<'a, 'wo, Peripheral, Memory>, - ) - -> BuffersViewMut<'a, 'wo, Peripheral, Memory>, + for<'a> F: FnOnce(&'a mut Buffers<'wo, Peripheral, Memory>), { - let peripheral_before = &self.peripheral_buffer as *const _; - let memory_before = &self.memory_buffer as *const _; - - let view = op(BuffersViewMut { - peripheral_buffer: &mut self.peripheral_buffer, - memory_buffer: &mut self.memory_buffer, - }); - - let peripheral_after = view.peripheral_buffer as *const _; - let memory_after = view.memory_buffer as *const _; - - assert_eq!(peripheral_before, peripheral_after); - assert_eq!(memory_before, memory_after); + op(&mut self.buffers); self.check_self(); } pub unsafe fn get_mut_unchecked( &mut self, - ) -> BuffersViewMut<'_, 'wo, Peripheral, Memory> { - BuffersViewMut { - peripheral_buffer: &mut self.peripheral_buffer, - memory_buffer: &mut self.memory_buffer, - } + ) -> &mut Buffers<'wo, Peripheral, Memory> { + &mut self.buffers } - pub fn free(self) -> (Buffer<'wo, Peripheral>, MemoryBufferType) { - (self.peripheral_buffer, self.memory_buffer) + pub fn free(self) -> Buffers<'wo, Peripheral, Memory> { + self.buffers } fn check_self(&self) { assert_ne!( - self.peripheral_buffer.is_read(), - self.memory_buffer.is_read() + self.buffers.peripheral_buffer.is_read(), + self.buffers.memory_buffer.is_read() ); - - if self.peripheral_buffer.is_memory() { - assert!(self.peripheral_buffer.is_read()); - } } } #[derive(Debug, Clone, Copy)] -pub struct StreamConfig { - pub transfer_mode: TransferModeConf, - pub flow_controller: FlowControllerConf, +pub struct AdditionalConfig { + pub transfer_mode: TransferModeTransferConf, + pub flow_controller: FlowControllerTransferConf, } -#[derive(Debug, Clone, Copy)] -pub enum PayloadPort -where - Peripheral: Payload, - Memory: Payload, -{ - Peripheral(Peripheral), - Memory(Memory), +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +pub enum TransferModeTransferConf { + Direct, + Fifo(FifoTransferConf), } -impl PayloadPort -where - Peripheral: Payload, - Memory: Payload, -{ - pub fn peripheral(self) -> Peripheral { - if let PayloadPort::Peripheral(p) = self { - p - } else { - panic!("Tried to unwrap memory port as peripheral port."); +impl TransferModeTransferConf { + pub fn into_stream_conf( + self, + m_size: Option, + pinc: Pinc, + pincos: Option, + ) -> TransferModeConf { + match self { + Self::Direct => TransferModeConf::Direct(DirectConf { pinc }), + Self::Fifo(fifo) => TransferModeConf::Fifo(fifo.into_stream_conf( + m_size.unwrap(), + pinc, + pincos, + )), } } +} - pub fn memory(self) -> Memory { - if let PayloadPort::Memory(m) = self { - m - } else { - panic!("Tried to unwrap peripheral port as memory port."); +impl From for TransferModeTransferConf { + fn from(x: TransferModeConf) -> Self { + match x { + TransferModeConf::Direct(_) => Self::Direct, + TransferModeConf::Fifo(fifo) => Self::Fifo(fifo.into()), } } } -#[derive(Debug, EnumAsInner)] -pub enum PointerPort -where - Peripheral: Payload, - Memory: Payload, -{ - Peripheral(*mut Peripheral), - Memory(*mut Memory), -} - -#[derive(Debug, EnumAsInner)] -pub enum Buffer<'wo, P> -where - P: Payload, -{ - Peripheral(PeripheralBuffer<'wo, P>), - Memory(MemoryBuffer

), +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +pub struct FifoTransferConf { + pub fifo_threshold: FifoThreshold, + pub p_burst: PBurstTransferConf, + pub m_burst: MBurst, } -impl<'wo, P> Buffer<'wo, P> -where - P: Payload, -{ - pub fn is_peripheral(&self) -> bool { - if let Buffer::Peripheral(_) = self { - true - } else { - false +impl FifoTransferConf { + pub fn into_stream_conf( + self, + m_size: MSize, + pinc: Pinc, + pincos: Option, + ) -> FifoConf { + FifoConf { + fifo_threshold: self.fifo_threshold, + p_burst: self.p_burst.into_stream_conf(pinc, pincos), + m_burst: self.m_burst, + m_size, } } +} - pub fn is_memory(&self) -> bool { - if let Buffer::Memory(_) = self { - true - } else { - false +impl From for FifoTransferConf { + fn from(x: FifoConf) -> Self { + Self { + fifo_threshold: x.fifo_threshold, + p_burst: x.p_burst.into(), + m_burst: x.m_burst, } } +} - pub unsafe fn get(&self, index: Option) -> P { - match self { - Buffer::Peripheral(buffer) => buffer.get(index), - Buffer::Memory(buffer) => buffer.get(index), - } - } +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +pub enum PBurstTransferConf { + Single, + Incr4, + Incr8, + Incr16, +} - pub fn as_ptr(&self, index: Option) -> *const P { +impl PBurstTransferConf { + pub fn into_stream_conf( + self, + pinc: Pinc, + pincos: Option, + ) -> PBurstConf { match self { - Buffer::Peripheral(buffer) => buffer.as_ptr(index), - Buffer::Memory(buffer) => buffer.as_ptr(index), - } - } + Self::Single => { + let pinc_conf = match pinc { + Pinc::Fixed => PincConf::Fixed, + Pinc::Incremented => PincConf::Incremented(pincos.unwrap()), + }; - pub fn is_read(&self) -> bool { - match self { - Buffer::Peripheral(buffer) => buffer.is_read(), - Buffer::Memory(buffer) => buffer.is_read(), + PBurstConf::Single(pinc_conf) + } + Self::Incr4 => PBurstConf::Incr4(pinc), + Self::Incr8 => PBurstConf::Incr8(pinc), + Self::Incr16 => PBurstConf::Incr16(pinc), } } +} - pub fn is_write(&self) -> bool { - match self { - Buffer::Peripheral(buffer) => buffer.is_write(), - Buffer::Memory(buffer) => buffer.is_write(), +impl From for PBurstTransferConf { + fn from(x: PBurstConf) -> Self { + match x { + PBurstConf::Single(_) => Self::Single, + PBurstConf::Incr4(_) => Self::Incr4, + PBurstConf::Incr8(_) => Self::Incr8, + PBurstConf::Incr16(_) => Self::Incr16, } } +} - pub fn is_fixed(&self) -> bool { +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +pub enum FlowControllerTransferConf { + Dma(CircularModeTransferConf), + Peripheral, +} + +impl FlowControllerTransferConf { + pub fn into_stream_conf(self, m1a: Option) -> FlowControllerConf { match self { - Buffer::Peripheral(buffer) => buffer.is_fixed(), - Buffer::Memory(buffer) => buffer.is_fixed(), + Self::Dma(circular) => { + FlowControllerConf::Dma(circular.into_stream_conf(m1a)) + } + Self::Peripheral => FlowControllerConf::Peripheral, } } +} - pub fn is_incremented(&self) -> bool { - match self { - Buffer::Peripheral(buffer) => buffer.is_incremented(), - Buffer::Memory(buffer) => buffer.is_incremented(), +impl From for FlowControllerTransferConf { + fn from(x: FlowControllerConf) -> Self { + match x { + FlowControllerConf::Dma(circ) => Self::Dma(circ.into()), + FlowControllerConf::Peripheral => Self::Peripheral, } } } -#[derive(Debug, EnumAsInner)] -pub enum MemoryBuffer

-where - P: Payload, -{ - Fixed(FixedBuffer

), - Incremented(RegularOffsetBuffer

), +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +pub enum CircularModeTransferConf { + Disabled, + Enabled(BufferModeTransferConf), } -impl

MemoryBuffer

-where - P: Payload, -{ - pub fn is_fixed(&self) -> bool { - if let MemoryBuffer::Fixed(_) = self { - true - } else { - false +impl CircularModeTransferConf { + pub fn into_stream_conf(self, m1a: Option) -> CircularModeConf { + match self { + Self::Disabled => CircularModeConf::Disabled, + Self::Enabled(buffer_mode) => { + CircularModeConf::Enabled(buffer_mode.into_stream_conf(m1a)) + } } } +} - pub fn is_incremented(&self) -> bool { - if let MemoryBuffer::Incremented(_) = self { - true - } else { - false +impl From for CircularModeTransferConf { + fn from(x: CircularModeConf) -> Self { + match x { + CircularModeConf::Disabled => Self::Disabled, + CircularModeConf::Enabled(buffer_mode) => { + Self::Enabled(buffer_mode.into()) + } } } +} - pub unsafe fn get(&self, index: Option) -> P { +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +pub enum BufferModeTransferConf { + Regular, + DoubleBuffer(DoubleBufferTransferConf), +} + +impl BufferModeTransferConf { + pub fn into_stream_conf(self, m1a: Option) -> BufferModeConf { match self { - MemoryBuffer::Fixed(buffer) => buffer.get(), - MemoryBuffer::Incremented(buffer) => buffer.get(index.unwrap()), + Self::Regular => BufferModeConf::Regular, + Self::DoubleBuffer(conf) => BufferModeConf::DoubleBuffer( + conf.into_stream_conf(m1a.unwrap()), + ), } } +} - pub fn as_ptr(&self, index: Option) -> *const P { - match self { - MemoryBuffer::Fixed(buffer) => buffer.as_ptr(), - MemoryBuffer::Incremented(buffer) => buffer.as_ptr(index.unwrap()), +impl From for BufferModeTransferConf { + fn from(x: BufferModeConf) -> Self { + match x { + BufferModeConf::Regular => Self::Regular, + BufferModeConf::DoubleBuffer(conf) => { + Self::DoubleBuffer(DoubleBufferTransferConf { + current_target: conf.current_target, + }) + } } } +} - pub fn is_read(&self) -> bool { - match self { - MemoryBuffer::Fixed(buffer) => buffer.is_read(), - MemoryBuffer::Incremented(buffer) => buffer.is_read(), +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +pub struct DoubleBufferTransferConf { + pub current_target: CurrentTarget, +} + +impl DoubleBufferTransferConf { + pub fn into_stream_conf(self, m1a: M1a) -> DoubleBufferConf { + DoubleBufferConf { + current_target: self.current_target, + m1a, } } +} - pub fn is_write(&self) -> bool { - match self { - MemoryBuffer::Fixed(buffer) => buffer.is_write(), - MemoryBuffer::Incremented(buffer) => buffer.is_write(), +impl From for DoubleBufferTransferConf { + fn from(x: DoubleBufferConf) -> Self { + Self { + current_target: x.current_target, } } } +#[derive(Copy, Clone, Debug, EnumAsInner)] +pub enum PayloadPort +where + Peripheral: Payload, + Memory: Payload, +{ + Peripheral(Peripheral), + Memory(Memory), +} + +#[derive(Debug, EnumAsInner)] +pub enum PointerPort +where + Peripheral: Payload, + Memory: Payload, +{ + Peripheral(*mut Peripheral), + Memory(*mut Memory), +} + #[derive(Debug, EnumAsInner)] -pub enum PeripheralBuffer<'wo, P> +pub enum Buffer<'wo, P> where P: Payload, { @@ -772,53 +1219,51 @@ where Incremented(IncrementedBuffer<'wo, P>), } -impl<'wo, P> PeripheralBuffer<'wo, P> +impl<'wo, P> Buffer<'wo, P> where P: Payload, { - pub fn is_fixed(&self) -> bool { - if let PeripheralBuffer::Fixed(_) = self { - true - } else { - false - } - } - - pub fn is_incremented(&self) -> bool { - if let PeripheralBuffer::Incremented(_) = self { - true - } else { - false - } - } - pub unsafe fn get(&self, index: Option) -> P { match self { - PeripheralBuffer::Fixed(buffer) => buffer.get(), - PeripheralBuffer::Incremented(buffer) => buffer.get(index.unwrap()), + Buffer::Fixed(buffer) => buffer.get(), + Buffer::Incremented(buffer) => buffer.get(index.unwrap()), } } pub fn as_ptr(&self, index: Option) -> *const P { match self { - PeripheralBuffer::Fixed(buffer) => buffer.as_ptr(), - PeripheralBuffer::Incremented(buffer) => { - buffer.as_ptr(index.unwrap()) - } + Buffer::Fixed(buffer) => buffer.as_ptr(), + Buffer::Incremented(buffer) => buffer.as_ptr(index.unwrap()), } } pub fn is_read(&self) -> bool { match self { - PeripheralBuffer::Fixed(buffer) => buffer.is_read(), - PeripheralBuffer::Incremented(buffer) => buffer.is_read(), + Buffer::Fixed(buffer) => buffer.is_read(), + Buffer::Incremented(buffer) => buffer.is_read(), } } pub fn is_write(&self) -> bool { match self { - PeripheralBuffer::Fixed(buffer) => buffer.is_write(), - PeripheralBuffer::Incremented(buffer) => buffer.is_write(), + Buffer::Fixed(buffer) => buffer.is_write(), + Buffer::Incremented(buffer) => buffer.is_write(), + } + } + + pub fn is_fixed(&self) -> bool { + if let Self::Fixed(_) = self { + true + } else { + false + } + } + + pub fn is_incremented(&self) -> bool { + if let Self::Incremented(_) = self { + true + } else { + false } } } diff --git a/src/dma/utils.rs b/src/dma/utils.rs index bddcf42b..de7ec6ea 100644 --- a/src/dma/utils.rs +++ b/src/dma/utils.rs @@ -1,5 +1,5 @@ use core::fmt; -pub trait DefaultTraits: fmt::Debug + PartialEq + Eq + Clone + Copy {} +pub trait DefaultTraits: Copy + Clone + PartialEq + Eq + fmt::Debug {} -impl DefaultTraits for T where T: fmt::Debug + PartialEq + Eq + Clone + Copy {} +impl DefaultTraits for T {} diff --git a/src/serial/dma.rs b/src/serial/dma.rs index 7e4f8cdc..7250e7bd 100644 --- a/src/serial/dma.rs +++ b/src/serial/dma.rs @@ -5,13 +5,13 @@ use crate::dma::mux::request_ids::{ Usart2TxDma, Usart3RxDma, Usart3TxDma, Usart6RxDma, Usart6TxDma, }; use crate::dma::mux::{EgED as IEgED, SyncED as ISyncED}; -use crate::dma::safe_transfer::{ - FixedBuffer, FixedBufferR, MemoryBufferStatic, Ongoing as TransferOngoing, - Payload, PeripheralBuffer, Start as TransferStart, -}; use crate::dma::stream::{ Disabled as StreamDisabled, IsrCleared as StreamIsrCleared, StreamIsr, }; +use crate::dma::transfer::{ + FixedBuffer, FixedBufferR, MemoryBufferStatic, Ongoing as TransferOngoing, + Payload, PeripheralBuffer, Start as TransferStart, +}; use crate::dma::{Channel, ChannelId, DmaMux, SafeTransfer}; use crate::stm32::{UART4, UART5, UART7, UART8}; use crate::stm32::{USART1, USART2, USART3, USART6}; From e19cb50837405272d3c8d2d8c13b2211786aba3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ad=C3=A4?= Date: Tue, 21 Apr 2020 12:09:37 +0200 Subject: [PATCH 086/103] splits dma into more modules --- src/dma/mod.rs | 1935 +++-------------------- src/dma/mux/mod.rs | 496 ++++-- src/dma/mux/request_gen.rs | 164 +- src/dma/{stream.rs => stream/config.rs} | 437 +++-- src/dma/stream/mod.rs | 1200 ++++++++++++++ src/dma/transfer.rs | 1784 --------------------- src/dma/transfer/buffer.rs | 729 +++++++++ src/dma/transfer/config.rs | 510 ++++++ src/dma/transfer/mod.rs | 607 +++++++ src/serial/dma.rs | 6 +- 10 files changed, 3989 insertions(+), 3879 deletions(-) rename src/dma/{stream.rs => stream/config.rs} (92%) create mode 100644 src/dma/stream/mod.rs delete mode 100644 src/dma/transfer.rs create mode 100644 src/dma/transfer/buffer.rs create mode 100644 src/dma/transfer/config.rs create mode 100644 src/dma/transfer/mod.rs diff --git a/src/dma/mod.rs b/src/dma/mod.rs index 80c5193f..3b9e8c08 100644 --- a/src/dma/mod.rs +++ b/src/dma/mod.rs @@ -2,6 +2,7 @@ // TODO: Remove when merging. #![warn(clippy::all)] +#![allow(clippy::missing_safety_doc)] #[macro_use] mod macros; @@ -13,1631 +14,133 @@ mod utils; use self::mux::request_gen::{ Disabled as GenDisabled, RequestGenIsr, G0, G1, G2, G3, G4, G5, G6, G7, }; -use self::mux::request_ids::{ReqNone, RequestId as IRequestId, RequestIdSome}; +use self::mux::request_ids::{ReqNone, RequestId as IRequestId}; use self::mux::MuxIsr; use self::mux::{ - EgDisabled, EgED as IEgED, EgEnabled, MuxShared, NbReq, OverrunError, - RequestGenerator, RequestId, SyncDisabled, SyncED as ISyncED, SyncEnabled, - SyncId, SyncOverrunInterrupt, SyncPolarity, + EgDisabled, IEgED, ISyncED, MuxShared, RequestGenerator, SyncDisabled, }; -use self::stream::{ - BufferMode, BufferModeConf, CircularMode, CircularModeConf, Config, - CurrentTarget, DirectConf, DirectModeErrorInterrupt, Disabled, - DoubleBufferConf, Enabled, Error, Event, FifoConf, FifoErrorInterrupt, - FifoThreshold, FlowController, FlowControllerConf, HalfTransferInterrupt, - IntoNum, IsrCleared, IsrState as IIsrState, IsrUncleared, M0a, M1a, MBurst, - MSize, Minc, Ndt, NotM2MConf, PBurst, PBurstConf, PSize, Pa, Pinc, - PincConf, Pincos, PriorityLevel, StreamIsr, TransferCompleteInterrupt, - TransferDirection, TransferDirectionConf, TransferErrorInterrupt, - TransferMode, TransferModeConf, ED as IED, -}; -use self::transfer::{ - Config as TransferConfig, Ongoing, Payload, Start, TransferState, -}; -use crate::nb::{self, Error as NbError}; -use crate::private; -use crate::rcc::Ccdr; -use crate::stm32::dma1::ST; -use crate::stm32::dmamux1::CCR; -use crate::stm32::{DMA1, DMA2, RCC}; -use core::convert::{Infallible, TryFrom, TryInto}; -use core::marker::PhantomData; -use stm32h7::stm32h743::DMAMUX1; - -/// Marker Trait for DMA peripherals -pub trait DmaPeripheral: private::Sealed {} -impl DmaPeripheral for DMA1 {} -impl DmaPeripheral for DMA2 {} - -pub trait ChannelId: Send + private::Sealed { - const STREAM_ID: usize; - const MUX_ID: usize; - - type DMA: DmaPeripheral; -} - -macro_rules! channels { - ($($channel:ident => [$stream:tt, $mux:tt, $dma:ident]),*) => { - $( - pub struct $channel; - - impl crate::private::Sealed for $channel {} - - impl ChannelId for $channel { - const STREAM_ID: usize = $stream; - const MUX_ID: usize = $mux; - - type DMA = $dma; - } - )* - }; -} - -channels! { - C0 => [0, 0, DMA1], - C1 => [1, 1, DMA1], - C2 => [2, 2, DMA1], - C3 => [3, 3, DMA1], - C4 => [4, 4, DMA1], - C5 => [5, 5, DMA1], - C6 => [6, 6, DMA1], - C7 => [7, 7, DMA1], - C8 => [0, 8, DMA2], - C9 => [1, 9, DMA2], - C10 => [2, 10, DMA2], - C11 => [3, 11, DMA2], - C12 => [4, 12, DMA2], - C13 => [5, 13, DMA2], - C14 => [6, 14, DMA2], - C15 => [7, 15, DMA2] -} - -/// DMA Channel -pub struct Channel -where - CXX: ChannelId, - StreamED: IED, - IsrState: IIsrState, - ReqId: IRequestId, - SyncED: ISyncED, - EgED: IEgED, -{ - pub stream: Stream, - pub mux: DmaMux, -} - -impl - Channel -where - CXX: ChannelId, - StreamED: IED, - IsrState: IIsrState, - ReqId: IRequestId, - SyncED: ISyncED, - EgED: IEgED, -{ - /// Exposes the stream as owned value in a closure - pub fn stream_owned( - self, - op: F, - ) -> Channel - where - F: FnOnce( - Stream, - ) -> Stream, - NewStreamED: IED, - NewIsrState: IIsrState, - { - let new_stream = op(self.stream); - - Channel { - stream: new_stream, - mux: self.mux, - } - } - - /// Exposes the mux as owned value in a closure - pub fn mux_owned( - self, - op: F, - ) -> Channel - where - F: FnOnce( - DmaMux, - ) -> DmaMux, - NewReqId: IRequestId, - NewSyncED: ISyncED, - NewEgED: IEgED, - { - let new_mux = op(self.mux); - - Channel { - stream: self.stream, - mux: new_mux, - } - } -} - -/// DMA Stream -pub struct Stream -where - CXX: ChannelId, - ED: IED, - IsrState: IIsrState, -{ - /// This field *must not* be mutated using shared references - rb: &'static ST, - config_ndt: Ndt, - _phantom_data: PhantomData<(CXX, ED, IsrState)>, -} - -impl Stream -where - CXX: ChannelId, -{ - /// Creates an instance of a Stream in initial state. - /// - /// Should only be called after RCC-Reset of the DMA. - fn after_reset(rb: &'static ST) -> Self { - Stream { - rb, - config_ndt: Ndt::default(), - _phantom_data: PhantomData, - } - } -} - -impl Stream -where - CXX: ChannelId, - ED: IED, - IsrState: IIsrState, -{ - pub fn config(&self) -> Config { - Config { - transfer_complete_interrupt: self.transfer_complete_interrupt(), - half_transfer_interrupt: self.half_transfer_interrupt(), - transfer_error_interrupt: self.transfer_error_interrupt(), - direct_mode_error_interrupt: self.direct_mode_error_interrupt(), - fifo_error_interrupt: self.fifo_error_interrupt(), - minc: self.minc(), - priority_level: self.priority_level(), - p_size: self.p_size(), - ndt: self.ndt(), - pa: self.pa(), - m0a: self.m0a(), - transfer_direction: self.transfer_direction_config(), - } - } - - fn transfer_direction_config(&self) -> TransferDirectionConf { - match self.transfer_direction() { - TransferDirection::P2M => { - TransferDirectionConf::P2M(self.not_m2m_config()) - } - TransferDirection::M2P => { - TransferDirectionConf::M2P(self.not_m2m_config()) - } - TransferDirection::M2M => { - TransferDirectionConf::M2M(self.fifo_config()) - } - } - } - - fn not_m2m_config(&self) -> NotM2MConf { - NotM2MConf { - transfer_mode: self.transfer_mode_config(), - flow_controller: self.flow_controller_config(), - } - } - - fn transfer_mode_config(&self) -> TransferModeConf { - match self.transfer_mode() { - TransferMode::Direct => { - TransferModeConf::Direct(self.direct_conf()) - } - TransferMode::Fifo => TransferModeConf::Fifo(self.fifo_config()), - } - } - - fn flow_controller_config(&self) -> FlowControllerConf { - match self.flow_controller() { - FlowController::Dma => { - FlowControllerConf::Dma(self.circular_mode_config()) - } - FlowController::Peripheral => FlowControllerConf::Peripheral, - } - } - - fn circular_mode_config(&self) -> CircularModeConf { - match self.circular_mode() { - CircularMode::Disabled => CircularModeConf::Disabled, - CircularMode::Enabled => { - CircularModeConf::Enabled(self.buffer_mode_config()) - } - } - } - - fn buffer_mode_config(&self) -> BufferModeConf { - match self.buffer_mode() { - BufferMode::Regular => BufferModeConf::Regular, - BufferMode::DoubleBuffer => { - BufferModeConf::DoubleBuffer(self.double_buffer_config()) - } - } - } - - fn double_buffer_config(&self) -> DoubleBufferConf { - DoubleBufferConf { - current_target: self.current_target(), - m1a: self.m1a().unwrap(), - } - } - - fn direct_conf(&self) -> DirectConf { - DirectConf { pinc: self.pinc() } - } - - fn fifo_config(&self) -> FifoConf { - FifoConf { - fifo_threshold: self.fifo_threshold().unwrap(), - p_burst: self.p_burst_config(), - m_burst: self.m_burst(), - m_size: self.m_size(), - } - } - - fn p_burst_config(&self) -> PBurstConf { - match self.p_burst() { - PBurst::Single => PBurstConf::Single(self.pinc_conf()), - PBurst::Incr4 => PBurstConf::Incr4(self.pinc()), - PBurst::Incr8 => PBurstConf::Incr8(self.pinc()), - PBurst::Incr16 => PBurstConf::Incr16(self.pinc()), - } - } - - fn pinc_conf(&self) -> PincConf { - match self.pinc() { - Pinc::Fixed => PincConf::Fixed, - Pinc::Incremented => PincConf::Incremented(self.pincos()), - } - } - - /// Returns the id of the Stream - pub fn id(&self) -> usize { - CXX::STREAM_ID - } - - /// Performs a *volatile* read of the stream enable bit - pub fn is_enabled(&self) -> bool { - self.rb.cr.read().en().bit_is_set() - } - - /// Returns the Transfer Complete Interrupt config flag - pub fn transfer_complete_interrupt(&self) -> TransferCompleteInterrupt { - self.rb.cr.read().tcie().bit().into() - } - - /// Sets the Transfer Complete Interrupt config flag - fn set_transfer_complete_interrupt( - &mut self, - tc_intrpt: TransferCompleteInterrupt, - ) { - self.rb.cr.modify(|_, w| w.tcie().bit(tc_intrpt.into())); - } - - /// Returns the Half Transfer Interrupt config flag - pub fn half_transfer_interrupt(&self) -> HalfTransferInterrupt { - self.rb.cr.read().htie().bit().into() - } - - /// Sets the Half Transfer Interrupt config flag - fn set_half_transfer_interrupt( - &mut self, - ht_intrpt: HalfTransferInterrupt, - ) { - self.rb.cr.modify(|_, w| w.htie().bit(ht_intrpt.into())); - } - - /// Returns the Transfer Error Interrupt config flag - pub fn transfer_error_interrupt(&self) -> TransferErrorInterrupt { - self.rb.cr.read().teie().bit().into() - } - - /// Sets the Transfer Error Interrupt config flag - fn set_transfer_error_interrupt( - &mut self, - te_intrpt: TransferErrorInterrupt, - ) { - self.rb.cr.modify(|_, w| w.teie().bit(te_intrpt.into())); - } - - /// Returns the Direct Mode Error Interrupt config flag - pub fn direct_mode_error_interrupt(&self) -> DirectModeErrorInterrupt { - self.rb.cr.read().dmeie().bit().into() - } - - /// Sets the Direct Mode Error Interrupt config flag - fn set_direct_mode_error_interrupt( - &mut self, - dme_intrpt: DirectModeErrorInterrupt, - ) { - self.rb.cr.modify(|_, w| w.dmeie().bit(dme_intrpt.into())); - } - - /// Returns the Fifo Error Interrupt config flag - pub fn fifo_error_interrupt(&self) -> FifoErrorInterrupt { - self.rb.fcr.read().feie().bit().into() - } - - /// Sets the Fifo Error Interrupt config flag - fn set_fifo_error_interrupt(&mut self, fe_intrpt: FifoErrorInterrupt) { - self.rb.fcr.modify(|_, w| w.feie().bit(fe_intrpt.into())); - } - - /// Returns the Flow Controller - pub fn flow_controller(&self) -> FlowController { - self.rb.cr.read().pfctrl().bit().into() - } - - /// Returns the Transfer Direction - pub fn transfer_direction(&self) -> TransferDirection { - self.rb.cr.read().dir().bits().try_into().unwrap() - } - - /// Returns the Circular Mode - pub fn circular_mode(&self) -> CircularMode { - self.rb.cr.read().circ().bit().into() - } - - /// Returns the Peripheral Increment config flag - pub fn pinc(&self) -> Pinc { - self.rb.cr.read().pinc().bit().into() - } - - /// Returns the Memory Increment config flag - pub fn minc(&self) -> Minc { - self.rb.cr.read().minc().bit().into() - } - - /// Returns the Peripheral Size - pub fn p_size(&self) -> PSize { - self.rb.cr.read().psize().bits().try_into().unwrap() - } - - /// Returns the Memory Size - pub fn m_size(&self) -> MSize { - self.rb.cr.read().msize().bits().try_into().unwrap() - } - - /// Returns the Peripheral Increment Offset - pub fn pincos(&self) -> Pincos { - self.rb.cr.read().pincos().bit().into() - } - - /// Returns the Priority Level - pub fn priority_level(&self) -> PriorityLevel { - self.rb.cr.read().pl().bits().try_into().unwrap() - } - - /// Returns the Buffer Mode - pub fn buffer_mode(&self) -> BufferMode { - self.rb.cr.read().dbm().bit().into() - } - - /// Returns the Current Target - pub fn current_target(&self) -> CurrentTarget { - self.rb.cr.read().ct().bit().into() - } - - /// Returns the Peripheral Burst config flag - pub fn p_burst(&self) -> PBurst { - self.rb.cr.read().pburst().bits().try_into().unwrap() - } - - /// Returns the Memory Burst config flag - pub fn m_burst(&self) -> MBurst { - self.rb.cr.read().mburst().bits().try_into().unwrap() - } - - /// Returns the content of the NDT register - pub fn ndt(&self) -> Ndt { - self.rb.ndtr.read().ndt().bits().into() - } - - /// Sets the content of the NDT register - pub fn configured_ndt(&self) -> Ndt { - self.config_ndt - } - - /// Returns the Peripheral Address - pub fn pa(&self) -> Pa { - self.rb.par.read().pa().bits().into() - } - - /// Returns the Memory-0 Address - pub fn m0a(&self) -> M0a { - self.rb.m0ar.read().m0a().bits().into() - } - - /// Returns the Memory-1 Address - pub fn m1a(&self) -> Option { - if self.buffer_mode() == BufferMode::DoubleBuffer { - Some(self.rb.m1ar.read().m1a().bits().into()) - } else { - None - } - } - - /// Returns the Fifo Threshold - pub fn fifo_threshold(&self) -> Option { - if self.transfer_mode() == TransferMode::Fifo { - Some(self.rb.fcr.read().fth().bits().try_into().unwrap()) - } else { - None - } - } - - /// Returns the Transfer Mode (`Direct` or `Fifo` Mode) - pub fn transfer_mode(&self) -> TransferMode { - self.rb.fcr.read().dmdis().bit().into() - } - - /// Performs the volatile write to the `M0a` register - fn impl_set_m0a(&mut self, m0a: M0a) { - self.rb.m0ar.modify(|_, w| w.m0a().bits(m0a.into())); - } - - /// Performs the volatile write to the `M1a` register - fn impl_set_m1a(&mut self, m1a: M1a) { - self.rb.m0ar.modify(|_, w| w.m0a().bits(m1a.into())); - } - - /// Transmutes the state of `self` - fn transmute(self) -> Stream - where - NewED: IED, - NewIsrState: IIsrState, - { - Stream { - rb: self.rb, - config_ndt: self.config_ndt, - _phantom_data: PhantomData, - } - } -} - -impl Stream -where - CXX: ChannelId, - IsrState: IIsrState, -{ - pub fn apply_config(&mut self, config: Config) { - self.set_transfer_complete_interrupt( - config.transfer_complete_interrupt, - ); - self.set_half_transfer_interrupt(config.half_transfer_interrupt); - self.set_transfer_error_interrupt(config.transfer_error_interrupt); - self.set_direct_mode_error_interrupt( - config.direct_mode_error_interrupt, - ); - self.set_fifo_error_interrupt(config.fifo_error_interrupt); - self.set_pinc(config.pinc()); - self.set_minc(config.minc); - self.set_priority_level(config.priority_level); - self.set_p_size(config.p_size); - self.set_ndt(config.ndt); - self.set_pa(config.pa); - self.set_m0a(config.m0a); - - self.set_transfer_direction(config.transfer_direction()); - self.set_transfer_mode(config.transfer_mode()); - self.set_flow_controller(config.flow_controller()); - self.set_circular_mode(config.circular_mode()); - self.set_buffer_mode(config.buffer_mode()); - - if let Some(fifo_threshold) = config.fifo_threshold() { - self.set_fifo_threshold(fifo_threshold); - } - self.set_p_burst(config.p_burst()); - self.set_m_burst(config.m_burst()); - self.set_m_size(config.m_size()); - - if let Some(pincos) = config.pincos() { - self.set_pincos(pincos); - } - - self.set_current_target(config.current_target()); - if let Some(m1a) = config.m1a() { - self.set_m1a(m1a); - } - } - - /// Sets the Flow Controller - fn set_flow_controller(&mut self, flow_controller: FlowController) { - self.rb - .cr - .modify(|_, w| w.pfctrl().bit(flow_controller.into())); - } - - /// Sets the Transfer Direction - fn set_transfer_direction(&mut self, transfer_dir: TransferDirection) { - unsafe { - self.rb.cr.modify(|_, w| w.dir().bits(transfer_dir.into())); - } - } - - /// Sets the Circular Mode - fn set_circular_mode(&mut self, circ_mode: CircularMode) { - self.rb.cr.modify(|_, w| w.circ().bit(circ_mode.into())); - } - - /// Sets the Peripheral Increment config flag - fn set_pinc(&mut self, pinc: Pinc) { - self.rb.cr.modify(|_, w| w.pinc().bit(pinc.into())); - } - - /// Sets the Memory Increment config flag - fn set_minc(&mut self, minc: Minc) { - self.rb.cr.modify(|_, w| w.minc().bit(minc.into())); - } - - /// Sets the Peripheral Size - fn set_p_size(&mut self, p_size: PSize) { - unsafe { - self.rb.cr.modify(|_, w| w.psize().bits(p_size.into())); - } - } - - /// Sets the Memory Size - fn set_m_size(&mut self, m_size: MSize) { - unsafe { - self.rb.cr.modify(|_, w| w.msize().bits(m_size.into())); - } - } - - /// Sets the Peripheral Increment Offset - fn set_pincos(&mut self, pincos: Pincos) { - self.rb.cr.modify(|_, w| w.pincos().bit(pincos.into())); - } - - /// Sets the Priority Level - fn set_priority_level(&mut self, priority_level: PriorityLevel) { - self.rb.cr.modify(|_, w| w.pl().bits(priority_level.into())); - } - - /// Sets the Buffer Mode (`Direct` or `Fifo` mode) - fn set_buffer_mode(&mut self, buffer_mode: BufferMode) { - self.rb.cr.modify(|_, w| w.dbm().bit(buffer_mode.into())); - } - - /// Sets the Current Target - fn set_current_target(&mut self, current_target: CurrentTarget) { - self.rb.cr.modify(|_, w| w.ct().bit(current_target.into())); - } - - /// Sets the Peripheral Burst - fn set_p_burst(&mut self, p_burst: PBurst) { - self.rb.cr.modify(|_, w| w.pburst().bits(p_burst.into())); - } - - /// Sets the Memory Burst - fn set_m_burst(&mut self, m_burst: MBurst) { - self.rb.cr.modify(|_, w| w.mburst().bits(m_burst.into())); - } - - /// Sets the NDT register - fn set_ndt(&mut self, ndt: Ndt) { - self.config_ndt = ndt; - - self.rb.ndtr.modify(|_, w| w.ndt().bits(ndt.into())); - } - - /// Sets the Peripheral Address - fn set_pa(&mut self, pa: Pa) { - self.rb.par.modify(|_, w| w.pa().bits(pa.into())); - } - - /// Sets the Memory-0 Address - fn set_m0a(&mut self, m0a: M0a) { - self.impl_set_m0a(m0a); - } - - /// Sets the Memory-1 Address - fn set_m1a(&mut self, m1a: M1a) { - self.impl_set_m1a(m1a); - } - - /// Sets the Fifo Threshold - fn set_fifo_threshold(&mut self, fifo_threshold: FifoThreshold) { - self.rb - .fcr - .modify(|_, w| w.fth().bits(fifo_threshold.into())); - } - - /// Sets the Transfer Mode - fn set_transfer_mode(&mut self, transfer_mode: TransferMode) { - self.rb - .fcr - .modify(|_, w| w.dmdis().bit(transfer_mode.into())); - } -} - -impl Stream -where - CXX: ChannelId, - IsrState: IIsrState, -{ - /// Sets the Memory-0 Address on the fly - /// - /// # Panic - /// - /// This panics if the stream is not in Double Buffer Mode. - pub fn set_m0a(&mut self, m0a: M0a) -> nb::Result<(), Infallible> { - self.check_double_buffer(); - - if self.current_target() == CurrentTarget::M0a && self.is_enabled() { - return Err(NbError::WouldBlock); - } - - self.impl_set_m0a(m0a); - - Ok(()) - } - - /// Sets the Memory-1 Address on the fly - /// - /// # Panic - /// - /// This panics if the stream is not in Double Buffer Mode. - pub fn set_m1a(&mut self, m1a: M1a) -> nb::Result<(), Infallible> { - self.check_double_buffer(); - - if self.current_target() == CurrentTarget::M1a && self.is_enabled() { - return Err(NbError::WouldBlock); - } - - self.impl_set_m1a(m1a); - - Ok(()) - } - - /// Checks if the stream is in Double Buffer Mode - fn check_double_buffer(&self) { - if self.buffer_mode() == BufferMode::Regular { - panic!("The buffer must be in double buffer mode to be changed on the fly."); - } - } -} - -impl Stream -where - CXX: ChannelId, -{ - /// Checks the config for data integrity and enables the stream - /// - /// # Safety - /// - /// Aliasing rules aren't enforced. - pub unsafe fn enable(self) -> Stream { - self.check_config(); - - self.enable_unchecked() - } - - /// Enables the stream without checking the config - /// - /// Consider using the checked version instead (`enable`). - /// - /// # Safety - /// - /// - Aliasing rules aren't enforced - /// - Config is not checked for guaranteeing data integrity - pub unsafe fn enable_unchecked(self) -> Stream { - self.rb.cr.modify(|_, w| w.en().set_bit()); - - self.transmute() - } - - /// Checks the config for data integrity - fn check_config(&self) { - if self.circular_mode() == CircularMode::Enabled { - self.check_config_circular(); - } - - if self.transfer_mode() == TransferMode::Fifo { - self.check_config_fifo(); - } - - self.check_ndt(); - } - - /// Checks the circular config. - // - // Reference: RM0433 Rev 6 - Chapter 15.3.10 - fn check_config_circular(&self) { - // Check for clashing config values - if self.transfer_direction() == TransferDirection::M2M - || self.flow_controller() == FlowController::Peripheral - { - panic!("For circular streams, the transfer direction must not be `M2M` and the FlowController must not be `Peripheral`."); - } - - // Check invariants - if self.transfer_mode() == TransferMode::Fifo { - let ndt = self.ndt().value() as usize; - let m_burst = self.m_burst().into_num(); - let p_burst = self.p_burst().into_num(); - let m_size = self.m_size().into_num(); - let p_size = self.p_size().into_num(); - - if self.m_burst() != MBurst::Single - && ndt % (m_burst * m_size / p_size) != 0 - { - panic!( - "Data integrity not guaranteed, because \ - `num_data_items != Multiple of (m_burst * (m_size / p_size))`" - ); - } - - if ndt % (p_burst * p_size) != 0 { - panic!( - "Data integrity not guaranteed, because \ - `num_data_items != Multiple of (p_burst * p_size)`" - ); - } - } else { - let ndt = self.ndt().value() as usize; - let p_size = self.p_size().into_num(); - - if ndt % p_size != 0 { - panic!( - "Data integrity not guaranteed, because \ - `num_data_items != Multiple of (p_size)`" - ); - } - } - } - - /// Checks the fifo config. - fn check_config_fifo(&self) { - if self.m_burst() != MBurst::Single { - self.check_config_fifo_m_burst(); - } - - if self.p_burst() != PBurst::Single { - self.check_config_fifo_p_burst(); - } - } - - /// Checks the memory config of fifo stream. - // - // Reference: RM0433 Rev 6 - Chapter 15.3.14 - fn check_config_fifo_m_burst(&self) { - let m_size = self.m_size().into_num(); - let m_burst = self.m_burst().into_num(); - // Fifo Size in bytes - let fifo_size = self.fifo_threshold().unwrap().into_num() * 4; - - if m_size * m_burst > fifo_size { - panic!("FIFO configuration invalid, because `msize * mburst > fifo_size`"); - } - - if fifo_size % (m_size * m_burst) != 0 { - panic!("FIFO configuration invalid, because `fifo_size % (msize * mburst) != 0`"); - } - } - - /// Checks the peripheral config of fifio stream. - // - // Reference: RM0433 Rev 6 - Chapter 15.3.14 - fn check_config_fifo_p_burst(&self) { - let p_burst = self.p_burst().into_num(); - let p_size = self.p_size().into_num(); - // 4 Words = 16 Bytes - const FULL_FIFO_BYTES: usize = 16; - - if p_burst * p_size == FULL_FIFO_BYTES - && self.fifo_threshold().unwrap() == FifoThreshold::F3_4 - { - panic!( - "FIFO configuration invalid, because \ - `pburst * psize == FULL_FIFO_SIZE` and \ - `fifo_threshhold == 3/4`" - ); - } - } - - /// Checks the NDT register - // - // Reference: RM0433 Rev 6 - Chapter 15.3.12 - fn check_ndt(&self) { - let m_size = self.m_size().into_num(); - let p_size = self.p_size().into_num(); - let ndt = self.config_ndt.value() as usize; - - if m_size > p_size && ndt % (m_size / p_size) != 0 { - panic!("`NDT` must be a multiple of (`m_size / p_size`)."); - } - } -} - -impl Stream -where - CXX: ChannelId, - IsrState: IIsrState, -{ - /// Disables the stream - pub fn disable(self) -> Stream { - self.rb.cr.modify(|_, w| w.en().clear_bit()); - - while self.rb.cr.read().en().bit_is_set() {} - - self.transmute() - } -} - -impl Stream -where - CXX: ChannelId, - ED: IED, -{ - /// Returns the contents of the isr. - /// - /// * If there is no error, an optional event is returned as `Ok` - /// * If there are errors, the errors are being wrapped into `Error` and returned as `Err` - pub fn check_isr( - &self, - isr: &StreamIsr, - ) -> Result, Error> { - let transfer_error = self.transfer_error_flag(isr); - let direct_mode_error = self.direct_mode_error_flag(isr); - let fifo_error = self.fifo_error_flag(isr); - - let event = if self.transfer_complete_flag(isr) { - Some(Event::TransferComplete) - } else if self.half_transfer_flag(isr) { - Some(Event::HalfTransfer) - } else { - None - }; - - let crashed = !self.is_enabled() && self.ndt().value() != 0; - - if transfer_error || direct_mode_error || fifo_error { - Err(Error { - transfer_error, - direct_mode_error, - fifo_error, - event, - crashed, - }) - } else { - Ok(event) - } - } - - /// Returns the Transfer Complete flag - pub fn transfer_complete_flag(&self, isr: &StreamIsr) -> bool { - match self.id() { - 0 => isr.lisr.read().tcif0().bit_is_set(), - 1 => isr.lisr.read().tcif1().bit_is_set(), - 2 => isr.lisr.read().tcif2().bit_is_set(), - 3 => isr.lisr.read().tcif3().bit_is_set(), - 4 => isr.hisr.read().tcif4().bit_is_set(), - 5 => isr.hisr.read().tcif5().bit_is_set(), - 6 => isr.hisr.read().tcif6().bit_is_set(), - 7 => isr.hisr.read().tcif7().bit_is_set(), - _ => unreachable!(), - } - } - - /// Returns the Half Transfer flag - pub fn half_transfer_flag(&self, isr: &StreamIsr) -> bool { - match self.id() { - 0 => isr.lisr.read().htif0().bit_is_set(), - 1 => isr.lisr.read().htif1().bit_is_set(), - 2 => isr.lisr.read().htif2().bit_is_set(), - 3 => isr.lisr.read().htif3().bit_is_set(), - 4 => isr.hisr.read().htif4().bit_is_set(), - 5 => isr.hisr.read().htif5().bit_is_set(), - 6 => isr.hisr.read().htif6().bit_is_set(), - 7 => isr.hisr.read().htif7().bit_is_set(), - _ => unreachable!(), - } - } - - /// Returns the Transfer Error flag - pub fn transfer_error_flag(&self, isr: &StreamIsr) -> bool { - match self.id() { - 0 => isr.lisr.read().teif0().bit_is_set(), - 1 => isr.lisr.read().teif1().bit_is_set(), - 2 => isr.lisr.read().teif2().bit_is_set(), - 3 => isr.lisr.read().teif3().bit_is_set(), - 4 => isr.hisr.read().teif4().bit_is_set(), - 5 => isr.hisr.read().teif5().bit_is_set(), - 6 => isr.hisr.read().teif6().bit_is_set(), - 7 => isr.hisr.read().teif7().bit_is_set(), - _ => unreachable!(), - } - } - - /// Returns the Direct Mode Error flag - pub fn direct_mode_error_flag(&self, isr: &StreamIsr) -> bool { - match self.id() { - 0 => isr.lisr.read().dmeif0().bit_is_set(), - 1 => isr.lisr.read().dmeif1().bit_is_set(), - 2 => isr.lisr.read().dmeif2().bit_is_set(), - 3 => isr.lisr.read().dmeif3().bit_is_set(), - 4 => isr.hisr.read().dmeif4().bit_is_set(), - 5 => isr.hisr.read().dmeif5().bit_is_set(), - 6 => isr.hisr.read().dmeif6().bit_is_set(), - 7 => isr.hisr.read().dmeif7().bit_is_set(), - _ => unreachable!(), - } - } - - /// Returns the Fifo Error flag - pub fn fifo_error_flag(&self, isr: &StreamIsr) -> bool { - match self.id() { - 0 => isr.lisr.read().feif0().bit_is_set(), - 1 => isr.lisr.read().feif1().bit_is_set(), - 2 => isr.lisr.read().feif2().bit_is_set(), - 3 => isr.lisr.read().feif3().bit_is_set(), - 4 => isr.hisr.read().feif4().bit_is_set(), - 5 => isr.hisr.read().feif5().bit_is_set(), - 6 => isr.hisr.read().feif6().bit_is_set(), - 7 => isr.hisr.read().feif7().bit_is_set(), - _ => unreachable!(), - } - } - - /// Performs the ISR clear - fn clear_isr_impl(&self, isr: &mut StreamIsr) { - self.clear_transfer_complete(isr); - self.clear_half_transfer(isr); - self.clear_transfer_error(isr); - self.clear_direct_mode_error(isr); - self.clear_fifo_error(isr); - } - - /// Clears the Transfer Complete flag - pub fn clear_transfer_complete(&self, isr: &mut StreamIsr) { - match self.id() { - 0 => { - isr.lifcr.write(|w| w.ctcif0().set_bit()); - } - 1 => { - isr.lifcr.write(|w| w.ctcif1().set_bit()); - } - 2 => { - isr.lifcr.write(|w| w.ctcif2().set_bit()); - } - 3 => { - isr.lifcr.write(|w| w.ctcif3().set_bit()); - } - 4 => { - isr.hifcr.write(|w| w.ctcif4().set_bit()); - } - 5 => { - isr.hifcr.write(|w| w.ctcif5().set_bit()); - } - 6 => { - isr.hifcr.write(|w| w.ctcif6().set_bit()); - } - 7 => { - isr.hifcr.write(|w| w.ctcif7().set_bit()); - } - _ => unreachable!(), - } - } - - /// Clears the Half Transfer flag - pub fn clear_half_transfer(&self, isr: &mut StreamIsr) { - match self.id() { - 0 => { - isr.lifcr.write(|w| w.chtif0().set_bit()); - } - 1 => { - isr.lifcr.write(|w| w.chtif1().set_bit()); - } - 2 => { - isr.lifcr.write(|w| w.chtif2().set_bit()); - } - 3 => { - isr.lifcr.write(|w| w.chtif3().set_bit()); - } - 4 => { - isr.hifcr.write(|w| w.chtif4().set_bit()); - } - 5 => { - isr.hifcr.write(|w| w.chtif5().set_bit()); - } - 6 => { - isr.hifcr.write(|w| w.chtif6().set_bit()); - } - 7 => { - isr.hifcr.write(|w| w.chtif7().set_bit()); - } - _ => unreachable!(), - } - } - - /// Clears the Transfer Error flag - pub fn clear_transfer_error(&self, isr: &mut StreamIsr) { - match self.id() { - 0 => { - isr.lifcr.write(|w| w.cteif0().set_bit()); - } - 1 => { - isr.lifcr.write(|w| w.cteif1().set_bit()); - } - 2 => { - isr.lifcr.write(|w| w.cteif2().set_bit()); - } - 3 => { - isr.lifcr.write(|w| w.cteif3().set_bit()); - } - 4 => { - isr.hifcr.write(|w| w.cteif4().set_bit()); - } - 5 => { - isr.hifcr.write(|w| w.cteif5().set_bit()); - } - 6 => { - isr.hifcr.write(|w| w.cteif6().set_bit()); - } - 7 => { - isr.hifcr.write(|w| w.cteif7().set_bit()); - } - _ => unreachable!(), - } - } - - /// Clears the Direct Mode Error flag - pub fn clear_direct_mode_error(&self, isr: &mut StreamIsr) { - match self.id() { - 0 => { - isr.lifcr.write(|w| w.cdmeif0().set_bit()); - } - 1 => { - isr.lifcr.write(|w| w.cdmeif1().set_bit()); - } - 2 => { - isr.lifcr.write(|w| w.cdmeif2().set_bit()); - } - 3 => { - isr.lifcr.write(|w| w.cdmeif3().set_bit()); - } - 4 => { - isr.hifcr.write(|w| w.cdmeif4().set_bit()); - } - 5 => { - isr.hifcr.write(|w| w.cdmeif5().set_bit()); - } - 6 => { - isr.hifcr.write(|w| w.cdmeif6().set_bit()); - } - 7 => { - isr.hifcr.write(|w| w.cdmeif7().set_bit()); - } - _ => unreachable!(), - } - } - - /// Clears the Fifo Error flag - pub fn clear_fifo_error(&self, isr: &mut StreamIsr) { - match self.id() { - 0 => { - isr.lifcr.write(|w| w.cfeif0().set_bit()); - } - 1 => { - isr.lifcr.write(|w| w.cfeif1().set_bit()); - } - 2 => { - isr.lifcr.write(|w| w.cfeif2().set_bit()); - } - 3 => { - isr.lifcr.write(|w| w.cfeif3().set_bit()); - } - 4 => { - isr.hifcr.write(|w| w.cfeif4().set_bit()); - } - 5 => { - isr.hifcr.write(|w| w.cfeif5().set_bit()); - } - 6 => { - isr.hifcr.write(|w| w.cfeif6().set_bit()); - } - 7 => { - isr.hifcr.write(|w| w.cfeif7().set_bit()); - } - _ => unreachable!(), - } - } -} - -impl Stream -where - CXX: ChannelId, -{ - /// Clears the ISR - pub fn clear_isr( - self, - isr: &mut StreamIsr, - ) -> Stream { - self.clear_isr_impl(isr); - - self.transmute() - } -} - -impl Stream -where - CXX: ChannelId, -{ - /// Clears the ISR - pub fn clear_isr(&self, isr: &mut StreamIsr) { - self.clear_isr_impl(isr); - } - - pub fn wait_until_completed( - &self, - isr: &StreamIsr, - ) -> nb::Result<(), Error> { - match self.check_isr(isr) { - Ok(Some(Event::TransferComplete)) => Ok(()), - Err(err) => Err(NbError::Other(err)), - _ => Err(NbError::WouldBlock), - } - } - - pub fn wait_until_completed_clear( - &self, - isr: &mut StreamIsr, - ) -> nb::Result<(), Error> { - let res = self.wait_until_completed(isr); - - self.clear_isr_if_not_blocking(res, isr); - - res - } - - pub fn wait_until_half_transfer( - &self, - isr: &StreamIsr, - ) -> nb::Result<(), Error> { - match self.check_isr(isr) { - Ok(Some(Event::HalfTransfer)) => Ok(()), - Err(err) => Err(NbError::Other(err)), - _ => Err(NbError::WouldBlock), - } - } +use self::stream::{Disabled, IIsrState, IsrCleared, StreamIsr, IED}; +use crate::private; +use crate::rcc::Ccdr; +use crate::stm32::{dma1, dmamux1, DMA1, DMA2, RCC}; +use stm32h7::stm32h743::DMAMUX1; - pub fn wait_until_half_transfer_clear( - &self, - isr: &mut StreamIsr, - ) -> nb::Result<(), Error> { - let res = self.wait_until_half_transfer(isr); +pub use self::mux::Mux; +pub use self::stream::Stream; +pub use self::transfer::Transfer; - self.clear_isr_if_not_blocking(res, isr); +/// Marker Trait for DMA peripherals +pub trait DmaPeripheral: private::Sealed {} +impl DmaPeripheral for DMA1 {} +impl DmaPeripheral for DMA2 {} - res - } +pub trait ChannelId: Send + private::Sealed { + const STREAM_ID: usize; + const MUX_ID: usize; - pub fn wait_until_next_half( - &self, - isr: &StreamIsr, - ) -> nb::Result<(), Error> { - match self.check_isr(isr) { - Ok(event) => match event { - Some(Event::HalfTransfer) | Some(Event::TransferComplete) => { - Ok(()) - } - None => Err(NbError::WouldBlock), - }, - Err(err) => Err(NbError::Other(err)), - } - } + type DMA: DmaPeripheral; +} - pub fn wait_until_next_half_clear( - &self, - isr: &mut StreamIsr, - ) -> nb::Result<(), Error> { - let res = self.wait_until_next_half(isr); +macro_rules! channels { + ($($channel:ident => [$stream:tt, $mux:tt, $dma:ident]),*) => { + $( + pub struct $channel; - self.clear_isr_if_not_blocking(res, isr); + impl crate::private::Sealed for $channel {} - res - } + impl ChannelId for $channel { + const STREAM_ID: usize = $stream; + const MUX_ID: usize = $mux; - fn clear_isr_if_not_blocking( - &self, - res: nb::Result<(), Error>, - isr: &mut StreamIsr, - ) { - if !matches!(res, Err(NbError::WouldBlock)) { - self.clear_isr(isr); - } - } + type DMA = $dma; + } + )* + }; } -unsafe impl Send for Stream -where - CXX: ChannelId, - ED: IED, - IsrState: IIsrState, -{ +channels! { + C0 => [0, 0, DMA1], + C1 => [1, 1, DMA1], + C2 => [2, 2, DMA1], + C3 => [3, 3, DMA1], + C4 => [4, 4, DMA1], + C5 => [5, 5, DMA1], + C6 => [6, 6, DMA1], + C7 => [7, 7, DMA1], + C8 => [0, 8, DMA2], + C9 => [1, 9, DMA2], + C10 => [2, 10, DMA2], + C11 => [3, 11, DMA2], + C12 => [4, 12, DMA2], + C13 => [5, 13, DMA2], + C14 => [6, 14, DMA2], + C15 => [7, 15, DMA2] } -unsafe impl Sync for Stream +/// DMA Channel +pub struct Channel where CXX: ChannelId, - ED: IED, + StreamED: IED, IsrState: IIsrState, -{ -} - -/// DMA Mux -pub struct DmaMux -where - CXX: ChannelId, ReqId: IRequestId, SyncED: ISyncED, EgED: IEgED, { - /// This field *must not* be mutated using shared references - rb: &'static CCR, - req_id: ReqId, - _phantom_data: PhantomData<(CXX, SyncED, EgED)>, -} - -impl DmaMux -where - CXX: ChannelId, -{ - /// Creates an instance of a DMA Mux in initial state. - /// - /// Should only be called after RCC-reset of the DMA. - fn after_reset(rb: &'static CCR) -> Self { - DmaMux { - rb, - req_id: ReqNone, - _phantom_data: PhantomData, - } - } + pub stream: Stream, + pub mux: Mux, } -impl DmaMux +impl + Channel where CXX: ChannelId, + StreamED: IED, + IsrState: IIsrState, ReqId: IRequestId, SyncED: ISyncED, EgED: IEgED, { - /// Returns the id of the DMA Mux - pub fn id(&self) -> usize { - CXX::MUX_ID - } - - /// Returns the request id assigned to this Mux - pub fn request_id(&self) -> RequestId { - debug_assert_eq!( - ReqId::REQUEST_ID, - RequestId::try_from(self.rb.read().dmareq_id().bits()).unwrap(), - "DmaMux is in invalid state, because \ - `ReqId::REQUEST_ID` ({:?}) != Volatile request id ({:?})", - ReqId::REQUEST_ID, - RequestId::try_from(self.rb.read().dmareq_id().bits()).unwrap(), - ); - - ReqId::REQUEST_ID - } - - /// Returns the Sync Overrun Interrupt config flag - pub fn sync_overrun_interrupt(&self) -> SyncOverrunInterrupt { - self.rb.read().soie().bit().into() - } - - /// Sets the Sync Overrun Interrupt config flag - pub fn set_sync_overrun_interrupt( - &mut self, - sync_overrun_intrpt: SyncOverrunInterrupt, - ) { - self.rb - .modify(|_, w| w.soie().bit(sync_overrun_intrpt.into())); - } - - /// Returns the Synchronization Polarity - pub fn sync_polarity(&self) -> SyncPolarity { - self.rb.read().spol().bits().try_into().unwrap() - } - - /// Sets the Synchronization Polarity - pub fn set_sync_polarity(&mut self, sync_polarity: SyncPolarity) { - self.rb.modify(|_, w| w.spol().bits(sync_polarity.into())); - } - - /// Returns the number of requests - pub fn nbreq(&self) -> NbReq { - self.rb.read().nbreq().bits().try_into().unwrap() - } - - /// Returns the Synchronization ID - pub fn sync_id(&self) -> SyncId { - self.rb.read().sync_id().bits().try_into().unwrap() - } - - /// Sets the Synchronization ID - pub fn set_sync_id(&mut self, sync_id: SyncId) { - unsafe { - self.rb.modify(|_, w| w.sync_id().bits(sync_id.into())); - } - } - - /// Performs the request id write - fn set_req_id_impl(&mut self, request_id: RequestId) { - unsafe { - self.rb.modify(|_, w| w.dmareq_id().bits(request_id.into())); - } - } - - /// Transmutes the state of the DMA Mux - fn transmute( + /// Exposes the stream as owned value in a closure + pub fn stream_owned( self, - ) -> DmaMux - where - NewSyncED: ISyncED, - NewEgED: IEgED, - { - DmaMux { - rb: self.rb, - req_id: self.req_id, - _phantom_data: PhantomData, - } - } -} - -impl DmaMux -where - CXX: ChannelId, - ReqId: IRequestId, -{ - /// Sets the number of requests - pub fn set_nbreq(&mut self, nbreq: NbReq) { - self.rb.modify(|_, w| w.nbreq().bits(nbreq.into())); - } -} - -impl DmaMux -where - CXX: ChannelId, - ReqId: IRequestId, - EgED: IEgED, -{ - /// Enables synchronization - pub fn enable_sync(self) -> DmaMux { - self.rb.modify(|_, w| w.se().set_bit()); - - self.transmute() - } -} - -impl DmaMux -where - CXX: ChannelId, - ReqId: IRequestId, - EgED: IEgED, -{ - /// Disables synchronization - pub fn disable_sync(self) -> DmaMux { - self.rb.modify(|_, w| w.se().clear_bit()); - - self.transmute() - } -} - -impl DmaMux -where - CXX: ChannelId, - ReqId: IRequestId, - SyncED: ISyncED, -{ - /// Enables event generation - pub fn enable_event_gen(self) -> DmaMux { - self.rb.modify(|_, w| w.ege().set_bit()); - - self.transmute() - } -} - -impl DmaMux -where - CXX: ChannelId, - ReqId: IRequestId, - SyncED: ISyncED, -{ - /// Disables event generation - pub fn disable_event_gen(self) -> DmaMux { - self.rb.modify(|_, w| w.ege().clear_bit()); - - self.transmute() - } -} - -impl DmaMux -where - CXX: ChannelId, - SyncED: ISyncED, - EgED: IEgED, -{ - /// Sets request id - pub fn set_req_id( - mut self, - req_id: NewReqId, - ) -> DmaMux + op: F, + ) -> Channel where - NewReqId: RequestIdSome, + F: FnOnce( + Stream, + ) -> Stream, + NewStreamED: IED, + NewIsrState: IIsrState, { - self.set_req_id_impl(NewReqId::REQUEST_ID); + let new_stream = op(self.stream); - DmaMux { - req_id, - rb: self.rb, - _phantom_data: PhantomData, + Channel { + stream: new_stream, + mux: self.mux, } } -} - -impl DmaMux -where - CXX: ChannelId, - ReqId: RequestIdSome, - SyncED: ISyncED, - EgED: IEgED, -{ - /// Unsets request id, defaulting to `ReqNone` and returning the old one - pub fn unset_req_id( - mut self, - ) -> (DmaMux, ReqId) { - self.set_req_id_impl(ReqNone::REQUEST_ID); - - let old_req_id = self.req_id; - let new_dma_mux = DmaMux { - rb: self.rb, - req_id: ReqNone, - _phantom_data: PhantomData, - }; - - (new_dma_mux, old_req_id) - } - /// Replaces the request id - pub fn replace_req_id( - mut self, - req_id: NewReqId, - ) -> (DmaMux, ReqId) + /// Exposes the mux as owned value in a closure + pub fn mux_owned( + self, + op: F, + ) -> Channel where - NewReqId: RequestIdSome, + F: FnOnce( + Mux, + ) -> Mux, + NewReqId: IRequestId, + NewSyncED: ISyncED, + NewEgED: IEgED, { - self.set_req_id_impl(NewReqId::REQUEST_ID); - - let old_req_id = self.req_id; - let new_dma_mux = DmaMux { - req_id, - rb: self.rb, - _phantom_data: PhantomData, - }; - - (new_dma_mux, old_req_id) - } -} - -impl DmaMux -where - CXX: ChannelId, - ReqId: IRequestId, - SyncED: ISyncED, - EgED: IEgED, -{ - /// Checks the ISR for errors - pub fn check_isr(&self, mux_isr: &MuxIsr) -> Result<(), OverrunError> { - if self.is_sync_overrun(mux_isr) { - Err(OverrunError) - } else { - Ok(()) - } - } - - /// Returns the Sync Overrun flag - pub fn is_sync_overrun(&self, mux_isr: &MuxIsr) -> bool { - mux_isr.csr.read().sof0().bit_is_set() - } - - /// Clears the ISR - pub fn clear_isr(&self, mux_isr: &mut MuxIsr) { - match self.id() { - 0 => mux_isr.cfr.write(|w| w.csof0().set_bit()), - 1 => mux_isr.cfr.write(|w| w.csof1().set_bit()), - 2 => mux_isr.cfr.write(|w| w.csof2().set_bit()), - 3 => mux_isr.cfr.write(|w| w.csof3().set_bit()), - 4 => mux_isr.cfr.write(|w| w.csof4().set_bit()), - 5 => mux_isr.cfr.write(|w| w.csof5().set_bit()), - 6 => mux_isr.cfr.write(|w| w.csof6().set_bit()), - 7 => mux_isr.cfr.write(|w| w.csof7().set_bit()), - 8 => mux_isr.cfr.write(|w| w.csof8().set_bit()), - 9 => mux_isr.cfr.write(|w| w.csof9().set_bit()), - 10 => mux_isr.cfr.write(|w| w.csof10().set_bit()), - 11 => mux_isr.cfr.write(|w| w.csof11().set_bit()), - 12 => mux_isr.cfr.write(|w| w.csof12().set_bit()), - 13 => mux_isr.cfr.write(|w| w.csof13().set_bit()), - 14 => mux_isr.cfr.write(|w| w.csof14().set_bit()), - 15 => mux_isr.cfr.write(|w| w.csof15().set_bit()), - _ => unreachable!(), - } - } -} - -unsafe impl Send for DmaMux -where - CXX: ChannelId, - ReqId: IRequestId, - SyncED: ISyncED, - EgED: IEgED, -{ -} - -unsafe impl Sync for DmaMux -where - CXX: ChannelId, - ReqId: IRequestId, - SyncED: ISyncED, - EgED: IEgED, -{ -} - -pub struct Transfer<'wo, State: TransferState<'wo>> { - state: State, - _phantom: PhantomData<&'wo ()>, -} - -impl<'wo, Peripheral, Memory> Transfer<'wo, Start<'wo, Peripheral, Memory>> -where - Peripheral: Payload, - Memory: Payload, -{ - pub fn new(conf: TransferConfig<'wo, Peripheral, Memory>) -> Self { - Self { - state: Start { conf }, - _phantom: PhantomData, - } - } - - pub fn start( - self, - mut stream: Stream, - ) -> Transfer<'wo, Ongoing<'wo, Peripheral, Memory, CXX>> { - self.configure_stream(&mut stream); + let new_mux = op(self.mux); - Transfer { - state: Ongoing { - stream: unsafe { stream.enable() }, - buffers: self.state.conf.free().free(), - }, - _phantom: PhantomData, + Channel { + stream: self.stream, + mux: new_mux, } } - - fn configure_stream( - &self, - stream: &mut Stream, - ) { - let mut conf = stream.config(); - - self.state.conf.stream_config(&mut conf); - - stream.apply_config(conf); - } } pub type ChannelsDma1 = ( @@ -1711,29 +214,29 @@ impl Dma { Dma::reset_mux(&mut dma_mux); - let dma1_rb = unsafe { &*DMA1::ptr() }; - let dma2_rb = unsafe { &*DMA2::ptr() }; - let dma_mux_rb = unsafe { &*DMAMUX1::ptr() }; + let dma1_rb: &mut dma1::RegisterBlock = + unsafe { &mut *(DMA1::ptr() as *mut _) }; + let dma2_rb: &mut dma1::RegisterBlock = + unsafe { &mut *(DMA2::ptr() as *mut _) }; + let dma_mux_rb: &mut dmamux1::RegisterBlock = + unsafe { &mut *(DMAMUX1::ptr() as *mut _) }; let stream_isr_dma_1 = StreamIsr::new( &dma1_rb.lisr, &dma1_rb.hisr, - &dma1_rb.lifcr, - &dma1_rb.hifcr, + &mut dma1_rb.lifcr, + &mut dma1_rb.hifcr, ); let stream_isr_dma_2 = StreamIsr::new( &dma2_rb.lisr, &dma2_rb.hisr, - &dma2_rb.lifcr, - &dma2_rb.hifcr, + &mut dma2_rb.lifcr, + &mut dma2_rb.hifcr, ); - let mux_isr = MuxIsr { - csr: &dma_mux_rb.csr, - cfr: &dma_mux_rb.cfr, - }; + let mux_isr = MuxIsr::new(&dma_mux_rb.csr, &mut dma_mux_rb.cfr); let req_gen_isr = - RequestGenIsr::new(&dma_mux_rb.rgsr, &dma_mux_rb.rgcfr); + RequestGenIsr::new(&dma_mux_rb.rgsr, &mut dma_mux_rb.rgcfr); let mux_shared = MuxShared::new(mux_isr, req_gen_isr); let dma_shared = DmaShared { @@ -1742,86 +245,172 @@ impl Dma { mux_shared, }; - let channels_dma_1 = ( - Channel { - stream: Stream::after_reset(&dma1_rb.st[0]), - mux: DmaMux::after_reset(&dma_mux_rb.ccr[0]), - }, - Channel { - stream: Stream::after_reset(&dma1_rb.st[1]), - mux: DmaMux::after_reset(&dma_mux_rb.ccr[1]), - }, - Channel { - stream: Stream::after_reset(&dma1_rb.st[2]), - mux: DmaMux::after_reset(&dma_mux_rb.ccr[2]), - }, - Channel { - stream: Stream::after_reset(&dma1_rb.st[3]), - mux: DmaMux::after_reset(&dma_mux_rb.ccr[3]), - }, - Channel { - stream: Stream::after_reset(&dma1_rb.st[4]), - mux: DmaMux::after_reset(&dma_mux_rb.ccr[4]), - }, - Channel { - stream: Stream::after_reset(&dma1_rb.st[5]), - mux: DmaMux::after_reset(&dma_mux_rb.ccr[5]), - }, - Channel { - stream: Stream::after_reset(&dma1_rb.st[6]), - mux: DmaMux::after_reset(&dma_mux_rb.ccr[6]), - }, - Channel { - stream: Stream::after_reset(&dma1_rb.st[7]), - mux: DmaMux::after_reset(&dma_mux_rb.ccr[7]), - }, - ); + let channels_dma_1 = unsafe { + ( + Channel { + stream: Stream::after_reset( + &mut *(&mut dma1_rb.st[0] as *mut _), + ), + mux: Mux::after_reset( + &mut *(&mut dma_mux_rb.ccr[0] as *mut _), + ), + }, + Channel { + stream: Stream::after_reset( + &mut *(&mut dma1_rb.st[1] as *mut _), + ), + mux: Mux::after_reset( + &mut *(&mut dma_mux_rb.ccr[1] as *mut _), + ), + }, + Channel { + stream: Stream::after_reset( + &mut *(&mut dma1_rb.st[2] as *mut _), + ), + mux: Mux::after_reset( + &mut *(&mut dma_mux_rb.ccr[2] as *mut _), + ), + }, + Channel { + stream: Stream::after_reset( + &mut *(&mut dma1_rb.st[3] as *mut _), + ), + mux: Mux::after_reset( + &mut *(&mut dma_mux_rb.ccr[3] as *mut _), + ), + }, + Channel { + stream: Stream::after_reset( + &mut *(&mut dma1_rb.st[4] as *mut _), + ), + mux: Mux::after_reset( + &mut *(&mut dma_mux_rb.ccr[4] as *mut _), + ), + }, + Channel { + stream: Stream::after_reset( + &mut *(&mut dma1_rb.st[5] as *mut _), + ), + mux: Mux::after_reset( + &mut *(&mut dma_mux_rb.ccr[5] as *mut _), + ), + }, + Channel { + stream: Stream::after_reset( + &mut *(&mut dma1_rb.st[6] as *mut _), + ), + mux: Mux::after_reset( + &mut *(&mut dma_mux_rb.ccr[6] as *mut _), + ), + }, + Channel { + stream: Stream::after_reset( + &mut *(&mut dma1_rb.st[7] as *mut _), + ), + mux: Mux::after_reset( + &mut *(&mut dma_mux_rb.ccr[7] as *mut _), + ), + }, + ) + }; - let channels_dma_2 = ( - Channel { - stream: Stream::after_reset(&dma2_rb.st[0]), - mux: DmaMux::after_reset(&dma_mux_rb.ccr[8]), - }, - Channel { - stream: Stream::after_reset(&dma2_rb.st[1]), - mux: DmaMux::after_reset(&dma_mux_rb.ccr[9]), - }, - Channel { - stream: Stream::after_reset(&dma2_rb.st[2]), - mux: DmaMux::after_reset(&dma_mux_rb.ccr[10]), - }, - Channel { - stream: Stream::after_reset(&dma2_rb.st[3]), - mux: DmaMux::after_reset(&dma_mux_rb.ccr[11]), - }, - Channel { - stream: Stream::after_reset(&dma2_rb.st[4]), - mux: DmaMux::after_reset(&dma_mux_rb.ccr[12]), - }, - Channel { - stream: Stream::after_reset(&dma2_rb.st[5]), - mux: DmaMux::after_reset(&dma_mux_rb.ccr[13]), - }, - Channel { - stream: Stream::after_reset(&dma2_rb.st[6]), - mux: DmaMux::after_reset(&dma_mux_rb.ccr[14]), - }, - Channel { - stream: Stream::after_reset(&dma2_rb.st[7]), - mux: DmaMux::after_reset(&dma_mux_rb.ccr[15]), - }, - ); + let channels_dma_2 = unsafe { + ( + Channel { + stream: Stream::after_reset( + &mut *(&mut dma2_rb.st[0] as *mut _), + ), + mux: Mux::after_reset( + &mut *(&mut dma_mux_rb.ccr[8] as *mut _), + ), + }, + Channel { + stream: Stream::after_reset( + &mut *(&mut dma2_rb.st[1] as *mut _), + ), + mux: Mux::after_reset( + &mut *(&mut dma_mux_rb.ccr[9] as *mut _), + ), + }, + Channel { + stream: Stream::after_reset( + &mut *(&mut dma2_rb.st[2] as *mut _), + ), + mux: Mux::after_reset( + &mut *(&mut dma_mux_rb.ccr[10] as *mut _), + ), + }, + Channel { + stream: Stream::after_reset( + &mut *(&mut dma2_rb.st[3] as *mut _), + ), + mux: Mux::after_reset( + &mut *(&mut dma_mux_rb.ccr[11] as *mut _), + ), + }, + Channel { + stream: Stream::after_reset( + &mut *(&mut dma2_rb.st[4] as *mut _), + ), + mux: Mux::after_reset( + &mut *(&mut dma_mux_rb.ccr[12] as *mut _), + ), + }, + Channel { + stream: Stream::after_reset( + &mut *(&mut dma2_rb.st[5] as *mut _), + ), + mux: Mux::after_reset( + &mut *(&mut dma_mux_rb.ccr[13] as *mut _), + ), + }, + Channel { + stream: Stream::after_reset( + &mut *(&mut dma2_rb.st[6] as *mut _), + ), + mux: Mux::after_reset( + &mut *(&mut dma_mux_rb.ccr[14] as *mut _), + ), + }, + Channel { + stream: Stream::after_reset( + &mut *(&mut dma2_rb.st[7] as *mut _), + ), + mux: Mux::after_reset( + &mut *(&mut dma_mux_rb.ccr[15] as *mut _), + ), + }, + ) + }; - let request_generators = ( - RequestGenerator::after_reset(&dma_mux_rb.rgcr[0]), - RequestGenerator::after_reset(&dma_mux_rb.rgcr[1]), - RequestGenerator::after_reset(&dma_mux_rb.rgcr[2]), - RequestGenerator::after_reset(&dma_mux_rb.rgcr[3]), - RequestGenerator::after_reset(&dma_mux_rb.rgcr[4]), - RequestGenerator::after_reset(&dma_mux_rb.rgcr[5]), - RequestGenerator::after_reset(&dma_mux_rb.rgcr[6]), - RequestGenerator::after_reset(&dma_mux_rb.rgcr[7]), - ); + let request_generators = unsafe { + ( + RequestGenerator::after_reset( + &mut *(&mut dma_mux_rb.rgcr[0] as *mut _), + ), + RequestGenerator::after_reset( + &mut *(&mut dma_mux_rb.rgcr[1] as *mut _), + ), + RequestGenerator::after_reset( + &mut *(&mut dma_mux_rb.rgcr[2] as *mut _), + ), + RequestGenerator::after_reset( + &mut *(&mut dma_mux_rb.rgcr[3] as *mut _), + ), + RequestGenerator::after_reset( + &mut *(&mut dma_mux_rb.rgcr[4] as *mut _), + ), + RequestGenerator::after_reset( + &mut *(&mut dma_mux_rb.rgcr[5] as *mut _), + ), + RequestGenerator::after_reset( + &mut *(&mut dma_mux_rb.rgcr[6] as *mut _), + ), + RequestGenerator::after_reset( + &mut *(&mut dma_mux_rb.rgcr[7] as *mut _), + ), + ) + }; Dma { channels_dma_1, diff --git a/src/dma/mux/mod.rs b/src/dma/mux/mod.rs index 2c67bfb5..1b889ea0 100644 --- a/src/dma/mux/mod.rs +++ b/src/dma/mux/mod.rs @@ -2,21 +2,337 @@ pub mod request_gen; -use self::request_gen::{ - Disabled as GenDisabled, Enabled as GenEnabled, GNbReq, GPol, GenId, - RequestGenIsr, SigId, TriggerOverrunError, TriggerOverrunInterrupt, - ED as GenED, -}; -use crate::stm32::dmamux1::{CFR, CSR, RGCR}; -use core::convert::TryInto; +use self::request_gen::RequestGenIsr; +use self::request_ids::{ReqNone, RequestId as IRequestId, RequestIdSome}; +use super::ChannelId; +use crate::stm32::dmamux1::{CCR, CFR, CSR}; +use core::convert::{TryFrom, TryInto}; use core::marker::PhantomData; +pub use self::request_gen::RequestGenerator; + +/// DMA Mux +pub struct Mux +where + CXX: ChannelId, + ReqId: IRequestId, + SyncED: ISyncED, + EgED: IEgED, +{ + /// This field *must not* be mutated using shared references + rb: &'static mut CCR, + req_id: ReqId, + _phantom_data: PhantomData<(CXX, SyncED, EgED)>, +} + +impl Mux +where + CXX: ChannelId, +{ + /// Creates an instance of a DMA Mux in initial state. + /// + /// Should only be called after RCC-reset of the DMA. + pub(super) fn after_reset(rb: &'static mut CCR) -> Self { + Mux { + rb, + req_id: ReqNone, + _phantom_data: PhantomData, + } + } +} + +impl Mux +where + CXX: ChannelId, + ReqId: IRequestId, + SyncED: ISyncED, + EgED: IEgED, +{ + /// Returns the id of the DMA Mux + pub fn id(&self) -> usize { + CXX::MUX_ID + } + + /// Returns the request id assigned to this Mux + pub fn request_id(&self) -> RequestId { + debug_assert_eq!( + ReqId::REQUEST_ID, + RequestId::try_from(self.rb.read().dmareq_id().bits()).unwrap(), + "DmaMux is in invalid state, because \ + `ReqId::REQUEST_ID` ({:?}) != Volatile request id ({:?})", + ReqId::REQUEST_ID, + RequestId::try_from(self.rb.read().dmareq_id().bits()).unwrap(), + ); + + ReqId::REQUEST_ID + } + + /// Returns the Sync Overrun Interrupt config flag + pub fn sync_overrun_interrupt(&self) -> SyncOverrunInterrupt { + self.rb.read().soie().bit().into() + } + + /// Sets the Sync Overrun Interrupt config flag + pub fn set_sync_overrun_interrupt( + &mut self, + sync_overrun_intrpt: SyncOverrunInterrupt, + ) { + self.rb + .modify(|_, w| w.soie().bit(sync_overrun_intrpt.into())); + } + + /// Returns the Synchronization Polarity + pub fn sync_polarity(&self) -> SyncPolarity { + self.rb.read().spol().bits().try_into().unwrap() + } + + /// Sets the Synchronization Polarity + pub fn set_sync_polarity(&mut self, sync_polarity: SyncPolarity) { + self.rb.modify(|_, w| w.spol().bits(sync_polarity.into())); + } + + /// Returns the number of requests + pub fn nbreq(&self) -> NbReq { + self.rb.read().nbreq().bits().try_into().unwrap() + } + + /// Returns the Synchronization ID + pub fn sync_id(&self) -> SyncId { + self.rb.read().sync_id().bits().try_into().unwrap() + } + + /// Sets the Synchronization ID + pub fn set_sync_id(&mut self, sync_id: SyncId) { + unsafe { + self.rb.modify(|_, w| w.sync_id().bits(sync_id.into())); + } + } + + /// Performs the request id write + fn set_req_id_impl(&mut self, request_id: RequestId) { + unsafe { + self.rb.modify(|_, w| w.dmareq_id().bits(request_id.into())); + } + } + + /// Transmutes the state of the DMA Mux + fn transmute( + self, + ) -> Mux + where + NewSyncED: ISyncED, + NewEgED: IEgED, + { + Mux { + rb: self.rb, + req_id: self.req_id, + _phantom_data: PhantomData, + } + } +} + +impl Mux +where + CXX: ChannelId, + ReqId: IRequestId, +{ + /// Sets the number of requests + pub fn set_nbreq(&mut self, nbreq: NbReq) { + self.rb.modify(|_, w| w.nbreq().bits(nbreq.into())); + } +} + +impl Mux +where + CXX: ChannelId, + ReqId: IRequestId, + EgED: IEgED, +{ + /// Enables synchronization + pub fn enable_sync(self) -> Mux { + self.rb.modify(|_, w| w.se().set_bit()); + + self.transmute() + } +} + +impl Mux +where + CXX: ChannelId, + ReqId: IRequestId, + EgED: IEgED, +{ + /// Disables synchronization + pub fn disable_sync(self) -> Mux { + self.rb.modify(|_, w| w.se().clear_bit()); + + self.transmute() + } +} + +impl Mux +where + CXX: ChannelId, + ReqId: IRequestId, + SyncED: ISyncED, +{ + /// Enables event generation + pub fn enable_event_gen(self) -> Mux { + self.rb.modify(|_, w| w.ege().set_bit()); + + self.transmute() + } +} + +impl Mux +where + CXX: ChannelId, + ReqId: IRequestId, + SyncED: ISyncED, +{ + /// Disables event generation + pub fn disable_event_gen(self) -> Mux { + self.rb.modify(|_, w| w.ege().clear_bit()); + + self.transmute() + } +} + +impl Mux +where + CXX: ChannelId, + SyncED: ISyncED, + EgED: IEgED, +{ + /// Sets request id + pub fn set_req_id( + mut self, + req_id: NewReqId, + ) -> Mux + where + NewReqId: RequestIdSome, + { + self.set_req_id_impl(NewReqId::REQUEST_ID); + + Mux { + req_id, + rb: self.rb, + _phantom_data: PhantomData, + } + } +} + +impl Mux +where + CXX: ChannelId, + ReqId: RequestIdSome, + SyncED: ISyncED, + EgED: IEgED, +{ + /// Unsets request id, defaulting to `ReqNone` and returning the old one + pub fn unset_req_id(mut self) -> (Mux, ReqId) { + self.set_req_id_impl(ReqNone::REQUEST_ID); + + let old_req_id = self.req_id; + let new_dma_mux = Mux { + rb: self.rb, + req_id: ReqNone, + _phantom_data: PhantomData, + }; + + (new_dma_mux, old_req_id) + } + + /// Replaces the request id + pub fn replace_req_id( + mut self, + req_id: NewReqId, + ) -> (Mux, ReqId) + where + NewReqId: RequestIdSome, + { + self.set_req_id_impl(NewReqId::REQUEST_ID); + + let old_req_id = self.req_id; + let new_dma_mux = Mux { + req_id, + rb: self.rb, + _phantom_data: PhantomData, + }; + + (new_dma_mux, old_req_id) + } +} + +impl Mux +where + CXX: ChannelId, + ReqId: IRequestId, + SyncED: ISyncED, + EgED: IEgED, +{ + /// Checks the ISR for errors + pub fn check_isr(&self, mux_isr: &MuxIsr) -> Result<(), OverrunError> { + if self.is_sync_overrun(mux_isr) { + Err(OverrunError) + } else { + Ok(()) + } + } + + /// Returns the Sync Overrun flag + pub fn is_sync_overrun(&self, mux_isr: &MuxIsr) -> bool { + mux_isr.csr.read().sof0().bit_is_set() + } + + /// Clears the ISR + pub fn clear_isr(&self, mux_isr: &mut MuxIsr) { + match self.id() { + 0 => mux_isr.cfr.write(|w| w.csof0().set_bit()), + 1 => mux_isr.cfr.write(|w| w.csof1().set_bit()), + 2 => mux_isr.cfr.write(|w| w.csof2().set_bit()), + 3 => mux_isr.cfr.write(|w| w.csof3().set_bit()), + 4 => mux_isr.cfr.write(|w| w.csof4().set_bit()), + 5 => mux_isr.cfr.write(|w| w.csof5().set_bit()), + 6 => mux_isr.cfr.write(|w| w.csof6().set_bit()), + 7 => mux_isr.cfr.write(|w| w.csof7().set_bit()), + 8 => mux_isr.cfr.write(|w| w.csof8().set_bit()), + 9 => mux_isr.cfr.write(|w| w.csof9().set_bit()), + 10 => mux_isr.cfr.write(|w| w.csof10().set_bit()), + 11 => mux_isr.cfr.write(|w| w.csof11().set_bit()), + 12 => mux_isr.cfr.write(|w| w.csof12().set_bit()), + 13 => mux_isr.cfr.write(|w| w.csof13().set_bit()), + 14 => mux_isr.cfr.write(|w| w.csof14().set_bit()), + 15 => mux_isr.cfr.write(|w| w.csof15().set_bit()), + _ => unreachable!(), + } + } +} + +unsafe impl Send for Mux +where + CXX: ChannelId, + ReqId: IRequestId, + SyncED: ISyncED, + EgED: IEgED, +{ +} + +unsafe impl Sync for Mux +where + CXX: ChannelId, + ReqId: IRequestId, + SyncED: ISyncED, + EgED: IEgED, +{ +} + type_state! { - SyncED, SyncDisabled, SyncEnabled + ISyncED, SyncDisabled, SyncEnabled } type_state! { - EgED, EgDisabled, EgEnabled + IEgED, EgDisabled, EgEnabled } bool_enum! { @@ -260,164 +576,18 @@ impl MuxShared { } pub struct MuxIsr { - pub(super) csr: &'static CSR, + csr: &'static CSR, /// This field *must not* be mutated using shared references - pub(super) cfr: &'static CFR, -} - -unsafe impl Send for MuxIsr {} -unsafe impl Sync for MuxIsr {} - -pub struct OverrunError; - -pub struct RequestGenerator -where - GXX: GenId, - ED: GenED, -{ - /// This field *must not* be mutated using shared references - rb: &'static RGCR, - _phantom_data: PhantomData<(GXX, ED)>, -} - -impl RequestGenerator -where - GXX: GenId, -{ - pub(super) fn after_reset(rb: &'static RGCR) -> Self { - RequestGenerator { - rb, - _phantom_data: PhantomData, - } - } -} - -impl RequestGenerator -where - GXX: GenId, - ED: GenED, -{ - pub fn id(&self) -> usize { - GXX::ID - } - - pub fn sig_id(&self) -> SigId { - self.rb.read().sig_id().bits().try_into().unwrap() - } - - pub fn set_sig_id(&mut self, sig_id: SigId) { - unsafe { - self.rb.modify(|_, w| w.sig_id().bits(sig_id.into())); - } - } - - pub fn overrun_interrupt(&self) -> TriggerOverrunInterrupt { - self.rb.read().oie().bit().into() - } - - pub fn set_trigger_overrun_interrupt( - &mut self, - overrun_intrpt: TriggerOverrunInterrupt, - ) { - self.rb.modify(|_, w| w.oie().bit(overrun_intrpt.into())); - } - - pub fn gpol(&self) -> GPol { - self.rb.read().gpol().bits().try_into().unwrap() - } - - pub fn set_gpol(&mut self, gpol: GPol) { - self.rb.modify(|_, w| w.gpol().bits(gpol.into())); - } - - pub fn gnbreq(&self) -> GNbReq { - self.rb.read().gnbreq().bits().try_into().unwrap() - } - - fn transmute(self) -> RequestGenerator - where - NewED: GenED, - { - RequestGenerator { - rb: self.rb, - _phantom_data: PhantomData, - } - } + cfr: &'static mut CFR, } -impl RequestGenerator -where - GXX: GenId, -{ - pub fn set_gnbreq(&mut self, gnbreq: GNbReq) { - self.rb.modify(|_, w| w.gnbreq().bits(gnbreq.into())); - } - - pub fn enable(self) -> RequestGenerator { - self.rb.modify(|_, w| w.ge().set_bit()); - - self.transmute() +impl MuxIsr { + pub(super) fn new(csr: &'static CSR, cfr: &'static mut CFR) -> Self { + Self { csr, cfr } } } -impl RequestGenerator -where - GXX: GenId, -{ - pub fn disable(self) -> RequestGenerator { - self.rb.modify(|_, w| w.ge().clear_bit()); - - self.transmute() - } -} - -impl RequestGenerator -where - GXX: GenId, - ED: GenED, -{ - pub fn check_isr( - &self, - isr: &RequestGenIsr, - ) -> Result<(), TriggerOverrunError> { - if self.trigger_overrun_flag(isr) { - Err(TriggerOverrunError) - } else { - Ok(()) - } - } - pub fn trigger_overrun_flag(&self, isr: &RequestGenIsr) -> bool { - match self.id() { - 0 => isr.rgsr.read().of0().bit_is_set(), - 1 => isr.rgsr.read().of1().bit_is_set(), - 2 => isr.rgsr.read().of2().bit_is_set(), - 3 => isr.rgsr.read().of3().bit_is_set(), - 4 => isr.rgsr.read().of4().bit_is_set(), - 5 => isr.rgsr.read().of5().bit_is_set(), - 6 => isr.rgsr.read().of6().bit_is_set(), - 7 => isr.rgsr.read().of7().bit_is_set(), - _ => unreachable!(), - } - } - - pub fn clear_isr(&self, isr: &mut RequestGenIsr) { - match self.id() { - 0 => isr.rgcfr.write(|w| w.cof0().set_bit()), - 1 => isr.rgcfr.write(|w| w.cof1().set_bit()), - 2 => isr.rgcfr.write(|w| w.cof2().set_bit()), - 3 => isr.rgcfr.write(|w| w.cof3().set_bit()), - 4 => isr.rgcfr.write(|w| w.cof4().set_bit()), - 5 => isr.rgcfr.write(|w| w.cof5().set_bit()), - 6 => isr.rgcfr.write(|w| w.cof6().set_bit()), - 7 => isr.rgcfr.write(|w| w.cof7().set_bit()), - _ => unreachable!(), - } - } -} +unsafe impl Send for MuxIsr {} +unsafe impl Sync for MuxIsr {} -unsafe impl Sync for RequestGenerator -where - GXX: GenId, - ED: GenED, -{ -} +pub struct OverrunError; diff --git a/src/dma/mux/request_gen.rs b/src/dma/mux/request_gen.rs index 09872dd0..7f8d5366 100644 --- a/src/dma/mux/request_gen.rs +++ b/src/dma/mux/request_gen.rs @@ -1,10 +1,164 @@ //! DMA Request Generator use crate::private; -use crate::stm32::dmamux1::{RGCFR, RGSR}; +use crate::stm32::dmamux1::{RGCFR, RGCR, RGSR}; +use core::convert::TryInto; +use core::marker::PhantomData; + +pub struct RequestGenerator +where + GXX: GenId, + ED: IED, +{ + /// This field *must not* be mutated using shared references + rb: &'static mut RGCR, + _phantom_data: PhantomData<(GXX, ED)>, +} + +impl RequestGenerator +where + GXX: GenId, +{ + pub(in super::super) fn after_reset(rb: &'static mut RGCR) -> Self { + RequestGenerator { + rb, + _phantom_data: PhantomData, + } + } +} + +impl RequestGenerator +where + GXX: GenId, + ED: IED, +{ + pub fn id(&self) -> usize { + GXX::ID + } + + pub fn sig_id(&self) -> SigId { + self.rb.read().sig_id().bits().try_into().unwrap() + } + + pub fn set_sig_id(&mut self, sig_id: SigId) { + unsafe { + self.rb.modify(|_, w| w.sig_id().bits(sig_id.into())); + } + } + + pub fn overrun_interrupt(&self) -> TriggerOverrunInterrupt { + self.rb.read().oie().bit().into() + } + + pub fn set_trigger_overrun_interrupt( + &mut self, + overrun_intrpt: TriggerOverrunInterrupt, + ) { + self.rb.modify(|_, w| w.oie().bit(overrun_intrpt.into())); + } + + pub fn gpol(&self) -> GPol { + self.rb.read().gpol().bits().try_into().unwrap() + } + + pub fn set_gpol(&mut self, gpol: GPol) { + self.rb.modify(|_, w| w.gpol().bits(gpol.into())); + } + + pub fn gnbreq(&self) -> GNbReq { + self.rb.read().gnbreq().bits().try_into().unwrap() + } + + fn transmute(self) -> RequestGenerator + where + NewED: IED, + { + RequestGenerator { + rb: self.rb, + _phantom_data: PhantomData, + } + } +} + +impl RequestGenerator +where + GXX: GenId, +{ + pub fn set_gnbreq(&mut self, gnbreq: GNbReq) { + self.rb.modify(|_, w| w.gnbreq().bits(gnbreq.into())); + } + + pub fn enable(self) -> RequestGenerator { + self.rb.modify(|_, w| w.ge().set_bit()); + + self.transmute() + } +} + +impl RequestGenerator +where + GXX: GenId, +{ + pub fn disable(self) -> RequestGenerator { + self.rb.modify(|_, w| w.ge().clear_bit()); + + self.transmute() + } +} + +impl RequestGenerator +where + GXX: GenId, + ED: IED, +{ + pub fn check_isr( + &self, + isr: &RequestGenIsr, + ) -> Result<(), TriggerOverrunError> { + if self.trigger_overrun_flag(isr) { + Err(TriggerOverrunError) + } else { + Ok(()) + } + } + pub fn trigger_overrun_flag(&self, isr: &RequestGenIsr) -> bool { + match self.id() { + 0 => isr.rgsr.read().of0().bit_is_set(), + 1 => isr.rgsr.read().of1().bit_is_set(), + 2 => isr.rgsr.read().of2().bit_is_set(), + 3 => isr.rgsr.read().of3().bit_is_set(), + 4 => isr.rgsr.read().of4().bit_is_set(), + 5 => isr.rgsr.read().of5().bit_is_set(), + 6 => isr.rgsr.read().of6().bit_is_set(), + 7 => isr.rgsr.read().of7().bit_is_set(), + _ => unreachable!(), + } + } + + pub fn clear_isr(&self, isr: &mut RequestGenIsr) { + match self.id() { + 0 => isr.rgcfr.write(|w| w.cof0().set_bit()), + 1 => isr.rgcfr.write(|w| w.cof1().set_bit()), + 2 => isr.rgcfr.write(|w| w.cof2().set_bit()), + 3 => isr.rgcfr.write(|w| w.cof3().set_bit()), + 4 => isr.rgcfr.write(|w| w.cof4().set_bit()), + 5 => isr.rgcfr.write(|w| w.cof5().set_bit()), + 6 => isr.rgcfr.write(|w| w.cof6().set_bit()), + 7 => isr.rgcfr.write(|w| w.cof7().set_bit()), + _ => unreachable!(), + } + } +} + +unsafe impl Sync for RequestGenerator +where + GXX: GenId, + ED: IED, +{ +} type_state! { - ED, Disabled, Enabled + IED, Disabled, Enabled } pub trait GenId: Send + private::Sealed { @@ -69,15 +223,15 @@ int_struct! { pub struct TriggerOverrunError; pub struct RequestGenIsr { - pub(super) rgsr: &'static RGSR, + rgsr: &'static RGSR, /// This field *must not* be mutated using shared references - pub(super) rgcfr: &'static RGCFR, + rgcfr: &'static mut RGCFR, } impl RequestGenIsr { pub(in super::super) fn new( rgsr: &'static RGSR, - rgcfr: &'static RGCFR, + rgcfr: &'static mut RGCFR, ) -> Self { RequestGenIsr { rgsr, rgcfr } } diff --git a/src/dma/stream.rs b/src/dma/stream/config.rs similarity index 92% rename from src/dma/stream.rs rename to src/dma/stream/config.rs index 03c5c22d..e05a96fb 100644 --- a/src/dma/stream.rs +++ b/src/dma/stream/config.rs @@ -1,254 +1,3 @@ -//! DMA Stream - -use super::DmaPeripheral; -use crate::stm32::dma1::{HIFCR, HISR, LIFCR, LISR}; -use core::marker::PhantomData; - -type_state! { - ED, Disabled, Enabled -} - -type_state! { - IsrState, IsrCleared, IsrUncleared -} - -pub trait IntoNum { - fn into_num(self) -> usize; -} - -bool_enum! { - TransferCompleteInterrupt, "Transfer Complete Interrupt", Disabled (D), Enabled -} - -bool_enum! { - HalfTransferInterrupt, "Half Transfer Interrupt", Disabled (D), Enabled -} - -bool_enum! { - TransferErrorInterrupt, "Transfer Error Interrupt", Disabled (D), Enabled -} - -bool_enum! { - DirectModeErrorInterrupt, "Direct Mode Error Interrupt", Disabled (D), Enabled -} - -bool_enum! { - FifoErrorInterrupt, "Fifo Error Interrupt", Disabled (D), Enabled -} - -bool_enum! { - FlowController, "Flow Controller", Dma (D), Peripheral -} - -int_enum! { - TransferDirection <=> u8, - "Transfer Direction", - P2M <=> 0b00 (D), - M2P <=> 0b01, - M2M <=> 0b10 -} - -bool_enum! { - CircularMode, "Circular Mode", Disabled (D), Enabled -} - -bool_enum! { - Pinc, "Peripheral Increment Mode", Fixed (D), Incremented -} - -bool_enum! { - Minc, "Memory Increment Mode", Fixed (D), Incremented -} - -int_enum! { - PSize <=> u8, - "Peripheral Data Size", - Byte <=> 0b00 (D), - HalfWord <=> 0b01, - Word <=> 0b10 -} - -impl IntoNum for PSize { - fn into_num(self) -> usize { - match self { - PSize::Byte => 1, - PSize::HalfWord => 2, - PSize::Word => 4, - } - } -} - -int_enum! { - MSize <=> u8, - "Memory Data Size", - Byte <=> 0b00 (D), - HalfWord <=> 0b01, - Word <=> 0b10 -} - -impl IntoNum for MSize { - fn into_num(self) -> usize { - match self { - MSize::Byte => 1, - MSize::HalfWord => 2, - MSize::Word => 4, - } - } -} - -bool_enum! { - Pincos, "Peripheral Increment Offset Size", PSize (D), Word -} - -int_enum! { - PriorityLevel <=> u8, - "Priority Level", - Low <=> 0b00 (D), - Medium <=> 0b01, - High <=> 0b10, - VeryHigh <=> 0b11 -} - -bool_enum! { - BufferMode, "Buffer Mode", Regular (D), DoubleBuffer -} - -bool_enum! { - CurrentTarget, "CurrentTarget", M0a (D), M1a -} - -int_enum! { - PBurst <=> u8, - "Peripheral Burst", - Single <=> 0b00 (D), - Incr4 <=> 0b01, - Incr8 <=> 0b10, - Incr16 <=> 0b11 -} - -impl IntoNum for PBurst { - fn into_num(self) -> usize { - match self { - PBurst::Single => 1, - PBurst::Incr4 => 4, - PBurst::Incr8 => 8, - PBurst::Incr16 => 16, - } - } -} - -int_enum! { - MBurst <=> u8, - "Memory Burst", - Single <=> 0b00 (D), - Incr4 <=> 0b01, - Incr8 <=> 0b10, - Incr16 <=> 0b11 -} - -impl IntoNum for MBurst { - fn into_num(self) -> usize { - match self { - MBurst::Single => 1, - MBurst::Incr4 => 4, - MBurst::Incr8 => 8, - MBurst::Incr16 => 16, - } - } -} - -int_struct! { - Ndt, u16, 0, "Number of Data Items to transfer", 0 -} - -int_struct! { - Pa, u32, 0, "Peripheral Address", 0 -} - -int_struct! { - M0a, u32, 0, "Memory 0 Address", 0 -} - -int_struct! { - M1a, u32, 0, "Memory 1 Address", 0 -} - -bool_enum! { - TransferMode, "Transfer Mode", Direct (D), Fifo -} - -int_enum! { - FifoThreshold <=> u8, - "Fifo Threshold", - F1_4 <=> 0b00 (D), - F1_2 <=> 0b01, - F3_4 <=> 0b10, - Full <=> 0b11 -} - -impl IntoNum for FifoThreshold { - /// Fifo threshold in words - fn into_num(self) -> usize { - match self { - FifoThreshold::F1_4 => 1, - FifoThreshold::F1_2 => 2, - FifoThreshold::F3_4 => 3, - FifoThreshold::Full => 4, - } - } -} - -pub struct StreamIsr -where - DMA: DmaPeripheral, -{ - pub(super) lisr: &'static LISR, - pub(super) hisr: &'static HISR, - /// This field *must not* be mutated using shared references - pub(super) lifcr: &'static LIFCR, - /// This field *must not* be mutated using shared references - pub(super) hifcr: &'static HIFCR, - _phantom_data: PhantomData, -} - -impl StreamIsr -where - DMA: DmaPeripheral, -{ - pub(super) fn new( - lisr: &'static LISR, - hisr: &'static HISR, - lifcr: &'static LIFCR, - hifcr: &'static HIFCR, - ) -> Self { - StreamIsr { - lisr, - hisr, - lifcr, - hifcr, - _phantom_data: PhantomData, - } - } -} - -unsafe impl Send for StreamIsr where DMA: DmaPeripheral {} -unsafe impl Sync for StreamIsr where DMA: DmaPeripheral {} - -#[derive(Debug, PartialEq, Eq, Clone, Copy)] -pub enum Event { - HalfTransfer, - TransferComplete, -} - -#[derive(Debug, Clone, Copy)] -pub struct Error { - pub transfer_error: bool, - pub direct_mode_error: bool, - pub fifo_error: bool, - pub event: Option, - pub crashed: bool, -} - ///////////////////////////////////////////////////////////////////////// // CONFIG ///////////////////////////////////////////////////////////////////////// @@ -802,3 +551,189 @@ pub struct DoubleBufferConf { pub current_target: CurrentTarget, pub m1a: M1a, } + +pub trait IntoNum { + fn into_num(self) -> usize; +} + +bool_enum! { + TransferCompleteInterrupt, "Transfer Complete Interrupt", Disabled (D), Enabled +} + +bool_enum! { + HalfTransferInterrupt, "Half Transfer Interrupt", Disabled (D), Enabled +} + +bool_enum! { + TransferErrorInterrupt, "Transfer Error Interrupt", Disabled (D), Enabled +} + +bool_enum! { + DirectModeErrorInterrupt, "Direct Mode Error Interrupt", Disabled (D), Enabled +} + +bool_enum! { + FifoErrorInterrupt, "Fifo Error Interrupt", Disabled (D), Enabled +} + +bool_enum! { + FlowController, "Flow Controller", Dma (D), Peripheral +} + +int_enum! { + TransferDirection <=> u8, + "Transfer Direction", + P2M <=> 0b00 (D), + M2P <=> 0b01, + M2M <=> 0b10 +} + +bool_enum! { + CircularMode, "Circular Mode", Disabled (D), Enabled +} + +bool_enum! { + Pinc, "Peripheral Increment Mode", Fixed (D), Incremented +} + +bool_enum! { + Minc, "Memory Increment Mode", Fixed (D), Incremented +} + +int_enum! { + PSize <=> u8, + "Peripheral Data Size", + Byte <=> 0b00 (D), + HalfWord <=> 0b01, + Word <=> 0b10 +} + +impl IntoNum for PSize { + fn into_num(self) -> usize { + match self { + PSize::Byte => 1, + PSize::HalfWord => 2, + PSize::Word => 4, + } + } +} + +int_enum! { + MSize <=> u8, + "Memory Data Size", + Byte <=> 0b00 (D), + HalfWord <=> 0b01, + Word <=> 0b10 +} + +impl IntoNum for MSize { + fn into_num(self) -> usize { + match self { + MSize::Byte => 1, + MSize::HalfWord => 2, + MSize::Word => 4, + } + } +} + +bool_enum! { + Pincos, "Peripheral Increment Offset Size", PSize (D), Word +} + +int_enum! { + PriorityLevel <=> u8, + "Priority Level", + Low <=> 0b00 (D), + Medium <=> 0b01, + High <=> 0b10, + VeryHigh <=> 0b11 +} + +bool_enum! { + BufferMode, "Buffer Mode", Regular (D), DoubleBuffer +} + +bool_enum! { + CurrentTarget, "CurrentTarget", M0a (D), M1a +} + +int_enum! { + PBurst <=> u8, + "Peripheral Burst", + Single <=> 0b00 (D), + Incr4 <=> 0b01, + Incr8 <=> 0b10, + Incr16 <=> 0b11 +} + +impl IntoNum for PBurst { + fn into_num(self) -> usize { + match self { + PBurst::Single => 1, + PBurst::Incr4 => 4, + PBurst::Incr8 => 8, + PBurst::Incr16 => 16, + } + } +} + +int_enum! { + MBurst <=> u8, + "Memory Burst", + Single <=> 0b00 (D), + Incr4 <=> 0b01, + Incr8 <=> 0b10, + Incr16 <=> 0b11 +} + +impl IntoNum for MBurst { + fn into_num(self) -> usize { + match self { + MBurst::Single => 1, + MBurst::Incr4 => 4, + MBurst::Incr8 => 8, + MBurst::Incr16 => 16, + } + } +} + +int_struct! { + Ndt, u16, 0, "Number of Data Items to transfer", 0 +} + +int_struct! { + Pa, u32, 0, "Peripheral Address", 0 +} + +int_struct! { + M0a, u32, 0, "Memory 0 Address", 0 +} + +int_struct! { + M1a, u32, 0, "Memory 1 Address", 0 +} + +bool_enum! { + TransferMode, "Transfer Mode", Direct (D), Fifo +} + +int_enum! { + FifoThreshold <=> u8, + "Fifo Threshold", + F1_4 <=> 0b00 (D), + F1_2 <=> 0b01, + F3_4 <=> 0b10, + Full <=> 0b11 +} + +impl IntoNum for FifoThreshold { + /// Fifo threshold in words + fn into_num(self) -> usize { + match self { + FifoThreshold::F1_4 => 1, + FifoThreshold::F1_2 => 2, + FifoThreshold::F3_4 => 3, + FifoThreshold::Full => 4, + } + } +} diff --git a/src/dma/stream/mod.rs b/src/dma/stream/mod.rs new file mode 100644 index 00000000..240915a7 --- /dev/null +++ b/src/dma/stream/mod.rs @@ -0,0 +1,1200 @@ +//! DMA Stream + +pub mod config; + +use self::config::{ + BufferMode, BufferModeConf, CircularMode, CircularModeConf, CurrentTarget, + DirectConf, DirectModeErrorInterrupt, DoubleBufferConf, FifoConf, + FifoErrorInterrupt, FifoThreshold, FlowController, FlowControllerConf, + HalfTransferInterrupt, IntoNum, M0a, M1a, MBurst, MSize, Minc, Ndt, + NotM2MConf, PBurst, PBurstConf, PSize, Pa, Pinc, PincConf, Pincos, + PriorityLevel, TransferCompleteInterrupt, TransferDirection, + TransferDirectionConf, TransferErrorInterrupt, TransferMode, + TransferModeConf, +}; +use super::{ChannelId, DmaPeripheral}; +use crate::nb::Error as NbError; +use crate::stm32::dma1::{HIFCR, HISR, LIFCR, LISR, ST}; +use core::convert::{Infallible, TryInto}; +use core::marker::PhantomData; + +pub use self::config::Config; + +/// DMA Stream +pub struct Stream +where + CXX: ChannelId, + ED: IED, + IsrState: IIsrState, +{ + /// This field *must not* be mutated using shared references + rb: &'static mut ST, + config_ndt: Ndt, + _phantom_data: PhantomData<(CXX, ED, IsrState)>, +} + +impl Stream +where + CXX: ChannelId, +{ + /// Creates an instance of a Stream in initial state. + /// + /// Should only be called after RCC-Reset of the DMA. + pub(super) fn after_reset(rb: &'static mut ST) -> Self { + Stream { + rb, + config_ndt: Ndt::default(), + _phantom_data: PhantomData, + } + } +} + +impl Stream +where + CXX: ChannelId, + ED: IED, + IsrState: IIsrState, +{ + pub fn config(&self) -> Config { + Config { + transfer_complete_interrupt: self.transfer_complete_interrupt(), + half_transfer_interrupt: self.half_transfer_interrupt(), + transfer_error_interrupt: self.transfer_error_interrupt(), + direct_mode_error_interrupt: self.direct_mode_error_interrupt(), + fifo_error_interrupt: self.fifo_error_interrupt(), + minc: self.minc(), + priority_level: self.priority_level(), + p_size: self.p_size(), + ndt: self.ndt(), + pa: self.pa(), + m0a: self.m0a(), + transfer_direction: self.transfer_direction_config(), + } + } + + fn transfer_direction_config(&self) -> TransferDirectionConf { + match self.transfer_direction() { + TransferDirection::P2M => { + TransferDirectionConf::P2M(self.not_m2m_config()) + } + TransferDirection::M2P => { + TransferDirectionConf::M2P(self.not_m2m_config()) + } + TransferDirection::M2M => { + TransferDirectionConf::M2M(self.fifo_config()) + } + } + } + + fn not_m2m_config(&self) -> NotM2MConf { + NotM2MConf { + transfer_mode: self.transfer_mode_config(), + flow_controller: self.flow_controller_config(), + } + } + + fn transfer_mode_config(&self) -> TransferModeConf { + match self.transfer_mode() { + TransferMode::Direct => { + TransferModeConf::Direct(self.direct_conf()) + } + TransferMode::Fifo => TransferModeConf::Fifo(self.fifo_config()), + } + } + + fn flow_controller_config(&self) -> FlowControllerConf { + match self.flow_controller() { + FlowController::Dma => { + FlowControllerConf::Dma(self.circular_mode_config()) + } + FlowController::Peripheral => FlowControllerConf::Peripheral, + } + } + + fn circular_mode_config(&self) -> CircularModeConf { + match self.circular_mode() { + CircularMode::Disabled => CircularModeConf::Disabled, + CircularMode::Enabled => { + CircularModeConf::Enabled(self.buffer_mode_config()) + } + } + } + + fn buffer_mode_config(&self) -> BufferModeConf { + match self.buffer_mode() { + BufferMode::Regular => BufferModeConf::Regular, + BufferMode::DoubleBuffer => { + BufferModeConf::DoubleBuffer(self.double_buffer_config()) + } + } + } + + fn double_buffer_config(&self) -> DoubleBufferConf { + DoubleBufferConf { + current_target: self.current_target(), + m1a: self.m1a().unwrap(), + } + } + + fn direct_conf(&self) -> DirectConf { + DirectConf { pinc: self.pinc() } + } + + fn fifo_config(&self) -> FifoConf { + FifoConf { + fifo_threshold: self.fifo_threshold().unwrap(), + p_burst: self.p_burst_config(), + m_burst: self.m_burst(), + m_size: self.m_size(), + } + } + + fn p_burst_config(&self) -> PBurstConf { + match self.p_burst() { + PBurst::Single => PBurstConf::Single(self.pinc_conf()), + PBurst::Incr4 => PBurstConf::Incr4(self.pinc()), + PBurst::Incr8 => PBurstConf::Incr8(self.pinc()), + PBurst::Incr16 => PBurstConf::Incr16(self.pinc()), + } + } + + fn pinc_conf(&self) -> PincConf { + match self.pinc() { + Pinc::Fixed => PincConf::Fixed, + Pinc::Incremented => PincConf::Incremented(self.pincos()), + } + } + + /// Returns the id of the Stream + pub fn id(&self) -> usize { + CXX::STREAM_ID + } + + /// Performs a *volatile* read of the stream enable bit + pub fn is_enabled(&self) -> bool { + self.rb.cr.read().en().bit_is_set() + } + + /// Returns the Transfer Complete Interrupt config flag + pub fn transfer_complete_interrupt(&self) -> TransferCompleteInterrupt { + self.rb.cr.read().tcie().bit().into() + } + + /// Sets the Transfer Complete Interrupt config flag + fn set_transfer_complete_interrupt( + &mut self, + tc_intrpt: TransferCompleteInterrupt, + ) { + self.rb.cr.modify(|_, w| w.tcie().bit(tc_intrpt.into())); + } + + /// Returns the Half Transfer Interrupt config flag + pub fn half_transfer_interrupt(&self) -> HalfTransferInterrupt { + self.rb.cr.read().htie().bit().into() + } + + /// Sets the Half Transfer Interrupt config flag + fn set_half_transfer_interrupt( + &mut self, + ht_intrpt: HalfTransferInterrupt, + ) { + self.rb.cr.modify(|_, w| w.htie().bit(ht_intrpt.into())); + } + + /// Returns the Transfer Error Interrupt config flag + pub fn transfer_error_interrupt(&self) -> TransferErrorInterrupt { + self.rb.cr.read().teie().bit().into() + } + + /// Sets the Transfer Error Interrupt config flag + fn set_transfer_error_interrupt( + &mut self, + te_intrpt: TransferErrorInterrupt, + ) { + self.rb.cr.modify(|_, w| w.teie().bit(te_intrpt.into())); + } + + /// Returns the Direct Mode Error Interrupt config flag + pub fn direct_mode_error_interrupt(&self) -> DirectModeErrorInterrupt { + self.rb.cr.read().dmeie().bit().into() + } + + /// Sets the Direct Mode Error Interrupt config flag + fn set_direct_mode_error_interrupt( + &mut self, + dme_intrpt: DirectModeErrorInterrupt, + ) { + self.rb.cr.modify(|_, w| w.dmeie().bit(dme_intrpt.into())); + } + + /// Returns the Fifo Error Interrupt config flag + pub fn fifo_error_interrupt(&self) -> FifoErrorInterrupt { + self.rb.fcr.read().feie().bit().into() + } + + /// Sets the Fifo Error Interrupt config flag + fn set_fifo_error_interrupt(&mut self, fe_intrpt: FifoErrorInterrupt) { + self.rb.fcr.modify(|_, w| w.feie().bit(fe_intrpt.into())); + } + + /// Returns the Flow Controller + pub fn flow_controller(&self) -> FlowController { + self.rb.cr.read().pfctrl().bit().into() + } + + /// Returns the Transfer Direction + pub fn transfer_direction(&self) -> TransferDirection { + self.rb.cr.read().dir().bits().try_into().unwrap() + } + + /// Returns the Circular Mode + pub fn circular_mode(&self) -> CircularMode { + self.rb.cr.read().circ().bit().into() + } + + /// Returns the Peripheral Increment config flag + pub fn pinc(&self) -> Pinc { + self.rb.cr.read().pinc().bit().into() + } + + /// Returns the Memory Increment config flag + pub fn minc(&self) -> Minc { + self.rb.cr.read().minc().bit().into() + } + + /// Returns the Peripheral Size + pub fn p_size(&self) -> PSize { + self.rb.cr.read().psize().bits().try_into().unwrap() + } + + /// Returns the Memory Size + pub fn m_size(&self) -> MSize { + self.rb.cr.read().msize().bits().try_into().unwrap() + } + + /// Returns the Peripheral Increment Offset + pub fn pincos(&self) -> Pincos { + self.rb.cr.read().pincos().bit().into() + } + + /// Returns the Priority Level + pub fn priority_level(&self) -> PriorityLevel { + self.rb.cr.read().pl().bits().try_into().unwrap() + } + + /// Returns the Buffer Mode + pub fn buffer_mode(&self) -> BufferMode { + self.rb.cr.read().dbm().bit().into() + } + + /// Returns the Current Target + pub fn current_target(&self) -> CurrentTarget { + self.rb.cr.read().ct().bit().into() + } + + /// Returns the Peripheral Burst config flag + pub fn p_burst(&self) -> PBurst { + self.rb.cr.read().pburst().bits().try_into().unwrap() + } + + /// Returns the Memory Burst config flag + pub fn m_burst(&self) -> MBurst { + self.rb.cr.read().mburst().bits().try_into().unwrap() + } + + /// Returns the content of the NDT register + pub fn ndt(&self) -> Ndt { + self.rb.ndtr.read().ndt().bits().into() + } + + /// Sets the content of the NDT register + pub fn configured_ndt(&self) -> Ndt { + self.config_ndt + } + + /// Returns the Peripheral Address + pub fn pa(&self) -> Pa { + self.rb.par.read().pa().bits().into() + } + + /// Returns the Memory-0 Address + pub fn m0a(&self) -> M0a { + self.rb.m0ar.read().m0a().bits().into() + } + + /// Returns the Memory-1 Address + pub fn m1a(&self) -> Option { + if self.buffer_mode() == BufferMode::DoubleBuffer { + Some(self.rb.m1ar.read().m1a().bits().into()) + } else { + None + } + } + + /// Returns the Fifo Threshold + pub fn fifo_threshold(&self) -> Option { + if self.transfer_mode() == TransferMode::Fifo { + Some(self.rb.fcr.read().fth().bits().try_into().unwrap()) + } else { + None + } + } + + /// Returns the Transfer Mode (`Direct` or `Fifo` Mode) + pub fn transfer_mode(&self) -> TransferMode { + self.rb.fcr.read().dmdis().bit().into() + } + + /// Performs the volatile write to the `M0a` register + fn impl_set_m0a(&mut self, m0a: M0a) { + self.rb.m0ar.modify(|_, w| w.m0a().bits(m0a.into())); + } + + /// Performs the volatile write to the `M1a` register + fn impl_set_m1a(&mut self, m1a: M1a) { + self.rb.m0ar.modify(|_, w| w.m0a().bits(m1a.into())); + } + + /// Transmutes the state of `self` + fn transmute(self) -> Stream + where + NewED: IED, + NewIsrState: IIsrState, + { + Stream { + rb: self.rb, + config_ndt: self.config_ndt, + _phantom_data: PhantomData, + } + } +} + +impl Stream +where + CXX: ChannelId, + IsrState: IIsrState, +{ + pub fn apply_config(&mut self, config: Config) { + self.set_transfer_complete_interrupt( + config.transfer_complete_interrupt, + ); + self.set_half_transfer_interrupt(config.half_transfer_interrupt); + self.set_transfer_error_interrupt(config.transfer_error_interrupt); + self.set_direct_mode_error_interrupt( + config.direct_mode_error_interrupt, + ); + self.set_fifo_error_interrupt(config.fifo_error_interrupt); + self.set_pinc(config.pinc()); + self.set_minc(config.minc); + self.set_priority_level(config.priority_level); + self.set_p_size(config.p_size); + self.set_ndt(config.ndt); + self.set_pa(config.pa); + self.set_m0a(config.m0a); + + self.set_transfer_direction(config.transfer_direction()); + self.set_transfer_mode(config.transfer_mode()); + self.set_flow_controller(config.flow_controller()); + self.set_circular_mode(config.circular_mode()); + self.set_buffer_mode(config.buffer_mode()); + + if let Some(fifo_threshold) = config.fifo_threshold() { + self.set_fifo_threshold(fifo_threshold); + } + self.set_p_burst(config.p_burst()); + self.set_m_burst(config.m_burst()); + self.set_m_size(config.m_size()); + + if let Some(pincos) = config.pincos() { + self.set_pincos(pincos); + } + + self.set_current_target(config.current_target()); + if let Some(m1a) = config.m1a() { + self.set_m1a(m1a); + } + } + + /// Sets the Flow Controller + fn set_flow_controller(&mut self, flow_controller: FlowController) { + self.rb + .cr + .modify(|_, w| w.pfctrl().bit(flow_controller.into())); + } + + /// Sets the Transfer Direction + fn set_transfer_direction(&mut self, transfer_dir: TransferDirection) { + unsafe { + self.rb.cr.modify(|_, w| w.dir().bits(transfer_dir.into())); + } + } + + /// Sets the Circular Mode + fn set_circular_mode(&mut self, circ_mode: CircularMode) { + self.rb.cr.modify(|_, w| w.circ().bit(circ_mode.into())); + } + + /// Sets the Peripheral Increment config flag + fn set_pinc(&mut self, pinc: Pinc) { + self.rb.cr.modify(|_, w| w.pinc().bit(pinc.into())); + } + + /// Sets the Memory Increment config flag + fn set_minc(&mut self, minc: Minc) { + self.rb.cr.modify(|_, w| w.minc().bit(minc.into())); + } + + /// Sets the Peripheral Size + fn set_p_size(&mut self, p_size: PSize) { + unsafe { + self.rb.cr.modify(|_, w| w.psize().bits(p_size.into())); + } + } + + /// Sets the Memory Size + fn set_m_size(&mut self, m_size: MSize) { + unsafe { + self.rb.cr.modify(|_, w| w.msize().bits(m_size.into())); + } + } + + /// Sets the Peripheral Increment Offset + fn set_pincos(&mut self, pincos: Pincos) { + self.rb.cr.modify(|_, w| w.pincos().bit(pincos.into())); + } + + /// Sets the Priority Level + fn set_priority_level(&mut self, priority_level: PriorityLevel) { + self.rb.cr.modify(|_, w| w.pl().bits(priority_level.into())); + } + + /// Sets the Buffer Mode (`Direct` or `Fifo` mode) + fn set_buffer_mode(&mut self, buffer_mode: BufferMode) { + self.rb.cr.modify(|_, w| w.dbm().bit(buffer_mode.into())); + } + + /// Sets the Current Target + fn set_current_target(&mut self, current_target: CurrentTarget) { + self.rb.cr.modify(|_, w| w.ct().bit(current_target.into())); + } + + /// Sets the Peripheral Burst + fn set_p_burst(&mut self, p_burst: PBurst) { + self.rb.cr.modify(|_, w| w.pburst().bits(p_burst.into())); + } + + /// Sets the Memory Burst + fn set_m_burst(&mut self, m_burst: MBurst) { + self.rb.cr.modify(|_, w| w.mburst().bits(m_burst.into())); + } + + /// Sets the NDT register + fn set_ndt(&mut self, ndt: Ndt) { + self.config_ndt = ndt; + + self.rb.ndtr.modify(|_, w| w.ndt().bits(ndt.into())); + } + + /// Sets the Peripheral Address + fn set_pa(&mut self, pa: Pa) { + self.rb.par.modify(|_, w| w.pa().bits(pa.into())); + } + + /// Sets the Memory-0 Address + fn set_m0a(&mut self, m0a: M0a) { + self.impl_set_m0a(m0a); + } + + /// Sets the Memory-1 Address + fn set_m1a(&mut self, m1a: M1a) { + self.impl_set_m1a(m1a); + } + + /// Sets the Fifo Threshold + fn set_fifo_threshold(&mut self, fifo_threshold: FifoThreshold) { + self.rb + .fcr + .modify(|_, w| w.fth().bits(fifo_threshold.into())); + } + + /// Sets the Transfer Mode + fn set_transfer_mode(&mut self, transfer_mode: TransferMode) { + self.rb + .fcr + .modify(|_, w| w.dmdis().bit(transfer_mode.into())); + } +} + +impl Stream +where + CXX: ChannelId, + IsrState: IIsrState, +{ + /// Sets the Memory-0 Address on the fly + /// + /// # Panic + /// + /// This panics if the stream is not in Double Buffer Mode. + pub fn set_m0a(&mut self, m0a: M0a) -> nb::Result<(), Infallible> { + self.check_double_buffer(); + + if self.current_target() == CurrentTarget::M0a && self.is_enabled() { + return Err(NbError::WouldBlock); + } + + self.impl_set_m0a(m0a); + + Ok(()) + } + + /// Sets the Memory-1 Address on the fly + /// + /// # Panic + /// + /// This panics if the stream is not in Double Buffer Mode. + pub fn set_m1a(&mut self, m1a: M1a) -> nb::Result<(), Infallible> { + self.check_double_buffer(); + + if self.current_target() == CurrentTarget::M1a && self.is_enabled() { + return Err(NbError::WouldBlock); + } + + self.impl_set_m1a(m1a); + + Ok(()) + } + + /// Checks if the stream is in Double Buffer Mode + fn check_double_buffer(&self) { + if self.buffer_mode() == BufferMode::Regular { + panic!("The buffer must be in double buffer mode to be changed on the fly."); + } + } +} + +impl Stream +where + CXX: ChannelId, +{ + /// Checks the config for data integrity and enables the stream + /// + /// # Safety + /// + /// Aliasing rules aren't enforced. + pub unsafe fn enable(self) -> Stream { + self.check_config(); + + self.enable_unchecked() + } + + /// Enables the stream without checking the config + /// + /// Consider using the checked version instead (`enable`). + /// + /// # Safety + /// + /// - Aliasing rules aren't enforced + /// - Config is not checked for guaranteeing data integrity + pub unsafe fn enable_unchecked(self) -> Stream { + self.rb.cr.modify(|_, w| w.en().set_bit()); + + self.transmute() + } + + /// Checks the config for data integrity + fn check_config(&self) { + if self.circular_mode() == CircularMode::Enabled { + self.check_config_circular(); + } + + if self.transfer_mode() == TransferMode::Fifo { + self.check_config_fifo(); + } + + self.check_ndt(); + } + + /// Checks the circular config. + // + // Reference: RM0433 Rev 6 - Chapter 15.3.10 + fn check_config_circular(&self) { + // Check for clashing config values + if self.transfer_direction() == TransferDirection::M2M + || self.flow_controller() == FlowController::Peripheral + { + panic!("For circular streams, the transfer direction must not be `M2M` and the FlowController must not be `Peripheral`."); + } + + // Check invariants + if self.transfer_mode() == TransferMode::Fifo { + let ndt = self.ndt().value() as usize; + let m_burst = self.m_burst().into_num(); + let p_burst = self.p_burst().into_num(); + let m_size = self.m_size().into_num(); + let p_size = self.p_size().into_num(); + + if self.m_burst() != MBurst::Single + && ndt % (m_burst * m_size / p_size) != 0 + { + panic!( + "Data integrity not guaranteed, because \ + `num_data_items != Multiple of (m_burst * (m_size / p_size))`" + ); + } + + if ndt % (p_burst * p_size) != 0 { + panic!( + "Data integrity not guaranteed, because \ + `num_data_items != Multiple of (p_burst * p_size)`" + ); + } + } else { + let ndt = self.ndt().value() as usize; + let p_size = self.p_size().into_num(); + + if ndt % p_size != 0 { + panic!( + "Data integrity not guaranteed, because \ + `num_data_items != Multiple of (p_size)`" + ); + } + } + } + + /// Checks the fifo config. + fn check_config_fifo(&self) { + if self.m_burst() != MBurst::Single { + self.check_config_fifo_m_burst(); + } + + if self.p_burst() != PBurst::Single { + self.check_config_fifo_p_burst(); + } + } + + /// Checks the memory config of fifo stream. + // + // Reference: RM0433 Rev 6 - Chapter 15.3.14 + fn check_config_fifo_m_burst(&self) { + let m_size = self.m_size().into_num(); + let m_burst = self.m_burst().into_num(); + // Fifo Size in bytes + let fifo_size = self.fifo_threshold().unwrap().into_num() * 4; + + if m_size * m_burst > fifo_size { + panic!("FIFO configuration invalid, because `msize * mburst > fifo_size`"); + } + + if fifo_size % (m_size * m_burst) != 0 { + panic!("FIFO configuration invalid, because `fifo_size % (msize * mburst) != 0`"); + } + } + + /// Checks the peripheral config of fifio stream. + // + // Reference: RM0433 Rev 6 - Chapter 15.3.14 + fn check_config_fifo_p_burst(&self) { + let p_burst = self.p_burst().into_num(); + let p_size = self.p_size().into_num(); + // 4 Words = 16 Bytes + const FULL_FIFO_BYTES: usize = 16; + + if p_burst * p_size == FULL_FIFO_BYTES + && self.fifo_threshold().unwrap() == FifoThreshold::F3_4 + { + panic!( + "FIFO configuration invalid, because \ + `pburst * psize == FULL_FIFO_SIZE` and \ + `fifo_threshhold == 3/4`" + ); + } + } + + /// Checks the NDT register + // + // Reference: RM0433 Rev 6 - Chapter 15.3.12 + fn check_ndt(&self) { + let m_size = self.m_size().into_num(); + let p_size = self.p_size().into_num(); + let ndt = self.config_ndt.value() as usize; + + if m_size > p_size && ndt % (m_size / p_size) != 0 { + panic!("`NDT` must be a multiple of (`m_size / p_size`)."); + } + } +} + +impl Stream +where + CXX: ChannelId, + IsrState: IIsrState, +{ + /// Disables the stream + pub fn disable(self) -> Stream { + self.rb.cr.modify(|_, w| w.en().clear_bit()); + + while self.rb.cr.read().en().bit_is_set() {} + + self.transmute() + } +} + +impl Stream +where + CXX: ChannelId, + ED: IED, +{ + /// Returns the contents of the isr. + /// + /// * If there is no error, an optional event is returned as `Ok` + /// * If there are errors, the errors are being wrapped into `Error` and returned as `Err` + pub fn check_isr( + &self, + isr: &StreamIsr, + ) -> Result, Error> { + let transfer_error = self.transfer_error_flag(isr); + let direct_mode_error = self.direct_mode_error_flag(isr); + let fifo_error = self.fifo_error_flag(isr); + + let event = if self.transfer_complete_flag(isr) { + Some(Event::TransferComplete) + } else if self.half_transfer_flag(isr) { + Some(Event::HalfTransfer) + } else { + None + }; + + let crashed = !self.is_enabled() && self.ndt().value() != 0; + + if transfer_error || direct_mode_error || fifo_error { + Err(Error { + transfer_error, + direct_mode_error, + fifo_error, + event, + crashed, + }) + } else { + Ok(event) + } + } + + /// Returns the Transfer Complete flag + pub fn transfer_complete_flag(&self, isr: &StreamIsr) -> bool { + match self.id() { + 0 => isr.lisr.read().tcif0().bit_is_set(), + 1 => isr.lisr.read().tcif1().bit_is_set(), + 2 => isr.lisr.read().tcif2().bit_is_set(), + 3 => isr.lisr.read().tcif3().bit_is_set(), + 4 => isr.hisr.read().tcif4().bit_is_set(), + 5 => isr.hisr.read().tcif5().bit_is_set(), + 6 => isr.hisr.read().tcif6().bit_is_set(), + 7 => isr.hisr.read().tcif7().bit_is_set(), + _ => unreachable!(), + } + } + + /// Returns the Half Transfer flag + pub fn half_transfer_flag(&self, isr: &StreamIsr) -> bool { + match self.id() { + 0 => isr.lisr.read().htif0().bit_is_set(), + 1 => isr.lisr.read().htif1().bit_is_set(), + 2 => isr.lisr.read().htif2().bit_is_set(), + 3 => isr.lisr.read().htif3().bit_is_set(), + 4 => isr.hisr.read().htif4().bit_is_set(), + 5 => isr.hisr.read().htif5().bit_is_set(), + 6 => isr.hisr.read().htif6().bit_is_set(), + 7 => isr.hisr.read().htif7().bit_is_set(), + _ => unreachable!(), + } + } + + /// Returns the Transfer Error flag + pub fn transfer_error_flag(&self, isr: &StreamIsr) -> bool { + match self.id() { + 0 => isr.lisr.read().teif0().bit_is_set(), + 1 => isr.lisr.read().teif1().bit_is_set(), + 2 => isr.lisr.read().teif2().bit_is_set(), + 3 => isr.lisr.read().teif3().bit_is_set(), + 4 => isr.hisr.read().teif4().bit_is_set(), + 5 => isr.hisr.read().teif5().bit_is_set(), + 6 => isr.hisr.read().teif6().bit_is_set(), + 7 => isr.hisr.read().teif7().bit_is_set(), + _ => unreachable!(), + } + } + + /// Returns the Direct Mode Error flag + pub fn direct_mode_error_flag(&self, isr: &StreamIsr) -> bool { + match self.id() { + 0 => isr.lisr.read().dmeif0().bit_is_set(), + 1 => isr.lisr.read().dmeif1().bit_is_set(), + 2 => isr.lisr.read().dmeif2().bit_is_set(), + 3 => isr.lisr.read().dmeif3().bit_is_set(), + 4 => isr.hisr.read().dmeif4().bit_is_set(), + 5 => isr.hisr.read().dmeif5().bit_is_set(), + 6 => isr.hisr.read().dmeif6().bit_is_set(), + 7 => isr.hisr.read().dmeif7().bit_is_set(), + _ => unreachable!(), + } + } + + /// Returns the Fifo Error flag + pub fn fifo_error_flag(&self, isr: &StreamIsr) -> bool { + match self.id() { + 0 => isr.lisr.read().feif0().bit_is_set(), + 1 => isr.lisr.read().feif1().bit_is_set(), + 2 => isr.lisr.read().feif2().bit_is_set(), + 3 => isr.lisr.read().feif3().bit_is_set(), + 4 => isr.hisr.read().feif4().bit_is_set(), + 5 => isr.hisr.read().feif5().bit_is_set(), + 6 => isr.hisr.read().feif6().bit_is_set(), + 7 => isr.hisr.read().feif7().bit_is_set(), + _ => unreachable!(), + } + } + + /// Performs the ISR clear + fn clear_isr_impl(&self, isr: &mut StreamIsr) { + self.clear_transfer_complete(isr); + self.clear_half_transfer(isr); + self.clear_transfer_error(isr); + self.clear_direct_mode_error(isr); + self.clear_fifo_error(isr); + } + + /// Clears the Transfer Complete flag + pub fn clear_transfer_complete(&self, isr: &mut StreamIsr) { + match self.id() { + 0 => { + isr.lifcr.write(|w| w.ctcif0().set_bit()); + } + 1 => { + isr.lifcr.write(|w| w.ctcif1().set_bit()); + } + 2 => { + isr.lifcr.write(|w| w.ctcif2().set_bit()); + } + 3 => { + isr.lifcr.write(|w| w.ctcif3().set_bit()); + } + 4 => { + isr.hifcr.write(|w| w.ctcif4().set_bit()); + } + 5 => { + isr.hifcr.write(|w| w.ctcif5().set_bit()); + } + 6 => { + isr.hifcr.write(|w| w.ctcif6().set_bit()); + } + 7 => { + isr.hifcr.write(|w| w.ctcif7().set_bit()); + } + _ => unreachable!(), + } + } + + /// Clears the Half Transfer flag + pub fn clear_half_transfer(&self, isr: &mut StreamIsr) { + match self.id() { + 0 => { + isr.lifcr.write(|w| w.chtif0().set_bit()); + } + 1 => { + isr.lifcr.write(|w| w.chtif1().set_bit()); + } + 2 => { + isr.lifcr.write(|w| w.chtif2().set_bit()); + } + 3 => { + isr.lifcr.write(|w| w.chtif3().set_bit()); + } + 4 => { + isr.hifcr.write(|w| w.chtif4().set_bit()); + } + 5 => { + isr.hifcr.write(|w| w.chtif5().set_bit()); + } + 6 => { + isr.hifcr.write(|w| w.chtif6().set_bit()); + } + 7 => { + isr.hifcr.write(|w| w.chtif7().set_bit()); + } + _ => unreachable!(), + } + } + + /// Clears the Transfer Error flag + pub fn clear_transfer_error(&self, isr: &mut StreamIsr) { + match self.id() { + 0 => { + isr.lifcr.write(|w| w.cteif0().set_bit()); + } + 1 => { + isr.lifcr.write(|w| w.cteif1().set_bit()); + } + 2 => { + isr.lifcr.write(|w| w.cteif2().set_bit()); + } + 3 => { + isr.lifcr.write(|w| w.cteif3().set_bit()); + } + 4 => { + isr.hifcr.write(|w| w.cteif4().set_bit()); + } + 5 => { + isr.hifcr.write(|w| w.cteif5().set_bit()); + } + 6 => { + isr.hifcr.write(|w| w.cteif6().set_bit()); + } + 7 => { + isr.hifcr.write(|w| w.cteif7().set_bit()); + } + _ => unreachable!(), + } + } + + /// Clears the Direct Mode Error flag + pub fn clear_direct_mode_error(&self, isr: &mut StreamIsr) { + match self.id() { + 0 => { + isr.lifcr.write(|w| w.cdmeif0().set_bit()); + } + 1 => { + isr.lifcr.write(|w| w.cdmeif1().set_bit()); + } + 2 => { + isr.lifcr.write(|w| w.cdmeif2().set_bit()); + } + 3 => { + isr.lifcr.write(|w| w.cdmeif3().set_bit()); + } + 4 => { + isr.hifcr.write(|w| w.cdmeif4().set_bit()); + } + 5 => { + isr.hifcr.write(|w| w.cdmeif5().set_bit()); + } + 6 => { + isr.hifcr.write(|w| w.cdmeif6().set_bit()); + } + 7 => { + isr.hifcr.write(|w| w.cdmeif7().set_bit()); + } + _ => unreachable!(), + } + } + + /// Clears the Fifo Error flag + pub fn clear_fifo_error(&self, isr: &mut StreamIsr) { + match self.id() { + 0 => { + isr.lifcr.write(|w| w.cfeif0().set_bit()); + } + 1 => { + isr.lifcr.write(|w| w.cfeif1().set_bit()); + } + 2 => { + isr.lifcr.write(|w| w.cfeif2().set_bit()); + } + 3 => { + isr.lifcr.write(|w| w.cfeif3().set_bit()); + } + 4 => { + isr.hifcr.write(|w| w.cfeif4().set_bit()); + } + 5 => { + isr.hifcr.write(|w| w.cfeif5().set_bit()); + } + 6 => { + isr.hifcr.write(|w| w.cfeif6().set_bit()); + } + 7 => { + isr.hifcr.write(|w| w.cfeif7().set_bit()); + } + _ => unreachable!(), + } + } +} + +impl Stream +where + CXX: ChannelId, +{ + /// Clears the ISR + pub fn clear_isr( + self, + isr: &mut StreamIsr, + ) -> Stream { + self.clear_isr_impl(isr); + + self.transmute() + } +} + +impl Stream +where + CXX: ChannelId, +{ + /// Clears the ISR + pub fn clear_isr(&self, isr: &mut StreamIsr) { + self.clear_isr_impl(isr); + } + + pub fn wait_until_completed( + &self, + isr: &StreamIsr, + ) -> nb::Result<(), Error> { + match self.check_isr(isr) { + Ok(Some(Event::TransferComplete)) => Ok(()), + Err(err) => Err(NbError::Other(err)), + _ => Err(NbError::WouldBlock), + } + } + + pub fn wait_until_completed_clear( + &self, + isr: &mut StreamIsr, + ) -> nb::Result<(), Error> { + let res = self.wait_until_completed(isr); + + self.clear_isr_if_not_blocking(res, isr); + + res + } + + pub fn wait_until_half_transfer( + &self, + isr: &StreamIsr, + ) -> nb::Result<(), Error> { + match self.check_isr(isr) { + Ok(Some(Event::HalfTransfer)) => Ok(()), + Err(err) => Err(NbError::Other(err)), + _ => Err(NbError::WouldBlock), + } + } + + pub fn wait_until_half_transfer_clear( + &self, + isr: &mut StreamIsr, + ) -> nb::Result<(), Error> { + let res = self.wait_until_half_transfer(isr); + + self.clear_isr_if_not_blocking(res, isr); + + res + } + + pub fn wait_until_next_half( + &self, + isr: &StreamIsr, + ) -> nb::Result<(), Error> { + match self.check_isr(isr) { + Ok(event) => match event { + Some(Event::HalfTransfer) | Some(Event::TransferComplete) => { + Ok(()) + } + None => Err(NbError::WouldBlock), + }, + Err(err) => Err(NbError::Other(err)), + } + } + + pub fn wait_until_next_half_clear( + &self, + isr: &mut StreamIsr, + ) -> nb::Result<(), Error> { + let res = self.wait_until_next_half(isr); + + self.clear_isr_if_not_blocking(res, isr); + + res + } + + fn clear_isr_if_not_blocking( + &self, + res: nb::Result<(), Error>, + isr: &mut StreamIsr, + ) { + if !matches!(res, Err(NbError::WouldBlock)) { + self.clear_isr(isr); + } + } +} + +unsafe impl Send for Stream +where + CXX: ChannelId, + ED: IED, + IsrState: IIsrState, +{ +} + +unsafe impl Sync for Stream +where + CXX: ChannelId, + ED: IED, + IsrState: IIsrState, +{ +} + +type_state! { + IED, Disabled, Enabled +} + +type_state! { + IIsrState, IsrCleared, IsrUncleared +} + +pub struct StreamIsr +where + DMA: DmaPeripheral, +{ + lisr: &'static LISR, + hisr: &'static HISR, + /// This field *must not* be mutated using shared references + lifcr: &'static mut LIFCR, + /// This field *must not* be mutated using shared references + hifcr: &'static mut HIFCR, + _phantom_data: PhantomData, +} + +impl StreamIsr +where + DMA: DmaPeripheral, +{ + pub(super) fn new( + lisr: &'static LISR, + hisr: &'static HISR, + lifcr: &'static mut LIFCR, + hifcr: &'static mut HIFCR, + ) -> Self { + StreamIsr { + lisr, + hisr, + lifcr, + hifcr, + _phantom_data: PhantomData, + } + } +} + +unsafe impl Send for StreamIsr where DMA: DmaPeripheral {} +unsafe impl Sync for StreamIsr where DMA: DmaPeripheral {} + +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +pub enum Event { + HalfTransfer, + TransferComplete, +} + +#[derive(Debug, Clone, Copy)] +pub struct Error { + pub transfer_error: bool, + pub direct_mode_error: bool, + pub fifo_error: bool, + pub event: Option, + pub crashed: bool, +} diff --git a/src/dma/transfer.rs b/src/dma/transfer.rs deleted file mode 100644 index 3d189f1f..00000000 --- a/src/dma/transfer.rs +++ /dev/null @@ -1,1784 +0,0 @@ -//! Safe DMA Transfers - -use super::stream::{ - BufferModeConf, CircularModeConf, Config as StreamConfig, CurrentTarget, - DirectConf, DoubleBufferConf, Enabled, FifoConf, FifoThreshold, - FlowControllerConf, IsrUncleared, M0a, M1a, MBurst, MSize, Minc, Ndt, - NotM2MConf, PBurstConf, PSize, Pa, Pinc, PincConf, Pincos, - TransferDirectionConf, TransferModeConf, -}; -use super::{ChannelId, Stream}; -use crate::private; -use core::convert::TryFrom; -use core::fmt::Debug; -use core::{mem, ptr}; -use enum_as_inner::EnumAsInner; - -pub trait TransferState<'wo>: Send + Sync + private::Sealed { - type Peripheral: Payload; - type Memory: Payload; - - fn buffers(&self) -> &TransferBuffers<'wo, Self::Peripheral, Self::Memory>; - - fn buffers_mut(&mut self, op: F) - where - for<'a> F: FnOnce( - &'a mut TransferBuffers<'wo, Self::Peripheral, Self::Memory>, - ); - - unsafe fn buffers_mut_unchecked( - &mut self, - ) -> &mut TransferBuffers<'wo, Self::Peripheral, Self::Memory>; -} - -pub struct Start<'wo, Peripheral, Memory> -where - Peripheral: Payload, - Memory: Payload, -{ - pub(super) conf: Config<'wo, Peripheral, Memory>, -} - -impl private::Sealed for Start<'_, Peripheral, Memory> -where - Peripheral: Payload, - Memory: Payload, -{ -} - -impl<'wo, Peripheral, Memory> TransferState<'wo> - for Start<'wo, Peripheral, Memory> -where - Peripheral: Payload, - Memory: Payload, -{ - type Peripheral = Peripheral; - type Memory = Memory; - - fn buffers(&self) -> &TransferBuffers<'wo, Peripheral, Memory> { - self.conf.transfer_direction.buffers() - } - - fn buffers_mut(&mut self, op: F) - where - for<'a> F: FnOnce(&'a mut TransferBuffers<'wo, Peripheral, Memory>), - { - self.conf.transfer_direction.buffers_mut(|b| op(b)); - } - - unsafe fn buffers_mut_unchecked( - &mut self, - ) -> &mut TransferBuffers<'wo, Peripheral, Memory> { - self.conf.transfer_direction.buffers_mut_unchecked() - } -} - -pub struct Ongoing<'wo, Peripheral, Memory, CXX> -where - Peripheral: Payload, - Memory: Payload, - CXX: ChannelId, -{ - pub(super) stream: Stream, - pub(super) buffers: TransferBuffers<'wo, Peripheral, Memory>, -} - -impl private::Sealed - for Ongoing<'_, Peripheral, Memory, CXX> -where - Peripheral: Payload, - Memory: Payload, - CXX: ChannelId, -{ -} - -impl<'wo, Peripheral, Memory, CXX> TransferState<'wo> - for Ongoing<'wo, Peripheral, Memory, CXX> -where - Peripheral: Payload, - Memory: Payload, - CXX: ChannelId, -{ - type Peripheral = Peripheral; - type Memory = Memory; - - fn buffers(&self) -> &TransferBuffers<'wo, Peripheral, Memory> { - &self.buffers - } - - fn buffers_mut(&mut self, op: F) - where - for<'a> F: FnOnce(&'a mut TransferBuffers<'wo, Peripheral, Memory>), - { - op(&mut self.buffers) - } - - unsafe fn buffers_mut_unchecked( - &mut self, - ) -> &mut TransferBuffers<'wo, Peripheral, Memory> { - &mut self.buffers - } -} - -/// # Safety -/// -/// * `Self` must be valid for any bit representation -/// * `Self::Size` must be equal to actual size -pub unsafe trait Payload: - Sized + Clone + Copy + Send + Sync + 'static -{ - type Size: IPayloadSize; -} - -// Maps Payload size to number of bytes -int_enum! { - PayloadSize <=> usize, - "Payload Size", - Byte <=> 1, - HalfWord <=> 2, - Word <=> 4 -} - -impl From for MSize { - fn from(val: PayloadSize) -> Self { - match val { - PayloadSize::Byte => MSize::Byte, - PayloadSize::HalfWord => MSize::HalfWord, - PayloadSize::Word => MSize::Word, - } - } -} - -impl From for PayloadSize { - fn from(val: MSize) -> Self { - match val { - MSize::Byte => PayloadSize::Byte, - MSize::HalfWord => PayloadSize::HalfWord, - MSize::Word => PayloadSize::Word, - } - } -} - -impl From for PSize { - fn from(val: PayloadSize) -> Self { - match val { - PayloadSize::Byte => PSize::Byte, - PayloadSize::HalfWord => PSize::HalfWord, - PayloadSize::Word => PSize::Word, - } - } -} - -impl From for PayloadSize { - fn from(val: PSize) -> Self { - match val { - PSize::Byte => PayloadSize::Byte, - PSize::HalfWord => PayloadSize::HalfWord, - PSize::Word => PayloadSize::Word, - } - } -} - -impl PayloadSize { - pub fn from_payload() -> Self { - let size = P::Size::SIZE; - - debug_assert_eq!(mem::size_of::

(), size.into()); - - size - } -} - -pub trait IPayloadSize { - const SIZE: PayloadSize; -} - -pub struct Byte; -pub struct HalfWord; -pub struct Word; - -impl IPayloadSize for Byte { - const SIZE: PayloadSize = PayloadSize::Byte; -} -impl IPayloadSize for HalfWord { - const SIZE: PayloadSize = PayloadSize::HalfWord; -} -impl IPayloadSize for Word { - const SIZE: PayloadSize = PayloadSize::Word; -} - -unsafe impl Payload for u8 { - type Size = Byte; -} - -unsafe impl Payload for i8 { - type Size = Byte; -} - -unsafe impl Payload for u16 { - type Size = HalfWord; -} - -unsafe impl Payload for i16 { - type Size = HalfWord; -} - -unsafe impl Payload for u32 { - type Size = Word; -} - -unsafe impl Payload for i32 { - type Size = Word; -} - -unsafe impl Payload for f32 { - type Size = Word; -} - -#[derive(Debug)] -pub struct MemoryBuffer -where - Memory: Payload, -{ - buffer: Buffer<'static, Memory>, -} - -impl MemoryBuffer -where - Memory: Payload, -{ - pub fn new(buffer: Buffer<'static, Memory>) -> Self { - let s = Self { buffer }; - - s.check_self(); - - s - } - - pub fn get(&self) -> &Buffer<'static, Memory> { - &self.buffer - } - - pub fn get_mut(&mut self, op: F) - where - for<'a> F: FnOnce(&'a mut Buffer<'static, Memory>), - { - op(&mut self.buffer); - - self.check_self(); - } - - pub unsafe fn get_mut_unchecked(&mut self) -> &mut Buffer<'static, Memory> { - &mut self.buffer - } - - pub fn free(self) -> Buffer<'static, Memory> { - self.buffer - } - - fn check_self(&self) { - if let Buffer::Incremented(IncrementedBuffer::WordOffset(_)) = - &self.buffer - { - panic!("Memory Buffer can't have word offset."); - } - } -} - -#[derive(Debug, EnumAsInner)] -pub enum MemoryBufferType -where - Memory: Payload, -{ - SingleBuffer(MemoryBuffer), - DoubleBuffer(DoubleBuffer), -} - -impl MemoryBufferType -where - Memory: Payload, -{ - pub fn is_single_buffer(&self) -> bool { - self.as_single_buffer().is_some() - } - - pub fn is_double_buffer(&self) -> bool { - self.as_double_buffer().is_some() - } - - pub fn is_read(&self) -> bool { - match self { - MemoryBufferType::SingleBuffer(buffer) => buffer.get().is_read(), - MemoryBufferType::DoubleBuffer(buffer) => { - buffer.memories[0].get().is_read() - } - } - } - - pub fn is_write(&self) -> bool { - !self.is_read() - } - - pub fn m0a(&self) -> &MemoryBuffer { - match self { - Self::SingleBuffer(buffer) => &buffer, - Self::DoubleBuffer(buffer) => &buffer.memories()[0], - } - } -} - -#[derive(Debug)] -pub struct DoubleBuffer -where - Memory: Payload, -{ - memories: [MemoryBuffer; 2], -} - -impl DoubleBuffer -where - Memory: Payload, -{ - pub fn new(memories: [MemoryBuffer; 2]) -> Self { - let s = Self { memories }; - - s.check_self(); - - s - } - - pub fn memories(&self) -> &[MemoryBuffer; 2] { - &self.memories - } - - /// Exposes a mutable reference to the double buffer inside a closure. - /// - /// At the end, the double buffer will be checked. - /// - /// If the closure is too limiting, consider using the unchecked version. - pub fn memories_mut(&mut self, op: F) - where - for<'a> F: FnOnce(&'a mut [MemoryBuffer; 2]), - { - op(&mut self.memories); - - self.check_self(); - } - - /// Returns mutable reference to the double buffer. - /// - /// # Safety - /// - /// This is unsafe because - by `mem::replace`ing the buffers - the api contract of both buffers - /// having the same characteristics (fixed/incremented, read/write) can be violated. - /// This may result in breaking the aliasing rules and subsequently undefined behaviour. - /// - /// This is safe as long as you don't `mem::replace` the buffers, or at least ensure that - /// both buffers have the same characteristics afterwards. - pub unsafe fn memories_mut_unchecked( - &mut self, - ) -> &mut [MemoryBuffer; 2] { - &mut self.memories - } - - pub fn free(self) -> [MemoryBuffer; 2] { - self.memories - } - - fn check_self(&self) { - assert_eq!( - self.memories[0].get().is_read(), - self.memories[1].get().is_read() - ); - assert_eq!( - self.memories[0].get().is_fixed(), - self.memories[1].get().is_fixed() - ); - - if self.memories[0].get().is_incremented() { - assert_eq!( - self.memories[0].get().as_incremented().unwrap().len(), - self.memories[1].get().as_incremented().unwrap().len() - ); - } - } -} - -#[derive(Debug, EnumAsInner)] -pub enum TransferDirection<'wo, Peripheral, Memory> -where - Peripheral: Payload, - Memory: Payload, -{ - P2M(PeripheralToMemory<'wo, Peripheral, Memory>), - M2P(MemoryToPeripheral<'wo, Peripheral, Memory>), - M2M(MemoryToMemory<'wo, Peripheral, Memory>), -} - -impl<'wo, Peripheral, Memory> TransferDirection<'wo, Peripheral, Memory> -where - Peripheral: Payload, - Memory: Payload, -{ - pub fn buffers(&self) -> &TransferBuffers<'wo, Peripheral, Memory> { - match self { - TransferDirection::P2M(p2m) => p2m.buffers(), - TransferDirection::M2P(m2p) => m2p.buffers(), - TransferDirection::M2M(m2m) => m2m.buffers(), - } - } - - pub fn buffers_mut(&mut self, op: F) - where - for<'a> F: FnOnce(&'a mut TransferBuffers<'wo, Peripheral, Memory>), - { - match self { - TransferDirection::P2M(p2m) => p2m.buffers_mut(move |b| op(b)), - TransferDirection::M2P(m2p) => m2p.buffers_mut(move |b| op(b)), - TransferDirection::M2M(m2m) => m2m.buffers_mut(move |b| op(b)), - } - } - - pub unsafe fn buffers_mut_unchecked( - &mut self, - ) -> &mut TransferBuffers<'wo, Peripheral, Memory> { - match self { - TransferDirection::P2M(p2m) => p2m.buffers_mut_unchecked(), - TransferDirection::M2P(m2p) => m2p.buffers_mut_unchecked(), - TransferDirection::M2M(m2m) => m2m.buffers_mut_unchecked(), - } - } - - pub fn free(self) -> TransferBuffers<'wo, Peripheral, Memory> { - match self { - TransferDirection::P2M(p2m) => p2m.free(), - TransferDirection::M2P(m2p) => m2p.free(), - TransferDirection::M2M(m2m) => m2m.free(), - } - } -} - -#[derive(Debug)] -pub struct PeripheralToMemory<'wo, Peripheral, Memory> -where - Peripheral: Payload, - Memory: Payload, -{ - buffers: TransferBuffers<'wo, Peripheral, Memory>, -} - -impl<'wo, Peripheral, Memory> PeripheralToMemory<'wo, Peripheral, Memory> -where - Peripheral: Payload, - Memory: Payload, -{ - pub fn new(buffers: TransferBuffers<'wo, Peripheral, Memory>) -> Self { - let s = Self { buffers }; - - s.check_self(); - - s - } - - pub fn buffers(&self) -> &TransferBuffers<'wo, Peripheral, Memory> { - &self.buffers - } - - pub fn buffers_mut(&mut self, op: F) - where - for<'a> F: FnOnce(&'a mut TransferBuffers<'wo, Peripheral, Memory>), - { - op(&mut self.buffers); - - self.check_self(); - } - - pub unsafe fn buffers_mut_unchecked( - &mut self, - ) -> &mut TransferBuffers<'wo, Peripheral, Memory> { - &mut self.buffers - } - - pub fn free(self) -> TransferBuffers<'wo, Peripheral, Memory> { - self.buffers - } - - fn check_self(&self) { - assert!(self.buffers.get().peripheral_buffer.is_read()); - assert!(self.buffers.get().memory_buffer.is_read()); - } -} - -#[derive(Debug)] -pub struct MemoryToPeripheral<'wo, Peripheral, Memory> -where - Peripheral: Payload, - Memory: Payload, -{ - buffers: TransferBuffers<'wo, Peripheral, Memory>, -} - -impl<'wo, Peripheral, Memory> MemoryToPeripheral<'wo, Peripheral, Memory> -where - Peripheral: Payload, - Memory: Payload, -{ - pub fn new(buffers: TransferBuffers<'wo, Peripheral, Memory>) -> Self { - let s = Self { buffers }; - - s.check_self(); - - s - } - - pub fn buffers(&self) -> &TransferBuffers<'wo, Peripheral, Memory> { - &self.buffers - } - - pub fn buffers_mut(&mut self, op: F) - where - for<'a> F: FnOnce(&'a mut TransferBuffers<'wo, Peripheral, Memory>), - { - op(&mut self.buffers); - - self.check_self(); - } - - pub unsafe fn buffers_mut_unchecked( - &mut self, - ) -> &mut TransferBuffers<'wo, Peripheral, Memory> { - &mut self.buffers - } - - pub fn free(self) -> TransferBuffers<'wo, Peripheral, Memory> { - self.buffers - } - - fn check_self(&self) { - assert!(self.buffers.get().peripheral_buffer.is_write()); - assert!(self.buffers.get().memory_buffer.is_read()); - } -} - -#[derive(Debug)] -pub struct MemoryToMemory<'wo, Source, Dest> -where - Source: Payload, - Dest: Payload, -{ - buffers: TransferBuffers<'wo, Source, Dest>, -} - -impl<'wo, Source, Dest> MemoryToMemory<'wo, Source, Dest> -where - Source: Payload, - Dest: Payload, -{ - pub fn new(buffers: TransferBuffers<'wo, Source, Dest>) -> Self { - let s = Self { buffers }; - - s.check_self(); - - s - } - - pub fn buffers(&self) -> &TransferBuffers<'wo, Source, Dest> { - &self.buffers - } - - pub fn buffers_mut(&mut self, op: F) - where - for<'a> F: FnOnce(&'a mut TransferBuffers<'wo, Source, Dest>), - { - op(&mut self.buffers); - - self.check_self(); - } - - pub unsafe fn buffers_mut_unchecked( - &mut self, - ) -> &mut TransferBuffers<'wo, Source, Dest> { - &mut self.buffers - } - - pub fn source_buffer(&self) -> &Buffer<'wo, Source> { - &self.buffers.get().peripheral_buffer - } - - pub fn dest_buffer(&self) -> &MemoryBuffer { - &self.buffers.get().memory_buffer.as_single_buffer().unwrap() - } - - pub fn dest_buffer_mut(&mut self, op: F) - where - for<'a> F: FnOnce(&'a mut MemoryBuffer), - { - self.buffers.get_mut(move |b| { - op(&mut b.memory_buffer.as_single_buffer_mut().unwrap()) - }); - } - - pub unsafe fn dest_buffer_mut_unchecked( - &mut self, - ) -> &mut MemoryBuffer { - self.buffers - .get_mut_unchecked() - .memory_buffer - .as_single_buffer_mut() - .unwrap() - } - - pub fn free(self) -> TransferBuffers<'wo, Source, Dest> { - self.buffers - } - - fn check_self(&self) { - assert!(self.buffers.get().peripheral_buffer.is_read()); - assert!(self.buffers.get().memory_buffer.is_write()); - - assert!(self.buffers.get().memory_buffer.is_single_buffer()); - } -} - -#[derive(Debug)] -pub struct Config<'wo, Peripheral, Memory> -where - Peripheral: Payload, - Memory: Payload, -{ - transfer_direction: TransferDirection<'wo, Peripheral, Memory>, - additional_config: AdditionalConfig, -} - -impl<'wo, Peripheral, Memory> Config<'wo, Peripheral, Memory> -where - Peripheral: Payload, - Memory: Payload, -{ - pub fn new( - transfer_direction: TransferDirection<'wo, Peripheral, Memory>, - additional_config: AdditionalConfig, - ) -> Self { - let s = Self { - transfer_direction, - additional_config, - }; - - s.check_self(); - - s - } - - pub fn additional_config(&self) -> AdditionalConfig { - self.additional_config - } - - pub fn transfer_direction( - &self, - ) -> &TransferDirection<'wo, Peripheral, Memory> { - &self.transfer_direction - } - - pub fn transfer_direction_conf(&self) -> TransferDirectionConf { - match self.transfer_direction() { - TransferDirection::P2M(_) => { - TransferDirectionConf::P2M(self.not_m2m_conf()) - } - TransferDirection::M2P(_) => { - TransferDirectionConf::M2P(self.not_m2m_conf()) - } - TransferDirection::M2M(_) => { - TransferDirectionConf::M2M(self.fifo_conf().unwrap()) - } - } - } - - fn not_m2m_conf(&self) -> NotM2MConf { - NotM2MConf { - transfer_mode: self.transfer_mode_conf(), - flow_controller: self.flow_controller_conf(), - } - } - - fn transfer_mode_conf(&self) -> TransferModeConf { - self.additional_config.transfer_mode.into_stream_conf( - Some(self.m_size()), - self.pinc(), - self.pincos(), - ) - } - - fn flow_controller_conf(&self) -> FlowControllerConf { - self.additional_config - .flow_controller - .into_stream_conf(self.m1a()) - } - - fn pinc(&self) -> Pinc { - let buffers = self.buffers().get(); - - if buffers.peripheral_buffer.is_fixed() { - Pinc::Fixed - } else { - Pinc::Incremented - } - } - - fn pincos(&self) -> Option { - let buffers = self.buffers().get(); - - match &buffers.peripheral_buffer { - Buffer::Fixed(_) => None, - Buffer::Incremented(buffer) => match buffer { - IncrementedBuffer::RegularOffset(_) => Some(Pincos::PSize), - IncrementedBuffer::WordOffset(_) => Some(Pincos::Word), - }, - } - } - - fn minc(&self) -> Minc { - let buffers = self.buffers().get(); - - match &buffers.memory_buffer.m0a().get() { - Buffer::Fixed(_) => Minc::Fixed, - Buffer::Incremented(_) => Minc::Incremented, - } - } - - fn m_size(&self) -> MSize { - PayloadSize::from_payload::().into() - } - - fn fifo_conf(&self) -> Option { - if let TransferModeTransferConf::Fifo(conf) = - self.additional_config.transfer_mode - { - Some(conf.into_stream_conf( - self.m_size(), - self.pinc(), - self.pincos(), - )) - } else { - None - } - } - - pub fn pa(&self) -> Pa { - Pa(self.buffers().get().peripheral_buffer.as_ptr(Some(0)) as u32) - } - - pub fn m0a(&self) -> M0a { - match &self.buffers().get().memory_buffer { - MemoryBufferType::SingleBuffer(memory) => { - M0a(memory.get().as_ptr(Some(0)) as u32) - } - MemoryBufferType::DoubleBuffer(double) => { - M0a(double.memories()[0].get().as_ptr(Some(0)) as u32) - } - } - } - - pub fn m1a(&self) -> Option { - if let MemoryBufferType::DoubleBuffer(buffer) = - &self.buffers().get().memory_buffer - { - Some(M1a(buffer.memories()[1].get().as_ptr(Some(0)) as u32)) - } else { - None - } - } - - pub fn stream_config(&self, conf: &mut StreamConfig) { - conf.transfer_direction = self.transfer_direction_conf(); - - let buffers = self.buffers().get(); - - // Configure ndt - - match &buffers.peripheral_buffer { - Buffer::Fixed(_) => { - match buffers.memory_buffer.m0a().get() { - Buffer::Fixed(_) => { - // NDT must be configured in advance - } - Buffer::Incremented(buffer) => { - let p_size: usize = - PayloadSize::from_payload::().into(); - let m_size: usize = - PayloadSize::from_payload::().into(); - - let memory_bytes = buffer.len() * m_size; - - if memory_bytes % p_size != 0 { - panic!("Last transfer may be incomplete."); - } - - let ndt = u16::try_from(memory_bytes / p_size).unwrap(); - conf.ndt = Ndt(ndt); - } - } - } - Buffer::Incremented(buffer) => { - let ndt = u16::try_from(buffer.len()).unwrap(); - conf.ndt = Ndt(ndt); - } - } - - // Configure addresses - // Note: M1a is already configured in `self.transfer_direction_conf()` - - conf.pa = self.pa(); - conf.m0a = self.m0a(); - - // Configure Incrementing - // Note: Pinc is already configured in `self.transfer_direction_conf()` - - conf.minc = self.minc(); - } - - pub fn buffers(&self) -> &TransferBuffers<'wo, Peripheral, Memory> { - self.transfer_direction.buffers() - } - - pub fn buffers_mut(&mut self, op: F) - where - for<'a> F: FnOnce(&'a mut TransferBuffers<'wo, Peripheral, Memory>), - { - self.transfer_direction.buffers_mut(|b| op(b)); - - self.check_self(); - } - - pub unsafe fn buffers_mut_unchecked( - &mut self, - ) -> &mut TransferBuffers<'wo, Peripheral, Memory> { - self.transfer_direction.buffers_mut_unchecked() - } - - pub fn free(self) -> TransferDirection<'wo, Peripheral, Memory> { - self.transfer_direction - } - - fn check_self(&self) { - let buffers = self.buffers().get(); - // Check Buffer Mode - - if matches!( - self.additional_config.flow_controller, - FlowControllerTransferConf::Dma( - CircularModeTransferConf::Enabled( - BufferModeTransferConf::DoubleBuffer(_), - ), - ) - ) { - assert!(buffers.memory_buffer.is_double_buffer()); - } else { - assert!(buffers.memory_buffer.is_single_buffer()); - } - - // Check Transfer Direction - - if matches!(self.transfer_direction(), TransferDirection::M2M(_)) { - assert!(matches!( - self.additional_config.transfer_mode, - TransferModeTransferConf::Fifo(_) - )); - assert!(matches!( - self.additional_config.flow_controller, - FlowControllerTransferConf::Dma( - CircularModeTransferConf::Disabled - ) - )); - } - - // Check Transfer Mode - - if matches!( - self.additional_config.transfer_mode, - TransferModeTransferConf::Direct - ) { - assert_eq!(Peripheral::Size::SIZE, Memory::Size::SIZE); - } - - // Check Incrementing - } -} - -#[derive(Debug)] -pub struct Buffers<'wo, Peripheral, Memory> -where - Peripheral: Payload, - Memory: Payload, -{ - pub peripheral_buffer: Buffer<'wo, Peripheral>, - pub memory_buffer: MemoryBufferType, -} - -#[derive(Debug)] -pub struct TransferBuffers<'wo, Peripheral, Memory> -where - Peripheral: Payload, - Memory: Payload, -{ - buffers: Buffers<'wo, Peripheral, Memory>, -} - -impl<'wo, Peripheral, Memory> TransferBuffers<'wo, Peripheral, Memory> -where - Peripheral: Payload, - Memory: Payload, -{ - /// # Args - /// - /// * `peripheral_buffer`: Usually `Buffer::Peripheral`, except for `M2M`-transfers (Memory to Memory), where the source buffer is `Buffer::Memory`. - /// * `memory_buffer`: The `MemoryBuffer` of the transfer. - pub fn new(buffers: Buffers<'wo, Peripheral, Memory>) -> Self { - let s = Self { buffers }; - - s.check_self(); - - s - } - - pub fn get(&self) -> &Buffers<'wo, Peripheral, Memory> { - &self.buffers - } - - pub fn get_mut(&mut self, op: F) - where - for<'a> F: FnOnce(&'a mut Buffers<'wo, Peripheral, Memory>), - { - op(&mut self.buffers); - - self.check_self(); - } - - pub unsafe fn get_mut_unchecked( - &mut self, - ) -> &mut Buffers<'wo, Peripheral, Memory> { - &mut self.buffers - } - - pub fn free(self) -> Buffers<'wo, Peripheral, Memory> { - self.buffers - } - - fn check_self(&self) { - assert_ne!( - self.buffers.peripheral_buffer.is_read(), - self.buffers.memory_buffer.is_read() - ); - } -} - -#[derive(Debug, Clone, Copy)] -pub struct AdditionalConfig { - pub transfer_mode: TransferModeTransferConf, - pub flow_controller: FlowControllerTransferConf, -} - -#[derive(Copy, Clone, PartialEq, Eq, Debug)] -pub enum TransferModeTransferConf { - Direct, - Fifo(FifoTransferConf), -} - -impl TransferModeTransferConf { - pub fn into_stream_conf( - self, - m_size: Option, - pinc: Pinc, - pincos: Option, - ) -> TransferModeConf { - match self { - Self::Direct => TransferModeConf::Direct(DirectConf { pinc }), - Self::Fifo(fifo) => TransferModeConf::Fifo(fifo.into_stream_conf( - m_size.unwrap(), - pinc, - pincos, - )), - } - } -} - -impl From for TransferModeTransferConf { - fn from(x: TransferModeConf) -> Self { - match x { - TransferModeConf::Direct(_) => Self::Direct, - TransferModeConf::Fifo(fifo) => Self::Fifo(fifo.into()), - } - } -} - -#[derive(Copy, Clone, PartialEq, Eq, Debug)] -pub struct FifoTransferConf { - pub fifo_threshold: FifoThreshold, - pub p_burst: PBurstTransferConf, - pub m_burst: MBurst, -} - -impl FifoTransferConf { - pub fn into_stream_conf( - self, - m_size: MSize, - pinc: Pinc, - pincos: Option, - ) -> FifoConf { - FifoConf { - fifo_threshold: self.fifo_threshold, - p_burst: self.p_burst.into_stream_conf(pinc, pincos), - m_burst: self.m_burst, - m_size, - } - } -} - -impl From for FifoTransferConf { - fn from(x: FifoConf) -> Self { - Self { - fifo_threshold: x.fifo_threshold, - p_burst: x.p_burst.into(), - m_burst: x.m_burst, - } - } -} - -#[derive(Copy, Clone, PartialEq, Eq, Debug)] -pub enum PBurstTransferConf { - Single, - Incr4, - Incr8, - Incr16, -} - -impl PBurstTransferConf { - pub fn into_stream_conf( - self, - pinc: Pinc, - pincos: Option, - ) -> PBurstConf { - match self { - Self::Single => { - let pinc_conf = match pinc { - Pinc::Fixed => PincConf::Fixed, - Pinc::Incremented => PincConf::Incremented(pincos.unwrap()), - }; - - PBurstConf::Single(pinc_conf) - } - Self::Incr4 => PBurstConf::Incr4(pinc), - Self::Incr8 => PBurstConf::Incr8(pinc), - Self::Incr16 => PBurstConf::Incr16(pinc), - } - } -} - -impl From for PBurstTransferConf { - fn from(x: PBurstConf) -> Self { - match x { - PBurstConf::Single(_) => Self::Single, - PBurstConf::Incr4(_) => Self::Incr4, - PBurstConf::Incr8(_) => Self::Incr8, - PBurstConf::Incr16(_) => Self::Incr16, - } - } -} - -#[derive(Copy, Clone, PartialEq, Eq, Debug)] -pub enum FlowControllerTransferConf { - Dma(CircularModeTransferConf), - Peripheral, -} - -impl FlowControllerTransferConf { - pub fn into_stream_conf(self, m1a: Option) -> FlowControllerConf { - match self { - Self::Dma(circular) => { - FlowControllerConf::Dma(circular.into_stream_conf(m1a)) - } - Self::Peripheral => FlowControllerConf::Peripheral, - } - } -} - -impl From for FlowControllerTransferConf { - fn from(x: FlowControllerConf) -> Self { - match x { - FlowControllerConf::Dma(circ) => Self::Dma(circ.into()), - FlowControllerConf::Peripheral => Self::Peripheral, - } - } -} - -#[derive(Copy, Clone, PartialEq, Eq, Debug)] -pub enum CircularModeTransferConf { - Disabled, - Enabled(BufferModeTransferConf), -} - -impl CircularModeTransferConf { - pub fn into_stream_conf(self, m1a: Option) -> CircularModeConf { - match self { - Self::Disabled => CircularModeConf::Disabled, - Self::Enabled(buffer_mode) => { - CircularModeConf::Enabled(buffer_mode.into_stream_conf(m1a)) - } - } - } -} - -impl From for CircularModeTransferConf { - fn from(x: CircularModeConf) -> Self { - match x { - CircularModeConf::Disabled => Self::Disabled, - CircularModeConf::Enabled(buffer_mode) => { - Self::Enabled(buffer_mode.into()) - } - } - } -} - -#[derive(Copy, Clone, PartialEq, Eq, Debug)] -pub enum BufferModeTransferConf { - Regular, - DoubleBuffer(DoubleBufferTransferConf), -} - -impl BufferModeTransferConf { - pub fn into_stream_conf(self, m1a: Option) -> BufferModeConf { - match self { - Self::Regular => BufferModeConf::Regular, - Self::DoubleBuffer(conf) => BufferModeConf::DoubleBuffer( - conf.into_stream_conf(m1a.unwrap()), - ), - } - } -} - -impl From for BufferModeTransferConf { - fn from(x: BufferModeConf) -> Self { - match x { - BufferModeConf::Regular => Self::Regular, - BufferModeConf::DoubleBuffer(conf) => { - Self::DoubleBuffer(DoubleBufferTransferConf { - current_target: conf.current_target, - }) - } - } - } -} - -#[derive(Copy, Clone, PartialEq, Eq, Debug)] -pub struct DoubleBufferTransferConf { - pub current_target: CurrentTarget, -} - -impl DoubleBufferTransferConf { - pub fn into_stream_conf(self, m1a: M1a) -> DoubleBufferConf { - DoubleBufferConf { - current_target: self.current_target, - m1a, - } - } -} - -impl From for DoubleBufferTransferConf { - fn from(x: DoubleBufferConf) -> Self { - Self { - current_target: x.current_target, - } - } -} - -#[derive(Copy, Clone, Debug, EnumAsInner)] -pub enum PayloadPort -where - Peripheral: Payload, - Memory: Payload, -{ - Peripheral(Peripheral), - Memory(Memory), -} - -#[derive(Debug, EnumAsInner)] -pub enum PointerPort -where - Peripheral: Payload, - Memory: Payload, -{ - Peripheral(*mut Peripheral), - Memory(*mut Memory), -} - -#[derive(Debug, EnumAsInner)] -pub enum Buffer<'wo, P> -where - P: Payload, -{ - Fixed(FixedBuffer

), - Incremented(IncrementedBuffer<'wo, P>), -} - -impl<'wo, P> Buffer<'wo, P> -where - P: Payload, -{ - pub unsafe fn get(&self, index: Option) -> P { - match self { - Buffer::Fixed(buffer) => buffer.get(), - Buffer::Incremented(buffer) => buffer.get(index.unwrap()), - } - } - - pub fn as_ptr(&self, index: Option) -> *const P { - match self { - Buffer::Fixed(buffer) => buffer.as_ptr(), - Buffer::Incremented(buffer) => buffer.as_ptr(index.unwrap()), - } - } - - pub fn is_read(&self) -> bool { - match self { - Buffer::Fixed(buffer) => buffer.is_read(), - Buffer::Incremented(buffer) => buffer.is_read(), - } - } - - pub fn is_write(&self) -> bool { - match self { - Buffer::Fixed(buffer) => buffer.is_write(), - Buffer::Incremented(buffer) => buffer.is_write(), - } - } - - pub fn is_fixed(&self) -> bool { - if let Self::Fixed(_) = self { - true - } else { - false - } - } - - pub fn is_incremented(&self) -> bool { - if let Self::Incremented(_) = self { - true - } else { - false - } - } -} - -#[derive(Debug, EnumAsInner)] -pub enum IncrementedBuffer<'wo, P> -where - P: Payload, -{ - RegularOffset(RegularOffsetBuffer

), - WordOffset(WordOffsetBuffer<'wo, P>), -} - -impl<'wo, P> IncrementedBuffer<'wo, P> -where - P: Payload, -{ - pub fn is_regular_offset(&self) -> bool { - if let IncrementedBuffer::RegularOffset(_) = self { - true - } else { - false - } - } - - pub fn is_word_offset(&self) -> bool { - if let IncrementedBuffer::WordOffset(_) = self { - true - } else { - false - } - } - - pub fn len(&self) -> usize { - match self { - IncrementedBuffer::RegularOffset(buffer) => buffer.len(), - IncrementedBuffer::WordOffset(buffer) => buffer.len(), - } - } - - pub unsafe fn get(&self, index: usize) -> P { - match self { - IncrementedBuffer::RegularOffset(buffer) => buffer.get(index), - IncrementedBuffer::WordOffset(buffer) => buffer.get(index), - } - } - - pub fn as_ptr(&self, index: usize) -> *const P { - match self { - IncrementedBuffer::RegularOffset(buffer) => buffer.as_ptr(index), - IncrementedBuffer::WordOffset(buffer) => buffer.as_ptr(index), - } - } - - pub fn is_read(&self) -> bool { - match self { - IncrementedBuffer::RegularOffset(buffer) => buffer.is_read(), - IncrementedBuffer::WordOffset(buffer) => buffer.is_read(), - } - } - - pub fn is_write(&self) -> bool { - match self { - IncrementedBuffer::RegularOffset(buffer) => buffer.is_write(), - IncrementedBuffer::WordOffset(buffer) => buffer.is_write(), - } - } -} - -#[derive(Debug, EnumAsInner)] -pub enum FixedBuffer

-where - P: Payload, -{ - Read(FixedBufferR

), - Write(FixedBufferW

), -} - -impl

FixedBuffer

-where - P: Payload, -{ - pub fn is_read(&self) -> bool { - match self { - FixedBuffer::Read(_) => true, - FixedBuffer::Write(_) => false, - } - } - - pub fn is_write(&self) -> bool { - match self { - FixedBuffer::Write(_) => true, - FixedBuffer::Read(_) => false, - } - } - - pub unsafe fn get(&self) -> P { - match self { - FixedBuffer::Read(buffer) => buffer.get(), - FixedBuffer::Write(buffer) => buffer.get(), - } - } - - pub fn as_ptr(&self) -> *const P { - match self { - FixedBuffer::Read(buffer) => buffer.as_ptr(), - FixedBuffer::Write(buffer) => buffer.as_ptr(), - } - } -} - -#[derive(Debug, Clone, Copy)] -pub struct FixedBufferR

(*const P) -where - P: Payload; - -impl

FixedBufferR

-where - P: Payload, -{ - pub fn new(buffer: &'static P) -> Self { - FixedBufferR(buffer) - } - - pub fn get(self) -> P { - unsafe { self.0.read_volatile() } - } - - pub fn as_ptr(self) -> *const P { - self.0 - } -} - -unsafe impl

Send for FixedBufferR

where P: Payload {} - -unsafe impl

Sync for FixedBufferR

where P: Payload {} - -#[derive(Debug)] -pub struct FixedBufferW

(*mut P) -where - P: Payload; - -impl

FixedBufferW

-where - P: Payload, -{ - pub fn new(buffer: &'static mut P) -> Self { - FixedBufferW(buffer) - } - - /// # Safety - /// - /// - The caller must ensure, that the DMA is currently not writing this address. - pub unsafe fn get(&self) -> P { - ptr::read_volatile(self.0) - } - - /// # Safety - /// - /// - The caller must ensure, that the DMA is currently not writing this address. - pub unsafe fn set(&mut self, buf: P) { - ptr::write_volatile(self.0, buf); - } - - pub fn as_ptr(&self) -> *const P { - self.0 - } - - pub fn as_mut_ptr(&mut self) -> *mut P { - self.0 - } -} - -unsafe impl

Send for FixedBufferW

where P: Payload {} - -unsafe impl

Sync for FixedBufferW

where P: Payload {} - -#[derive(Debug, EnumAsInner)] -pub enum RegularOffsetBuffer

-where - P: Payload, -{ - Read(RegularOffsetBufferR

), - Write(RegularOffsetBufferW

), -} - -impl

RegularOffsetBuffer

-where - P: Payload, -{ - pub fn is_read(&self) -> bool { - match self { - RegularOffsetBuffer::Read(_) => true, - RegularOffsetBuffer::Write(_) => false, - } - } - - pub fn is_write(&self) -> bool { - match self { - RegularOffsetBuffer::Write(_) => true, - RegularOffsetBuffer::Read(_) => false, - } - } - - // Methods both variants implement - - pub unsafe fn get(&self, index: usize) -> P { - match self { - RegularOffsetBuffer::Read(buffer) => buffer.get(index), - RegularOffsetBuffer::Write(buffer) => buffer.get(index), - } - } - - pub fn as_ptr(&self, index: usize) -> *const P { - match self { - RegularOffsetBuffer::Read(buffer) => buffer.as_ptr(index), - RegularOffsetBuffer::Write(buffer) => buffer.as_ptr(index), - } - } - - pub fn len(&self) -> usize { - match self { - RegularOffsetBuffer::Read(buffer) => buffer.len(), - RegularOffsetBuffer::Write(buffer) => buffer.len(), - } - } -} - -#[derive(Debug, Clone, Copy)] -pub struct RegularOffsetBufferR

(*const [P]) -where - P: Payload; - -#[allow(clippy::len_without_is_empty)] -impl

RegularOffsetBufferR

-where - P: Payload, -{ - pub fn new(buffer: &'static [P]) -> Self { - check_buffer_not_empty(buffer); - - RegularOffsetBufferR(buffer) - } - - pub fn get(self, index: usize) -> P { - unsafe { read_volatile_slice_buffer(self.0, index) } - } - - pub fn as_ptr(self, index: usize) -> *const P { - unsafe { - let slice = &*self.0; - &slice[index] as *const _ - } - } - - pub fn len(self) -> usize { - unsafe { - let slice = &*self.0; - slice.len() - } - } -} - -unsafe impl

Send for RegularOffsetBufferR

where P: Payload {} - -unsafe impl

Sync for RegularOffsetBufferR

where P: Payload {} - -#[derive(Debug)] -pub struct RegularOffsetBufferW

(*mut [P]) -where - P: Payload; - -#[allow(clippy::len_without_is_empty)] -impl

RegularOffsetBufferW

-where - P: Payload, -{ - pub fn new(buffer: &'static mut [P]) -> Self { - check_buffer_not_empty(buffer); - - RegularOffsetBufferW(buffer) - } - - /// # Safety - /// - /// - The caller must ensure, that the DMA is currently not modifying this address. - pub unsafe fn get(&self, index: usize) -> P { - read_volatile_slice_buffer(self.0, index) - } - - /// # Safety - /// - /// - The caller must ensure, that the DMA is currently not modifying this address. - pub unsafe fn set(&mut self, index: usize, item: P) { - let slice = &mut *self.0; - ptr::write_volatile(&mut slice[index] as *mut _, item); - } - - pub fn as_ptr(&self, index: usize) -> *const P { - unsafe { - let slice = &*self.0; - &slice[index] as *const _ - } - } - - pub fn as_mut_ptr(&mut self, index: usize) -> *mut P { - unsafe { - let slice = &mut *self.0; - &mut slice[index] as *mut _ - } - } - - pub fn len(&self) -> usize { - unsafe { - let slice = &*self.0; - slice.len() - } - } -} - -unsafe impl

Send for RegularOffsetBufferW

where P: Payload {} - -unsafe impl

Sync for RegularOffsetBufferW

where P: Payload {} - -unsafe fn read_volatile_slice_buffer

( - slice_ptr: *const [P], - index: usize, -) -> P -where - P: Payload, -{ - let slice = &*slice_ptr; - ptr::read_volatile(&slice[index] as *const _) -} - -#[derive(Debug, EnumAsInner)] -pub enum WordOffsetBuffer<'wo, P> -where - P: Payload, -{ - Read(WordOffsetBufferR<'wo, P>), - Write(WordOffsetBufferW<'wo, P>), -} - -impl<'wo, P> WordOffsetBuffer<'wo, P> -where - P: Payload, -{ - pub fn is_read(&self) -> bool { - match self { - WordOffsetBuffer::Read(_) => true, - WordOffsetBuffer::Write(_) => false, - } - } - - pub fn is_write(&self) -> bool { - match self { - WordOffsetBuffer::Write(_) => true, - WordOffsetBuffer::Read(_) => false, - } - } - - pub unsafe fn get(&self, index: usize) -> P { - match self { - WordOffsetBuffer::Read(buffer) => buffer.get(index), - WordOffsetBuffer::Write(buffer) => buffer.get(index), - } - } - - pub fn as_ptr(&self, index: usize) -> *const P { - match self { - WordOffsetBuffer::Read(buffer) => buffer.as_ptr(index), - WordOffsetBuffer::Write(buffer) => buffer.as_ptr(index), - } - } - - pub fn len(&self) -> usize { - match self { - WordOffsetBuffer::Read(buffer) => buffer.len(), - WordOffsetBuffer::Write(buffer) => buffer.len(), - } - } -} - -#[derive(Debug, Clone, Copy)] -pub struct WordOffsetBufferR<'wo, P>(&'wo [*const P]) -where - P: Payload; - -#[allow(clippy::len_without_is_empty)] -impl<'wo, P> WordOffsetBufferR<'wo, P> -where - P: Payload, -{ - pub fn new(buffer: &'wo [&'static P]) -> Self { - check_buffer_not_empty(buffer); - - let buffer = unsafe { &*(buffer as *const _ as *const _) }; - - check_word_offset(buffer); - - WordOffsetBufferR(buffer) - } - - pub fn get(self, index: usize) -> P { - unsafe { ptr::read_volatile(self.0[index]) } - } - - pub fn as_ptr(self, index: usize) -> *const P { - self.0[index] - } - - pub fn len(self) -> usize { - self.0.len() - } -} - -unsafe impl

Send for WordOffsetBufferR<'_, P> where P: Payload {} - -unsafe impl

Sync for WordOffsetBufferR<'_, P> where P: Payload {} - -#[derive(Debug)] -pub struct WordOffsetBufferW<'wo, P>(&'wo mut [*mut P]) -where - P: Payload; - -#[allow(clippy::len_without_is_empty)] -impl<'wo, P> WordOffsetBufferW<'wo, P> -where - P: Payload, -{ - pub fn new(buffer: &'wo mut [&'static mut P]) -> Self { - check_buffer_not_empty(buffer); - - unsafe { - check_word_offset::

(&*(buffer as *const _ as *const _)); - - WordOffsetBufferW(&mut *(buffer as *mut _ as *mut _)) - } - } - - /// # Safety - /// - /// The caller must ensure, that the DMA is currently not modifying this address. - pub unsafe fn get(&self, index: usize) -> P { - ptr::read_volatile(self.0[index]) - } - - /// # Safety - /// - /// The caller must ensure, that the DMA is currently not modifying this address. - pub unsafe fn set(&mut self, index: usize, item: P) { - ptr::write_volatile(self.0[index], item); - } - - pub fn as_ptr(&self, index: usize) -> *const P { - self.0[index] - } - - pub fn as_mut_ptr(&mut self, index: usize) -> *mut P { - self.0[index] - } - - pub fn len(&self) -> usize { - self.0.len() - } -} - -unsafe impl

Send for WordOffsetBufferW<'_, P> where P: Payload {} - -unsafe impl

Sync for WordOffsetBufferW<'_, P> where P: Payload {} - -fn check_buffer_not_empty

(buffer: &[P]) { - if buffer.is_empty() { - panic!("The buffer must not be empty."); - } -} - -// -// Safe Transfer implementations -// - -fn check_word_offset

(buffer: &[*const P]) -where - P: Payload, -{ - if buffer.is_empty() { - return; - } - - let mut last_pointer = buffer[0] as *const _ as *const u32; - - for ¤t_pointer in buffer.iter().skip(1) { - // Size of u32 is one word / 4 bytes - let current_pointer = current_pointer as *const u32; - let expected_pointer = unsafe { last_pointer.add(1) }; - if current_pointer != expected_pointer { - panic!("The offset must be one word (4 bytes)."); - } - - last_pointer = current_pointer; - } -} - -#[derive(Debug, Clone, Copy)] -pub enum WhichBuffer { - First, - Second, -} - -impl WhichBuffer { - pub fn index(self) -> usize { - match self { - WhichBuffer::First => 0, - WhichBuffer::Second => 1, - } - } -} diff --git a/src/dma/transfer/buffer.rs b/src/dma/transfer/buffer.rs new file mode 100644 index 00000000..138bde15 --- /dev/null +++ b/src/dma/transfer/buffer.rs @@ -0,0 +1,729 @@ +use super::Payload; +use core::ptr; +use enum_as_inner::EnumAsInner; + +#[derive(Debug, EnumAsInner)] +pub enum Buffer<'wo, P> +where + P: Payload, +{ + Fixed(FixedBuffer

), + Incremented(IncrementedBuffer<'wo, P>), +} + +impl<'wo, P> Buffer<'wo, P> +where + P: Payload, +{ + pub unsafe fn get(&self, index: Option) -> P { + match self { + Buffer::Fixed(buffer) => buffer.get(), + Buffer::Incremented(buffer) => buffer.get(index.unwrap()), + } + } + + pub fn as_ptr(&self, index: Option) -> *const P { + match self { + Buffer::Fixed(buffer) => buffer.as_ptr(), + Buffer::Incremented(buffer) => buffer.as_ptr(index.unwrap()), + } + } + + pub fn is_read(&self) -> bool { + match self { + Buffer::Fixed(buffer) => buffer.is_read(), + Buffer::Incremented(buffer) => buffer.is_read(), + } + } + + pub fn is_write(&self) -> bool { + match self { + Buffer::Fixed(buffer) => buffer.is_write(), + Buffer::Incremented(buffer) => buffer.is_write(), + } + } + + pub fn is_fixed(&self) -> bool { + if let Self::Fixed(_) = self { + true + } else { + false + } + } + + pub fn is_incremented(&self) -> bool { + if let Self::Incremented(_) = self { + true + } else { + false + } + } +} + +#[derive(Debug, EnumAsInner)] +pub enum IncrementedBuffer<'wo, P> +where + P: Payload, +{ + RegularOffset(RegularOffsetBuffer

), + WordOffset(WordOffsetBuffer<'wo, P>), +} + +#[allow(clippy::len_without_is_empty)] +impl<'wo, P> IncrementedBuffer<'wo, P> +where + P: Payload, +{ + pub fn is_regular_offset(&self) -> bool { + if let IncrementedBuffer::RegularOffset(_) = self { + true + } else { + false + } + } + + pub fn is_word_offset(&self) -> bool { + if let IncrementedBuffer::WordOffset(_) = self { + true + } else { + false + } + } + + pub fn len(&self) -> usize { + match self { + IncrementedBuffer::RegularOffset(buffer) => buffer.len(), + IncrementedBuffer::WordOffset(buffer) => buffer.len(), + } + } + + pub unsafe fn get(&self, index: usize) -> P { + match self { + IncrementedBuffer::RegularOffset(buffer) => buffer.get(index), + IncrementedBuffer::WordOffset(buffer) => buffer.get(index), + } + } + + pub fn as_ptr(&self, index: usize) -> *const P { + match self { + IncrementedBuffer::RegularOffset(buffer) => buffer.as_ptr(index), + IncrementedBuffer::WordOffset(buffer) => buffer.as_ptr(index), + } + } + + pub fn is_read(&self) -> bool { + match self { + IncrementedBuffer::RegularOffset(buffer) => buffer.is_read(), + IncrementedBuffer::WordOffset(buffer) => buffer.is_read(), + } + } + + pub fn is_write(&self) -> bool { + match self { + IncrementedBuffer::RegularOffset(buffer) => buffer.is_write(), + IncrementedBuffer::WordOffset(buffer) => buffer.is_write(), + } + } +} + +#[derive(Debug, EnumAsInner)] +pub enum FixedBuffer

+where + P: Payload, +{ + Read(FixedBufferR

), + Write(FixedBufferW

), +} + +impl

FixedBuffer

+where + P: Payload, +{ + pub fn is_read(&self) -> bool { + match self { + FixedBuffer::Read(_) => true, + FixedBuffer::Write(_) => false, + } + } + + pub fn is_write(&self) -> bool { + match self { + FixedBuffer::Write(_) => true, + FixedBuffer::Read(_) => false, + } + } + + pub unsafe fn get(&self) -> P { + match self { + FixedBuffer::Read(buffer) => buffer.get(), + FixedBuffer::Write(buffer) => buffer.get(), + } + } + + pub fn as_ptr(&self) -> *const P { + match self { + FixedBuffer::Read(buffer) => buffer.as_ptr(), + FixedBuffer::Write(buffer) => buffer.as_ptr(), + } + } +} + +#[derive(Debug, Clone, Copy)] +pub struct FixedBufferR

(*const P) +where + P: Payload; + +impl

FixedBufferR

+where + P: Payload, +{ + pub fn new(buffer: &'static P) -> Self { + FixedBufferR(buffer) + } + + pub fn get(self) -> P { + unsafe { self.0.read_volatile() } + } + + pub fn as_ptr(self) -> *const P { + self.0 + } +} + +unsafe impl

Send for FixedBufferR

where P: Payload {} + +unsafe impl

Sync for FixedBufferR

where P: Payload {} + +#[derive(Debug)] +pub struct FixedBufferW

(*mut P) +where + P: Payload; + +impl

FixedBufferW

+where + P: Payload, +{ + pub fn new(buffer: &'static mut P) -> Self { + FixedBufferW(buffer) + } + + /// # Safety + /// + /// - The caller must ensure, that the DMA is currently not writing this address. + pub unsafe fn get(&self) -> P { + ptr::read_volatile(self.0) + } + + /// # Safety + /// + /// - The caller must ensure, that the DMA is currently not writing this address. + pub unsafe fn set(&mut self, buf: P) { + ptr::write_volatile(self.0, buf); + } + + pub fn as_ptr(&self) -> *const P { + self.0 + } + + pub fn as_mut_ptr(&mut self) -> *mut P { + self.0 + } +} + +unsafe impl

Send for FixedBufferW

where P: Payload {} + +unsafe impl

Sync for FixedBufferW

where P: Payload {} + +#[derive(Debug, EnumAsInner)] +pub enum RegularOffsetBuffer

+where + P: Payload, +{ + Read(RegularOffsetBufferR

), + Write(RegularOffsetBufferW

), +} + +#[allow(clippy::len_without_is_empty)] +impl

RegularOffsetBuffer

+where + P: Payload, +{ + pub fn is_read(&self) -> bool { + match self { + RegularOffsetBuffer::Read(_) => true, + RegularOffsetBuffer::Write(_) => false, + } + } + + pub fn is_write(&self) -> bool { + match self { + RegularOffsetBuffer::Write(_) => true, + RegularOffsetBuffer::Read(_) => false, + } + } + + // Methods both variants implement + + pub unsafe fn get(&self, index: usize) -> P { + match self { + RegularOffsetBuffer::Read(buffer) => buffer.get(index), + RegularOffsetBuffer::Write(buffer) => buffer.get(index), + } + } + + pub fn as_ptr(&self, index: usize) -> *const P { + match self { + RegularOffsetBuffer::Read(buffer) => buffer.as_ptr(index), + RegularOffsetBuffer::Write(buffer) => buffer.as_ptr(index), + } + } + + pub fn len(&self) -> usize { + match self { + RegularOffsetBuffer::Read(buffer) => buffer.len(), + RegularOffsetBuffer::Write(buffer) => buffer.len(), + } + } +} + +#[derive(Debug, Clone, Copy)] +pub struct RegularOffsetBufferR

(*const [P]) +where + P: Payload; + +#[allow(clippy::len_without_is_empty)] +impl

RegularOffsetBufferR

+where + P: Payload, +{ + pub fn new(buffer: &'static [P]) -> Self { + check_buffer_not_empty(buffer); + + RegularOffsetBufferR(buffer) + } + + pub fn get(self, index: usize) -> P { + unsafe { read_volatile_slice_buffer(self.0, index) } + } + + pub fn as_ptr(self, index: usize) -> *const P { + unsafe { + let slice = &*self.0; + &slice[index] as *const _ + } + } + + pub fn len(self) -> usize { + unsafe { + let slice = &*self.0; + slice.len() + } + } +} + +unsafe impl

Send for RegularOffsetBufferR

where P: Payload {} + +unsafe impl

Sync for RegularOffsetBufferR

where P: Payload {} + +#[derive(Debug)] +pub struct RegularOffsetBufferW

(*mut [P]) +where + P: Payload; + +#[allow(clippy::len_without_is_empty)] +impl

RegularOffsetBufferW

+where + P: Payload, +{ + pub fn new(buffer: &'static mut [P]) -> Self { + check_buffer_not_empty(buffer); + + RegularOffsetBufferW(buffer) + } + + /// # Safety + /// + /// - The caller must ensure, that the DMA is currently not modifying this address. + pub unsafe fn get(&self, index: usize) -> P { + read_volatile_slice_buffer(self.0, index) + } + + /// # Safety + /// + /// - The caller must ensure, that the DMA is currently not modifying this address. + pub unsafe fn set(&mut self, index: usize, item: P) { + let slice = &mut *self.0; + ptr::write_volatile(&mut slice[index] as *mut _, item); + } + + pub fn as_ptr(&self, index: usize) -> *const P { + unsafe { + let slice = &*self.0; + &slice[index] as *const _ + } + } + + pub fn as_mut_ptr(&mut self, index: usize) -> *mut P { + unsafe { + let slice = &mut *self.0; + &mut slice[index] as *mut _ + } + } + + pub fn len(&self) -> usize { + unsafe { + let slice = &*self.0; + slice.len() + } + } +} + +unsafe impl

Send for RegularOffsetBufferW

where P: Payload {} + +unsafe impl

Sync for RegularOffsetBufferW

where P: Payload {} + +unsafe fn read_volatile_slice_buffer

( + slice_ptr: *const [P], + index: usize, +) -> P +where + P: Payload, +{ + let slice = &*slice_ptr; + ptr::read_volatile(&slice[index] as *const _) +} + +#[derive(Debug, EnumAsInner)] +pub enum WordOffsetBuffer<'wo, P> +where + P: Payload, +{ + Read(WordOffsetBufferR<'wo, P>), + Write(WordOffsetBufferW<'wo, P>), +} + +#[allow(clippy::len_without_is_empty)] +impl<'wo, P> WordOffsetBuffer<'wo, P> +where + P: Payload, +{ + pub fn is_read(&self) -> bool { + match self { + WordOffsetBuffer::Read(_) => true, + WordOffsetBuffer::Write(_) => false, + } + } + + pub fn is_write(&self) -> bool { + match self { + WordOffsetBuffer::Write(_) => true, + WordOffsetBuffer::Read(_) => false, + } + } + + pub unsafe fn get(&self, index: usize) -> P { + match self { + WordOffsetBuffer::Read(buffer) => buffer.get(index), + WordOffsetBuffer::Write(buffer) => buffer.get(index), + } + } + + pub fn as_ptr(&self, index: usize) -> *const P { + match self { + WordOffsetBuffer::Read(buffer) => buffer.as_ptr(index), + WordOffsetBuffer::Write(buffer) => buffer.as_ptr(index), + } + } + + pub fn len(&self) -> usize { + match self { + WordOffsetBuffer::Read(buffer) => buffer.len(), + WordOffsetBuffer::Write(buffer) => buffer.len(), + } + } +} + +#[derive(Debug, Clone, Copy)] +pub struct WordOffsetBufferR<'wo, P>(&'wo [*const P]) +where + P: Payload; + +#[allow(clippy::len_without_is_empty)] +impl<'wo, P> WordOffsetBufferR<'wo, P> +where + P: Payload, +{ + pub fn new(buffer: &'wo [&'static P]) -> Self { + check_buffer_not_empty(buffer); + + let buffer = unsafe { &*(buffer as *const _ as *const _) }; + + check_word_offset(buffer); + + WordOffsetBufferR(buffer) + } + + pub fn get(self, index: usize) -> P { + unsafe { ptr::read_volatile(self.0[index]) } + } + + pub fn as_ptr(self, index: usize) -> *const P { + self.0[index] + } + + pub fn len(self) -> usize { + self.0.len() + } +} + +unsafe impl

Send for WordOffsetBufferR<'_, P> where P: Payload {} + +unsafe impl

Sync for WordOffsetBufferR<'_, P> where P: Payload {} + +#[derive(Debug)] +pub struct WordOffsetBufferW<'wo, P>(&'wo mut [*mut P]) +where + P: Payload; + +#[allow(clippy::len_without_is_empty)] +impl<'wo, P> WordOffsetBufferW<'wo, P> +where + P: Payload, +{ + pub fn new(buffer: &'wo mut [&'static mut P]) -> Self { + check_buffer_not_empty(buffer); + + unsafe { + check_word_offset::

(&*(buffer as *const _ as *const _)); + + WordOffsetBufferW(&mut *(buffer as *mut _ as *mut _)) + } + } + + /// # Safety + /// + /// The caller must ensure, that the DMA is currently not modifying this address. + pub unsafe fn get(&self, index: usize) -> P { + ptr::read_volatile(self.0[index]) + } + + /// # Safety + /// + /// The caller must ensure, that the DMA is currently not modifying this address. + pub unsafe fn set(&mut self, index: usize, item: P) { + ptr::write_volatile(self.0[index], item); + } + + pub fn as_ptr(&self, index: usize) -> *const P { + self.0[index] + } + + pub fn as_mut_ptr(&mut self, index: usize) -> *mut P { + self.0[index] + } + + pub fn len(&self) -> usize { + self.0.len() + } +} + +unsafe impl

Send for WordOffsetBufferW<'_, P> where P: Payload {} + +unsafe impl

Sync for WordOffsetBufferW<'_, P> where P: Payload {} + +fn check_buffer_not_empty

(buffer: &[P]) { + if buffer.is_empty() { + panic!("The buffer must not be empty."); + } +} + +fn check_word_offset

(buffer: &[*const P]) +where + P: Payload, +{ + if buffer.is_empty() { + return; + } + + let mut last_pointer = buffer[0] as *const _ as *const u32; + + for ¤t_pointer in buffer.iter().skip(1) { + // Size of u32 is one word / 4 bytes + let current_pointer = current_pointer as *const u32; + let expected_pointer = unsafe { last_pointer.add(1) }; + if current_pointer != expected_pointer { + panic!("The offset must be one word (4 bytes)."); + } + + last_pointer = current_pointer; + } +} + +#[derive(Debug)] +pub struct MemoryBuffer +where + Memory: Payload, +{ + buffer: Buffer<'static, Memory>, +} + +impl MemoryBuffer +where + Memory: Payload, +{ + pub fn new(buffer: Buffer<'static, Memory>) -> Self { + let s = Self { buffer }; + + s.check_self(); + + s + } + + pub fn get(&self) -> &Buffer<'static, Memory> { + &self.buffer + } + + pub fn get_mut(&mut self, op: F) + where + for<'a> F: FnOnce(&'a mut Buffer<'static, Memory>), + { + op(&mut self.buffer); + + self.check_self(); + } + + pub unsafe fn get_mut_unchecked(&mut self) -> &mut Buffer<'static, Memory> { + &mut self.buffer + } + + pub fn free(self) -> Buffer<'static, Memory> { + self.buffer + } + + fn check_self(&self) { + if let Buffer::Incremented(IncrementedBuffer::WordOffset(_)) = + &self.buffer + { + panic!("Memory Buffer can't have word offset."); + } + } +} + +#[derive(Debug, EnumAsInner)] +pub enum MemoryBufferType +where + Memory: Payload, +{ + SingleBuffer(MemoryBuffer), + DoubleBuffer(DoubleBuffer), +} + +impl MemoryBufferType +where + Memory: Payload, +{ + pub fn is_single_buffer(&self) -> bool { + self.as_single_buffer().is_some() + } + + pub fn is_double_buffer(&self) -> bool { + self.as_double_buffer().is_some() + } + + pub fn is_read(&self) -> bool { + match self { + MemoryBufferType::SingleBuffer(buffer) => buffer.get().is_read(), + MemoryBufferType::DoubleBuffer(buffer) => { + buffer.memories[0].get().is_read() + } + } + } + + pub fn is_write(&self) -> bool { + !self.is_read() + } + + pub fn m0a(&self) -> &MemoryBuffer { + match self { + Self::SingleBuffer(buffer) => &buffer, + Self::DoubleBuffer(buffer) => &buffer.memories()[0], + } + } +} + +#[derive(Debug)] +pub struct DoubleBuffer +where + Memory: Payload, +{ + memories: [MemoryBuffer; 2], +} + +impl DoubleBuffer +where + Memory: Payload, +{ + pub fn new(memories: [MemoryBuffer; 2]) -> Self { + let s = Self { memories }; + + s.check_self(); + + s + } + + pub fn memories(&self) -> &[MemoryBuffer; 2] { + &self.memories + } + + /// Exposes a mutable reference to the double buffer inside a closure. + /// + /// At the end, the double buffer will be checked. + /// + /// If the closure is too limiting, consider using the unchecked version. + pub fn memories_mut(&mut self, op: F) + where + for<'a> F: FnOnce(&'a mut [MemoryBuffer; 2]), + { + op(&mut self.memories); + + self.check_self(); + } + + /// Returns mutable reference to the double buffer. + /// + /// # Safety + /// + /// This is unsafe because - by `mem::replace`ing the buffers - the api contract of both buffers + /// having the same characteristics (fixed/incremented, read/write) can be violated. + /// This may result in breaking the aliasing rules and subsequently undefined behaviour. + /// + /// This is safe as long as you don't `mem::replace` the buffers, or at least ensure that + /// both buffers have the same characteristics afterwards. + pub unsafe fn memories_mut_unchecked( + &mut self, + ) -> &mut [MemoryBuffer; 2] { + &mut self.memories + } + + pub fn free(self) -> [MemoryBuffer; 2] { + self.memories + } + + fn check_self(&self) { + assert_eq!( + self.memories[0].get().is_read(), + self.memories[1].get().is_read() + ); + assert_eq!( + self.memories[0].get().is_fixed(), + self.memories[1].get().is_fixed() + ); + + if self.memories[0].get().is_incremented() { + assert_eq!( + self.memories[0].get().as_incremented().unwrap().len(), + self.memories[1].get().as_incremented().unwrap().len() + ); + } + } +} diff --git a/src/dma/transfer/config.rs b/src/dma/transfer/config.rs new file mode 100644 index 00000000..14bde698 --- /dev/null +++ b/src/dma/transfer/config.rs @@ -0,0 +1,510 @@ +use super::super::stream::config::{ + BufferModeConf, CircularModeConf, Config as StreamConfig, CurrentTarget, + DirectConf, DoubleBufferConf, FifoConf, FifoThreshold, FlowControllerConf, + M0a, M1a, MBurst, MSize, Minc, Ndt, NotM2MConf, PBurstConf, Pa, Pinc, + PincConf, Pincos, TransferDirectionConf, TransferModeConf, +}; +use super::buffer::{IncrementedBuffer, MemoryBufferType}; +use super::{ + Buffer, IPayloadSize, Payload, PayloadSize, TransferBuffers, + TransferDirection, +}; +use core::convert::TryFrom; + +#[derive(Debug)] +pub struct Config<'wo, Peripheral, Memory> +where + Peripheral: Payload, + Memory: Payload, +{ + transfer_direction: TransferDirection<'wo, Peripheral, Memory>, + additional_config: AdditionalConfig, +} + +impl<'wo, Peripheral, Memory> Config<'wo, Peripheral, Memory> +where + Peripheral: Payload, + Memory: Payload, +{ + pub fn new( + transfer_direction: TransferDirection<'wo, Peripheral, Memory>, + additional_config: AdditionalConfig, + ) -> Self { + let s = Self { + transfer_direction, + additional_config, + }; + + s.check_self(); + + s + } + + pub fn additional_config(&self) -> AdditionalConfig { + self.additional_config + } + + pub fn transfer_direction( + &self, + ) -> &TransferDirection<'wo, Peripheral, Memory> { + &self.transfer_direction + } + + pub fn transfer_direction_mut(&mut self, op: F) + where + for<'a> F: FnOnce(&'a mut TransferDirection<'wo, Peripheral, Memory>), + { + op(&mut self.transfer_direction); + + self.check_self(); + } + + pub unsafe fn transfer_direction_mut_unchecked( + &mut self, + ) -> &mut TransferDirection<'wo, Peripheral, Memory> { + &mut self.transfer_direction + } + + pub fn transfer_direction_conf(&self) -> TransferDirectionConf { + match self.transfer_direction() { + TransferDirection::P2M(_) => { + TransferDirectionConf::P2M(self.not_m2m_conf()) + } + TransferDirection::M2P(_) => { + TransferDirectionConf::M2P(self.not_m2m_conf()) + } + TransferDirection::M2M(_) => { + TransferDirectionConf::M2M(self.fifo_conf().unwrap()) + } + } + } + + fn not_m2m_conf(&self) -> NotM2MConf { + NotM2MConf { + transfer_mode: self.transfer_mode_conf(), + flow_controller: self.flow_controller_conf(), + } + } + + fn transfer_mode_conf(&self) -> TransferModeConf { + self.additional_config.transfer_mode.into_stream_conf( + Some(self.m_size()), + self.pinc(), + self.pincos(), + ) + } + + fn flow_controller_conf(&self) -> FlowControllerConf { + self.additional_config + .flow_controller + .into_stream_conf(self.m1a()) + } + + fn pinc(&self) -> Pinc { + let buffers = self.buffers().get(); + + if buffers.peripheral_buffer.is_fixed() { + Pinc::Fixed + } else { + Pinc::Incremented + } + } + + fn pincos(&self) -> Option { + let buffers = self.buffers().get(); + + match &buffers.peripheral_buffer { + Buffer::Fixed(_) => None, + Buffer::Incremented(buffer) => match buffer { + IncrementedBuffer::RegularOffset(_) => Some(Pincos::PSize), + IncrementedBuffer::WordOffset(_) => Some(Pincos::Word), + }, + } + } + + fn minc(&self) -> Minc { + let buffers = self.buffers().get(); + + match &buffers.memory_buffer.m0a().get() { + Buffer::Fixed(_) => Minc::Fixed, + Buffer::Incremented(_) => Minc::Incremented, + } + } + + fn m_size(&self) -> MSize { + PayloadSize::from_payload::().into() + } + + fn fifo_conf(&self) -> Option { + if let TransferModeTransferConf::Fifo(conf) = + self.additional_config.transfer_mode + { + Some(conf.into_stream_conf( + self.m_size(), + self.pinc(), + self.pincos(), + )) + } else { + None + } + } + + pub fn pa(&self) -> Pa { + Pa(self.buffers().get().peripheral_buffer.as_ptr(Some(0)) as u32) + } + + pub fn m0a(&self) -> M0a { + match &self.buffers().get().memory_buffer { + MemoryBufferType::SingleBuffer(memory) => { + M0a(memory.get().as_ptr(Some(0)) as u32) + } + MemoryBufferType::DoubleBuffer(double) => { + M0a(double.memories()[0].get().as_ptr(Some(0)) as u32) + } + } + } + + pub fn m1a(&self) -> Option { + if let MemoryBufferType::DoubleBuffer(buffer) = + &self.buffers().get().memory_buffer + { + Some(M1a(buffer.memories()[1].get().as_ptr(Some(0)) as u32)) + } else { + None + } + } + + pub fn stream_config(&self, conf: &mut StreamConfig) { + conf.transfer_direction = self.transfer_direction_conf(); + + let buffers = self.buffers().get(); + + // Configure ndt + + match &buffers.peripheral_buffer { + Buffer::Fixed(_) => { + match buffers.memory_buffer.m0a().get() { + Buffer::Fixed(_) => { + // NDT must be configured in advance + } + Buffer::Incremented(buffer) => { + let p_size: usize = + PayloadSize::from_payload::().into(); + let m_size: usize = + PayloadSize::from_payload::().into(); + + let memory_bytes = buffer.len() * m_size; + + if memory_bytes % p_size != 0 { + panic!("Last transfer may be incomplete."); + } + + let ndt = u16::try_from(memory_bytes / p_size).unwrap(); + conf.ndt = Ndt(ndt); + } + } + } + Buffer::Incremented(buffer) => { + let ndt = u16::try_from(buffer.len()).unwrap(); + conf.ndt = Ndt(ndt); + } + } + + // Configure addresses + // Note: M1a is already configured in `self.transfer_direction_conf()` + + conf.pa = self.pa(); + conf.m0a = self.m0a(); + + // Configure Incrementing + // Note: Pinc is already configured in `self.transfer_direction_conf()` + + conf.minc = self.minc(); + } + + pub fn buffers(&self) -> &TransferBuffers<'wo, Peripheral, Memory> { + self.transfer_direction.buffers() + } + + pub fn buffers_mut(&mut self, op: F) + where + for<'a> F: FnOnce(&'a mut TransferBuffers<'wo, Peripheral, Memory>), + { + self.transfer_direction.buffers_mut(op); + + self.check_self(); + } + + pub unsafe fn buffers_mut_unchecked( + &mut self, + ) -> &mut TransferBuffers<'wo, Peripheral, Memory> { + self.transfer_direction.buffers_mut_unchecked() + } + + pub fn free(self) -> TransferDirection<'wo, Peripheral, Memory> { + self.transfer_direction + } + + fn check_self(&self) { + let buffers = self.buffers().get(); + // Check Buffer Mode + + if matches!( + self.additional_config.flow_controller, + FlowControllerTransferConf::Dma( + CircularModeTransferConf::Enabled( + BufferModeTransferConf::DoubleBuffer(_), + ), + ) + ) { + assert!(buffers.memory_buffer.is_double_buffer()); + } else { + assert!(buffers.memory_buffer.is_single_buffer()); + } + + // Check Transfer Direction + + if matches!(self.transfer_direction(), TransferDirection::M2M(_)) { + assert!(matches!( + self.additional_config.transfer_mode, + TransferModeTransferConf::Fifo(_) + )); + assert!(matches!( + self.additional_config.flow_controller, + FlowControllerTransferConf::Dma( + CircularModeTransferConf::Disabled + ) + )); + } + + // Check Transfer Mode + + if matches!( + self.additional_config.transfer_mode, + TransferModeTransferConf::Direct + ) { + assert_eq!(Peripheral::Size::SIZE, Memory::Size::SIZE); + } + + // Check Incrementing + } +} + +#[derive(Debug, Clone, Copy)] +pub struct AdditionalConfig { + pub transfer_mode: TransferModeTransferConf, + pub flow_controller: FlowControllerTransferConf, +} + +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +pub enum TransferModeTransferConf { + Direct, + Fifo(FifoTransferConf), +} + +impl TransferModeTransferConf { + pub fn into_stream_conf( + self, + m_size: Option, + pinc: Pinc, + pincos: Option, + ) -> TransferModeConf { + match self { + Self::Direct => TransferModeConf::Direct(DirectConf { pinc }), + Self::Fifo(fifo) => TransferModeConf::Fifo(fifo.into_stream_conf( + m_size.unwrap(), + pinc, + pincos, + )), + } + } +} + +impl From for TransferModeTransferConf { + fn from(x: TransferModeConf) -> Self { + match x { + TransferModeConf::Direct(_) => Self::Direct, + TransferModeConf::Fifo(fifo) => Self::Fifo(fifo.into()), + } + } +} + +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +pub struct FifoTransferConf { + pub fifo_threshold: FifoThreshold, + pub p_burst: PBurstTransferConf, + pub m_burst: MBurst, +} + +impl FifoTransferConf { + pub fn into_stream_conf( + self, + m_size: MSize, + pinc: Pinc, + pincos: Option, + ) -> FifoConf { + FifoConf { + fifo_threshold: self.fifo_threshold, + p_burst: self.p_burst.into_stream_conf(pinc, pincos), + m_burst: self.m_burst, + m_size, + } + } +} + +impl From for FifoTransferConf { + fn from(x: FifoConf) -> Self { + Self { + fifo_threshold: x.fifo_threshold, + p_burst: x.p_burst.into(), + m_burst: x.m_burst, + } + } +} + +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +pub enum PBurstTransferConf { + Single, + Incr4, + Incr8, + Incr16, +} + +impl PBurstTransferConf { + pub fn into_stream_conf( + self, + pinc: Pinc, + pincos: Option, + ) -> PBurstConf { + match self { + Self::Single => { + let pinc_conf = match pinc { + Pinc::Fixed => PincConf::Fixed, + Pinc::Incremented => PincConf::Incremented(pincos.unwrap()), + }; + + PBurstConf::Single(pinc_conf) + } + Self::Incr4 => PBurstConf::Incr4(pinc), + Self::Incr8 => PBurstConf::Incr8(pinc), + Self::Incr16 => PBurstConf::Incr16(pinc), + } + } +} + +impl From for PBurstTransferConf { + fn from(x: PBurstConf) -> Self { + match x { + PBurstConf::Single(_) => Self::Single, + PBurstConf::Incr4(_) => Self::Incr4, + PBurstConf::Incr8(_) => Self::Incr8, + PBurstConf::Incr16(_) => Self::Incr16, + } + } +} + +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +pub enum FlowControllerTransferConf { + Dma(CircularModeTransferConf), + Peripheral, +} + +impl FlowControllerTransferConf { + pub fn into_stream_conf(self, m1a: Option) -> FlowControllerConf { + match self { + Self::Dma(circular) => { + FlowControllerConf::Dma(circular.into_stream_conf(m1a)) + } + Self::Peripheral => FlowControllerConf::Peripheral, + } + } +} + +impl From for FlowControllerTransferConf { + fn from(x: FlowControllerConf) -> Self { + match x { + FlowControllerConf::Dma(circ) => Self::Dma(circ.into()), + FlowControllerConf::Peripheral => Self::Peripheral, + } + } +} + +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +pub enum CircularModeTransferConf { + Disabled, + Enabled(BufferModeTransferConf), +} + +impl CircularModeTransferConf { + pub fn into_stream_conf(self, m1a: Option) -> CircularModeConf { + match self { + Self::Disabled => CircularModeConf::Disabled, + Self::Enabled(buffer_mode) => { + CircularModeConf::Enabled(buffer_mode.into_stream_conf(m1a)) + } + } + } +} + +impl From for CircularModeTransferConf { + fn from(x: CircularModeConf) -> Self { + match x { + CircularModeConf::Disabled => Self::Disabled, + CircularModeConf::Enabled(buffer_mode) => { + Self::Enabled(buffer_mode.into()) + } + } + } +} + +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +pub enum BufferModeTransferConf { + Regular, + DoubleBuffer(DoubleBufferTransferConf), +} + +impl BufferModeTransferConf { + pub fn into_stream_conf(self, m1a: Option) -> BufferModeConf { + match self { + Self::Regular => BufferModeConf::Regular, + Self::DoubleBuffer(conf) => BufferModeConf::DoubleBuffer( + conf.into_stream_conf(m1a.unwrap()), + ), + } + } +} + +impl From for BufferModeTransferConf { + fn from(x: BufferModeConf) -> Self { + match x { + BufferModeConf::Regular => Self::Regular, + BufferModeConf::DoubleBuffer(conf) => { + Self::DoubleBuffer(DoubleBufferTransferConf { + current_target: conf.current_target, + }) + } + } + } +} + +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +pub struct DoubleBufferTransferConf { + pub current_target: CurrentTarget, +} + +impl DoubleBufferTransferConf { + pub fn into_stream_conf(self, m1a: M1a) -> DoubleBufferConf { + DoubleBufferConf { + current_target: self.current_target, + m1a, + } + } +} + +impl From for DoubleBufferTransferConf { + fn from(x: DoubleBufferConf) -> Self { + Self { + current_target: x.current_target, + } + } +} diff --git a/src/dma/transfer/mod.rs b/src/dma/transfer/mod.rs new file mode 100644 index 00000000..a8d8d210 --- /dev/null +++ b/src/dma/transfer/mod.rs @@ -0,0 +1,607 @@ +//! Safe DMA Transfers + +pub mod buffer; +pub mod config; + +use self::buffer::{MemoryBuffer, MemoryBufferType}; +use super::stream::config::{MSize, PSize}; +use super::stream::{Disabled, Enabled, IsrCleared, IsrUncleared}; +use super::{ChannelId, Stream}; +use crate::private; +use core::fmt::Debug; +use core::marker::PhantomData; +use core::mem; +use enum_as_inner::EnumAsInner; + +pub use self::buffer::Buffer; +pub use self::config::Config; + +pub struct Transfer<'wo, State: TransferState<'wo>> { + state: State, + _phantom: PhantomData<&'wo ()>, +} + +impl<'wo, Peripheral, Memory> Transfer<'wo, Start<'wo, Peripheral, Memory>> +where + Peripheral: Payload, + Memory: Payload, +{ + pub fn new(conf: Config<'wo, Peripheral, Memory>) -> Self { + Self { + state: Start { conf }, + _phantom: PhantomData, + } + } + + pub fn start( + self, + mut stream: Stream, + ) -> Transfer<'wo, Ongoing<'wo, Peripheral, Memory, CXX>> { + self.configure_stream(&mut stream); + + Transfer { + state: Ongoing { + stream: unsafe { stream.enable() }, + buffers: self.state.conf.free().free(), + }, + _phantom: PhantomData, + } + } + + fn configure_stream( + &self, + stream: &mut Stream, + ) { + let mut conf = stream.config(); + + self.state.conf.stream_config(&mut conf); + + stream.apply_config(conf); + } +} + +pub trait TransferState<'wo>: Send + Sync + private::Sealed { + type Peripheral: Payload; + type Memory: Payload; + + fn buffers(&self) -> &TransferBuffers<'wo, Self::Peripheral, Self::Memory>; + + fn buffers_mut(&mut self, op: F) + where + for<'a> F: FnOnce( + &'a mut TransferBuffers<'wo, Self::Peripheral, Self::Memory>, + ); + + unsafe fn buffers_mut_unchecked( + &mut self, + ) -> &mut TransferBuffers<'wo, Self::Peripheral, Self::Memory>; +} + +pub struct Start<'wo, Peripheral, Memory> +where + Peripheral: Payload, + Memory: Payload, +{ + conf: Config<'wo, Peripheral, Memory>, +} + +impl private::Sealed for Start<'_, Peripheral, Memory> +where + Peripheral: Payload, + Memory: Payload, +{ +} + +impl<'wo, Peripheral, Memory> TransferState<'wo> + for Start<'wo, Peripheral, Memory> +where + Peripheral: Payload, + Memory: Payload, +{ + type Peripheral = Peripheral; + type Memory = Memory; + + fn buffers(&self) -> &TransferBuffers<'wo, Peripheral, Memory> { + self.conf.transfer_direction().buffers() + } + + fn buffers_mut(&mut self, op: F) + where + for<'a> F: FnOnce(&'a mut TransferBuffers<'wo, Peripheral, Memory>), + { + self.conf.transfer_direction_mut(|t| t.buffers_mut(op)); + } + + unsafe fn buffers_mut_unchecked( + &mut self, + ) -> &mut TransferBuffers<'wo, Peripheral, Memory> { + self.conf + .transfer_direction_mut_unchecked() + .buffers_mut_unchecked() + } +} + +pub struct Ongoing<'wo, Peripheral, Memory, CXX> +where + Peripheral: Payload, + Memory: Payload, + CXX: ChannelId, +{ + stream: Stream, + buffers: TransferBuffers<'wo, Peripheral, Memory>, +} + +impl private::Sealed + for Ongoing<'_, Peripheral, Memory, CXX> +where + Peripheral: Payload, + Memory: Payload, + CXX: ChannelId, +{ +} + +impl<'wo, Peripheral, Memory, CXX> TransferState<'wo> + for Ongoing<'wo, Peripheral, Memory, CXX> +where + Peripheral: Payload, + Memory: Payload, + CXX: ChannelId, +{ + type Peripheral = Peripheral; + type Memory = Memory; + + fn buffers(&self) -> &TransferBuffers<'wo, Peripheral, Memory> { + &self.buffers + } + + fn buffers_mut(&mut self, op: F) + where + for<'a> F: FnOnce(&'a mut TransferBuffers<'wo, Peripheral, Memory>), + { + op(&mut self.buffers) + } + + unsafe fn buffers_mut_unchecked( + &mut self, + ) -> &mut TransferBuffers<'wo, Peripheral, Memory> { + &mut self.buffers + } +} + +/// # Safety +/// +/// * `Self` must be valid for any bit representation +/// * `Self::Size` must be equal to actual size +pub unsafe trait Payload: + Sized + Clone + Copy + Send + Sync + 'static +{ + type Size: IPayloadSize; +} + +// Maps Payload size to number of bytes +int_enum! { + PayloadSize <=> usize, + "Payload Size", + Byte <=> 1, + HalfWord <=> 2, + Word <=> 4 +} + +impl From for MSize { + fn from(val: PayloadSize) -> Self { + match val { + PayloadSize::Byte => MSize::Byte, + PayloadSize::HalfWord => MSize::HalfWord, + PayloadSize::Word => MSize::Word, + } + } +} + +impl From for PayloadSize { + fn from(val: MSize) -> Self { + match val { + MSize::Byte => PayloadSize::Byte, + MSize::HalfWord => PayloadSize::HalfWord, + MSize::Word => PayloadSize::Word, + } + } +} + +impl From for PSize { + fn from(val: PayloadSize) -> Self { + match val { + PayloadSize::Byte => PSize::Byte, + PayloadSize::HalfWord => PSize::HalfWord, + PayloadSize::Word => PSize::Word, + } + } +} + +impl From for PayloadSize { + fn from(val: PSize) -> Self { + match val { + PSize::Byte => PayloadSize::Byte, + PSize::HalfWord => PayloadSize::HalfWord, + PSize::Word => PayloadSize::Word, + } + } +} + +impl PayloadSize { + pub fn from_payload() -> Self { + let size = P::Size::SIZE; + + debug_assert_eq!(mem::size_of::

(), size.into()); + + size + } +} + +pub trait IPayloadSize { + const SIZE: PayloadSize; +} + +pub struct Byte; +pub struct HalfWord; +pub struct Word; + +impl IPayloadSize for Byte { + const SIZE: PayloadSize = PayloadSize::Byte; +} +impl IPayloadSize for HalfWord { + const SIZE: PayloadSize = PayloadSize::HalfWord; +} +impl IPayloadSize for Word { + const SIZE: PayloadSize = PayloadSize::Word; +} + +unsafe impl Payload for u8 { + type Size = Byte; +} + +unsafe impl Payload for i8 { + type Size = Byte; +} + +unsafe impl Payload for u16 { + type Size = HalfWord; +} + +unsafe impl Payload for i16 { + type Size = HalfWord; +} + +unsafe impl Payload for u32 { + type Size = Word; +} + +unsafe impl Payload for i32 { + type Size = Word; +} + +unsafe impl Payload for f32 { + type Size = Word; +} + +#[derive(Debug, EnumAsInner)] +pub enum TransferDirection<'wo, Peripheral, Memory> +where + Peripheral: Payload, + Memory: Payload, +{ + P2M(PeripheralToMemory<'wo, Peripheral, Memory>), + M2P(MemoryToPeripheral<'wo, Peripheral, Memory>), + M2M(MemoryToMemory<'wo, Peripheral, Memory>), +} + +impl<'wo, Peripheral, Memory> TransferDirection<'wo, Peripheral, Memory> +where + Peripheral: Payload, + Memory: Payload, +{ + pub fn buffers(&self) -> &TransferBuffers<'wo, Peripheral, Memory> { + match self { + TransferDirection::P2M(p2m) => p2m.buffers(), + TransferDirection::M2P(m2p) => m2p.buffers(), + TransferDirection::M2M(m2m) => m2m.buffers(), + } + } + + pub fn buffers_mut(&mut self, op: F) + where + for<'a> F: FnOnce(&'a mut TransferBuffers<'wo, Peripheral, Memory>), + { + match self { + TransferDirection::P2M(p2m) => p2m.buffers_mut(op), + TransferDirection::M2P(m2p) => m2p.buffers_mut(op), + TransferDirection::M2M(m2m) => m2m.buffers_mut(op), + } + } + + pub unsafe fn buffers_mut_unchecked( + &mut self, + ) -> &mut TransferBuffers<'wo, Peripheral, Memory> { + match self { + TransferDirection::P2M(p2m) => p2m.buffers_mut_unchecked(), + TransferDirection::M2P(m2p) => m2p.buffers_mut_unchecked(), + TransferDirection::M2M(m2m) => m2m.buffers_mut_unchecked(), + } + } + + pub fn free(self) -> TransferBuffers<'wo, Peripheral, Memory> { + match self { + TransferDirection::P2M(p2m) => p2m.free(), + TransferDirection::M2P(m2p) => m2p.free(), + TransferDirection::M2M(m2m) => m2m.free(), + } + } +} + +#[derive(Debug)] +pub struct PeripheralToMemory<'wo, Peripheral, Memory> +where + Peripheral: Payload, + Memory: Payload, +{ + buffers: TransferBuffers<'wo, Peripheral, Memory>, +} + +impl<'wo, Peripheral, Memory> PeripheralToMemory<'wo, Peripheral, Memory> +where + Peripheral: Payload, + Memory: Payload, +{ + pub fn new(buffers: TransferBuffers<'wo, Peripheral, Memory>) -> Self { + let s = Self { buffers }; + + s.check_self(); + + s + } + + pub fn buffers(&self) -> &TransferBuffers<'wo, Peripheral, Memory> { + &self.buffers + } + + pub fn buffers_mut(&mut self, op: F) + where + for<'a> F: FnOnce(&'a mut TransferBuffers<'wo, Peripheral, Memory>), + { + op(&mut self.buffers); + + self.check_self(); + } + + pub unsafe fn buffers_mut_unchecked( + &mut self, + ) -> &mut TransferBuffers<'wo, Peripheral, Memory> { + &mut self.buffers + } + + pub fn free(self) -> TransferBuffers<'wo, Peripheral, Memory> { + self.buffers + } + + fn check_self(&self) { + assert!(self.buffers.get().peripheral_buffer.is_read()); + assert!(self.buffers.get().memory_buffer.is_read()); + } +} + +#[derive(Debug)] +pub struct MemoryToPeripheral<'wo, Peripheral, Memory> +where + Peripheral: Payload, + Memory: Payload, +{ + buffers: TransferBuffers<'wo, Peripheral, Memory>, +} + +impl<'wo, Peripheral, Memory> MemoryToPeripheral<'wo, Peripheral, Memory> +where + Peripheral: Payload, + Memory: Payload, +{ + pub fn new(buffers: TransferBuffers<'wo, Peripheral, Memory>) -> Self { + let s = Self { buffers }; + + s.check_self(); + + s + } + + pub fn buffers(&self) -> &TransferBuffers<'wo, Peripheral, Memory> { + &self.buffers + } + + pub fn buffers_mut(&mut self, op: F) + where + for<'a> F: FnOnce(&'a mut TransferBuffers<'wo, Peripheral, Memory>), + { + op(&mut self.buffers); + + self.check_self(); + } + + pub unsafe fn buffers_mut_unchecked( + &mut self, + ) -> &mut TransferBuffers<'wo, Peripheral, Memory> { + &mut self.buffers + } + + pub fn free(self) -> TransferBuffers<'wo, Peripheral, Memory> { + self.buffers + } + + fn check_self(&self) { + assert!(self.buffers.get().peripheral_buffer.is_write()); + assert!(self.buffers.get().memory_buffer.is_read()); + } +} + +#[derive(Debug)] +pub struct MemoryToMemory<'wo, Source, Dest> +where + Source: Payload, + Dest: Payload, +{ + buffers: TransferBuffers<'wo, Source, Dest>, +} + +impl<'wo, Source, Dest> MemoryToMemory<'wo, Source, Dest> +where + Source: Payload, + Dest: Payload, +{ + pub fn new(buffers: TransferBuffers<'wo, Source, Dest>) -> Self { + let s = Self { buffers }; + + s.check_self(); + + s + } + + pub fn buffers(&self) -> &TransferBuffers<'wo, Source, Dest> { + &self.buffers + } + + pub fn buffers_mut(&mut self, op: F) + where + for<'a> F: FnOnce(&'a mut TransferBuffers<'wo, Source, Dest>), + { + op(&mut self.buffers); + + self.check_self(); + } + + pub unsafe fn buffers_mut_unchecked( + &mut self, + ) -> &mut TransferBuffers<'wo, Source, Dest> { + &mut self.buffers + } + + pub fn source_buffer(&self) -> &Buffer<'wo, Source> { + &self.buffers.get().peripheral_buffer + } + + pub fn dest_buffer(&self) -> &MemoryBuffer { + &self.buffers.get().memory_buffer.as_single_buffer().unwrap() + } + + pub fn dest_buffer_mut(&mut self, op: F) + where + for<'a> F: FnOnce(&'a mut MemoryBuffer), + { + self.buffers.get_mut(move |b| { + op(&mut b.memory_buffer.as_single_buffer_mut().unwrap()) + }); + } + + pub unsafe fn dest_buffer_mut_unchecked( + &mut self, + ) -> &mut MemoryBuffer { + self.buffers + .get_mut_unchecked() + .memory_buffer + .as_single_buffer_mut() + .unwrap() + } + + pub fn free(self) -> TransferBuffers<'wo, Source, Dest> { + self.buffers + } + + fn check_self(&self) { + assert!(self.buffers.get().peripheral_buffer.is_read()); + assert!(self.buffers.get().memory_buffer.is_write()); + + assert!(self.buffers.get().memory_buffer.is_single_buffer()); + } +} + +#[derive(Debug)] +pub struct Buffers<'wo, Peripheral, Memory> +where + Peripheral: Payload, + Memory: Payload, +{ + pub peripheral_buffer: Buffer<'wo, Peripheral>, + pub memory_buffer: MemoryBufferType, +} + +#[derive(Debug)] +pub struct TransferBuffers<'wo, Peripheral, Memory> +where + Peripheral: Payload, + Memory: Payload, +{ + buffers: Buffers<'wo, Peripheral, Memory>, +} + +impl<'wo, Peripheral, Memory> TransferBuffers<'wo, Peripheral, Memory> +where + Peripheral: Payload, + Memory: Payload, +{ + /// # Args + /// + /// * `peripheral_buffer`: Usually `Buffer::Peripheral`, except for `M2M`-transfers (Memory to Memory), where the source buffer is `Buffer::Memory`. + /// * `memory_buffer`: The `MemoryBuffer` of the transfer. + pub fn new(buffers: Buffers<'wo, Peripheral, Memory>) -> Self { + let s = Self { buffers }; + + s.check_self(); + + s + } + + pub fn get(&self) -> &Buffers<'wo, Peripheral, Memory> { + &self.buffers + } + + pub fn get_mut(&mut self, op: F) + where + for<'a> F: FnOnce(&'a mut Buffers<'wo, Peripheral, Memory>), + { + op(&mut self.buffers); + + self.check_self(); + } + + pub unsafe fn get_mut_unchecked( + &mut self, + ) -> &mut Buffers<'wo, Peripheral, Memory> { + &mut self.buffers + } + + pub fn free(self) -> Buffers<'wo, Peripheral, Memory> { + self.buffers + } + + fn check_self(&self) { + assert_ne!( + self.buffers.peripheral_buffer.is_read(), + self.buffers.memory_buffer.is_read() + ); + } +} + +#[derive(Copy, Clone, Debug, EnumAsInner)] +pub enum PayloadPort +where + Peripheral: Payload, + Memory: Payload, +{ + Peripheral(Peripheral), + Memory(Memory), +} + +#[derive(Debug, EnumAsInner)] +pub enum PointerPort +where + Peripheral: Payload, + Memory: Payload, +{ + Peripheral(*mut Peripheral), + Memory(*mut Memory), +} diff --git a/src/serial/dma.rs b/src/serial/dma.rs index 7250e7bd..7490ce01 100644 --- a/src/serial/dma.rs +++ b/src/serial/dma.rs @@ -12,7 +12,7 @@ use crate::dma::transfer::{ FixedBuffer, FixedBufferR, MemoryBufferStatic, Ongoing as TransferOngoing, Payload, PeripheralBuffer, Start as TransferStart, }; -use crate::dma::{Channel, ChannelId, DmaMux, SafeTransfer}; +use crate::dma::{Channel, ChannelId, Mux, SafeTransfer}; use crate::stm32::{UART4, UART5, UART7, UART8}; use crate::stm32::{USART1, USART2, USART3, USART6}; use core::ops::Deref; @@ -119,7 +119,7 @@ where Peripheral: Payload, Memory: Payload, { - mux: DmaMux, + mux: Mux, transfer: SafeTransfer<'static, Peripheral, Memory, TransferOngoing>, } @@ -306,7 +306,7 @@ where &mut self.state.transfer } - pub fn mux(&self) -> &DmaMux { + pub fn mux(&self) -> &Mux { &self.state.mux } From 76630dc90ddefeaffc36f3d733f26977aa36a034 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ad=C3=A4?= Date: Tue, 21 Apr 2020 17:29:27 +0200 Subject: [PATCH 087/103] Moved TransferDirection from transfer to transfer::config --- src/dma/transfer/config.rs | 244 ++++++++++++++++++++++++++++++++++++- src/dma/transfer/mod.rs | 238 +----------------------------------- 2 files changed, 240 insertions(+), 242 deletions(-) diff --git a/src/dma/transfer/config.rs b/src/dma/transfer/config.rs index 14bde698..5fedc00e 100644 --- a/src/dma/transfer/config.rs +++ b/src/dma/transfer/config.rs @@ -4,12 +4,10 @@ use super::super::stream::config::{ M0a, M1a, MBurst, MSize, Minc, Ndt, NotM2MConf, PBurstConf, Pa, Pinc, PincConf, Pincos, TransferDirectionConf, TransferModeConf, }; -use super::buffer::{IncrementedBuffer, MemoryBufferType}; -use super::{ - Buffer, IPayloadSize, Payload, PayloadSize, TransferBuffers, - TransferDirection, -}; +use super::buffer::{IncrementedBuffer, MemoryBuffer, MemoryBufferType}; +use super::{Buffer, IPayloadSize, Payload, PayloadSize, TransferBuffers}; use core::convert::TryFrom; +use enum_as_inner::EnumAsInner; #[derive(Debug)] pub struct Config<'wo, Peripheral, Memory> @@ -290,6 +288,242 @@ where } } +#[derive(Debug, EnumAsInner)] +pub enum TransferDirection<'wo, Peripheral, Memory> +where + Peripheral: Payload, + Memory: Payload, +{ + P2M(PeripheralToMemory<'wo, Peripheral, Memory>), + M2P(MemoryToPeripheral<'wo, Peripheral, Memory>), + M2M(MemoryToMemory<'wo, Peripheral, Memory>), +} + +impl<'wo, Peripheral, Memory> TransferDirection<'wo, Peripheral, Memory> +where + Peripheral: Payload, + Memory: Payload, +{ + pub fn buffers(&self) -> &TransferBuffers<'wo, Peripheral, Memory> { + match self { + TransferDirection::P2M(p2m) => p2m.buffers(), + TransferDirection::M2P(m2p) => m2p.buffers(), + TransferDirection::M2M(m2m) => m2m.buffers(), + } + } + + pub fn buffers_mut(&mut self, op: F) + where + for<'a> F: FnOnce(&'a mut TransferBuffers<'wo, Peripheral, Memory>), + { + match self { + TransferDirection::P2M(p2m) => p2m.buffers_mut(op), + TransferDirection::M2P(m2p) => m2p.buffers_mut(op), + TransferDirection::M2M(m2m) => m2m.buffers_mut(op), + } + } + + pub unsafe fn buffers_mut_unchecked( + &mut self, + ) -> &mut TransferBuffers<'wo, Peripheral, Memory> { + match self { + TransferDirection::P2M(p2m) => p2m.buffers_mut_unchecked(), + TransferDirection::M2P(m2p) => m2p.buffers_mut_unchecked(), + TransferDirection::M2M(m2m) => m2m.buffers_mut_unchecked(), + } + } + + pub fn free(self) -> TransferBuffers<'wo, Peripheral, Memory> { + match self { + TransferDirection::P2M(p2m) => p2m.free(), + TransferDirection::M2P(m2p) => m2p.free(), + TransferDirection::M2M(m2m) => m2m.free(), + } + } +} + +#[derive(Debug)] +pub struct PeripheralToMemory<'wo, Peripheral, Memory> +where + Peripheral: Payload, + Memory: Payload, +{ + buffers: TransferBuffers<'wo, Peripheral, Memory>, +} + +impl<'wo, Peripheral, Memory> PeripheralToMemory<'wo, Peripheral, Memory> +where + Peripheral: Payload, + Memory: Payload, +{ + pub fn new(buffers: TransferBuffers<'wo, Peripheral, Memory>) -> Self { + let s = Self { buffers }; + + s.check_self(); + + s + } + + pub fn buffers(&self) -> &TransferBuffers<'wo, Peripheral, Memory> { + &self.buffers + } + + pub fn buffers_mut(&mut self, op: F) + where + for<'a> F: FnOnce(&'a mut TransferBuffers<'wo, Peripheral, Memory>), + { + op(&mut self.buffers); + + self.check_self(); + } + + pub unsafe fn buffers_mut_unchecked( + &mut self, + ) -> &mut TransferBuffers<'wo, Peripheral, Memory> { + &mut self.buffers + } + + pub fn free(self) -> TransferBuffers<'wo, Peripheral, Memory> { + self.buffers + } + + fn check_self(&self) { + assert!(self.buffers.get().peripheral_buffer.is_read()); + assert!(self.buffers.get().memory_buffer.is_read()); + } +} + +#[derive(Debug)] +pub struct MemoryToPeripheral<'wo, Peripheral, Memory> +where + Peripheral: Payload, + Memory: Payload, +{ + buffers: TransferBuffers<'wo, Peripheral, Memory>, +} + +impl<'wo, Peripheral, Memory> MemoryToPeripheral<'wo, Peripheral, Memory> +where + Peripheral: Payload, + Memory: Payload, +{ + pub fn new(buffers: TransferBuffers<'wo, Peripheral, Memory>) -> Self { + let s = Self { buffers }; + + s.check_self(); + + s + } + + pub fn buffers(&self) -> &TransferBuffers<'wo, Peripheral, Memory> { + &self.buffers + } + + pub fn buffers_mut(&mut self, op: F) + where + for<'a> F: FnOnce(&'a mut TransferBuffers<'wo, Peripheral, Memory>), + { + op(&mut self.buffers); + + self.check_self(); + } + + pub unsafe fn buffers_mut_unchecked( + &mut self, + ) -> &mut TransferBuffers<'wo, Peripheral, Memory> { + &mut self.buffers + } + + pub fn free(self) -> TransferBuffers<'wo, Peripheral, Memory> { + self.buffers + } + + fn check_self(&self) { + assert!(self.buffers.get().peripheral_buffer.is_write()); + assert!(self.buffers.get().memory_buffer.is_read()); + } +} + +#[derive(Debug)] +pub struct MemoryToMemory<'wo, Source, Dest> +where + Source: Payload, + Dest: Payload, +{ + buffers: TransferBuffers<'wo, Source, Dest>, +} + +impl<'wo, Source, Dest> MemoryToMemory<'wo, Source, Dest> +where + Source: Payload, + Dest: Payload, +{ + pub fn new(buffers: TransferBuffers<'wo, Source, Dest>) -> Self { + let s = Self { buffers }; + + s.check_self(); + + s + } + + pub fn buffers(&self) -> &TransferBuffers<'wo, Source, Dest> { + &self.buffers + } + + pub fn buffers_mut(&mut self, op: F) + where + for<'a> F: FnOnce(&'a mut TransferBuffers<'wo, Source, Dest>), + { + op(&mut self.buffers); + + self.check_self(); + } + + pub unsafe fn buffers_mut_unchecked( + &mut self, + ) -> &mut TransferBuffers<'wo, Source, Dest> { + &mut self.buffers + } + + pub fn source_buffer(&self) -> &Buffer<'wo, Source> { + &self.buffers.get().peripheral_buffer + } + + pub fn dest_buffer(&self) -> &MemoryBuffer { + &self.buffers.get().memory_buffer.as_single_buffer().unwrap() + } + + pub fn dest_buffer_mut(&mut self, op: F) + where + for<'a> F: FnOnce(&'a mut MemoryBuffer), + { + self.buffers.get_mut(move |b| { + op(&mut b.memory_buffer.as_single_buffer_mut().unwrap()) + }); + } + + pub unsafe fn dest_buffer_mut_unchecked( + &mut self, + ) -> &mut MemoryBuffer { + self.buffers + .get_mut_unchecked() + .memory_buffer + .as_single_buffer_mut() + .unwrap() + } + + pub fn free(self) -> TransferBuffers<'wo, Source, Dest> { + self.buffers + } + + fn check_self(&self) { + assert!(self.buffers.get().peripheral_buffer.is_read()); + assert!(self.buffers.get().memory_buffer.is_write()); + + assert!(self.buffers.get().memory_buffer.is_single_buffer()); + } +} + #[derive(Debug, Clone, Copy)] pub struct AdditionalConfig { pub transfer_mode: TransferModeTransferConf, diff --git a/src/dma/transfer/mod.rs b/src/dma/transfer/mod.rs index a8d8d210..affcd690 100644 --- a/src/dma/transfer/mod.rs +++ b/src/dma/transfer/mod.rs @@ -3,7 +3,7 @@ pub mod buffer; pub mod config; -use self::buffer::{MemoryBuffer, MemoryBufferType}; +use self::buffer::MemoryBufferType; use super::stream::config::{MSize, PSize}; use super::stream::{Disabled, Enabled, IsrCleared, IsrUncleared}; use super::{ChannelId, Stream}; @@ -283,242 +283,6 @@ unsafe impl Payload for f32 { type Size = Word; } -#[derive(Debug, EnumAsInner)] -pub enum TransferDirection<'wo, Peripheral, Memory> -where - Peripheral: Payload, - Memory: Payload, -{ - P2M(PeripheralToMemory<'wo, Peripheral, Memory>), - M2P(MemoryToPeripheral<'wo, Peripheral, Memory>), - M2M(MemoryToMemory<'wo, Peripheral, Memory>), -} - -impl<'wo, Peripheral, Memory> TransferDirection<'wo, Peripheral, Memory> -where - Peripheral: Payload, - Memory: Payload, -{ - pub fn buffers(&self) -> &TransferBuffers<'wo, Peripheral, Memory> { - match self { - TransferDirection::P2M(p2m) => p2m.buffers(), - TransferDirection::M2P(m2p) => m2p.buffers(), - TransferDirection::M2M(m2m) => m2m.buffers(), - } - } - - pub fn buffers_mut(&mut self, op: F) - where - for<'a> F: FnOnce(&'a mut TransferBuffers<'wo, Peripheral, Memory>), - { - match self { - TransferDirection::P2M(p2m) => p2m.buffers_mut(op), - TransferDirection::M2P(m2p) => m2p.buffers_mut(op), - TransferDirection::M2M(m2m) => m2m.buffers_mut(op), - } - } - - pub unsafe fn buffers_mut_unchecked( - &mut self, - ) -> &mut TransferBuffers<'wo, Peripheral, Memory> { - match self { - TransferDirection::P2M(p2m) => p2m.buffers_mut_unchecked(), - TransferDirection::M2P(m2p) => m2p.buffers_mut_unchecked(), - TransferDirection::M2M(m2m) => m2m.buffers_mut_unchecked(), - } - } - - pub fn free(self) -> TransferBuffers<'wo, Peripheral, Memory> { - match self { - TransferDirection::P2M(p2m) => p2m.free(), - TransferDirection::M2P(m2p) => m2p.free(), - TransferDirection::M2M(m2m) => m2m.free(), - } - } -} - -#[derive(Debug)] -pub struct PeripheralToMemory<'wo, Peripheral, Memory> -where - Peripheral: Payload, - Memory: Payload, -{ - buffers: TransferBuffers<'wo, Peripheral, Memory>, -} - -impl<'wo, Peripheral, Memory> PeripheralToMemory<'wo, Peripheral, Memory> -where - Peripheral: Payload, - Memory: Payload, -{ - pub fn new(buffers: TransferBuffers<'wo, Peripheral, Memory>) -> Self { - let s = Self { buffers }; - - s.check_self(); - - s - } - - pub fn buffers(&self) -> &TransferBuffers<'wo, Peripheral, Memory> { - &self.buffers - } - - pub fn buffers_mut(&mut self, op: F) - where - for<'a> F: FnOnce(&'a mut TransferBuffers<'wo, Peripheral, Memory>), - { - op(&mut self.buffers); - - self.check_self(); - } - - pub unsafe fn buffers_mut_unchecked( - &mut self, - ) -> &mut TransferBuffers<'wo, Peripheral, Memory> { - &mut self.buffers - } - - pub fn free(self) -> TransferBuffers<'wo, Peripheral, Memory> { - self.buffers - } - - fn check_self(&self) { - assert!(self.buffers.get().peripheral_buffer.is_read()); - assert!(self.buffers.get().memory_buffer.is_read()); - } -} - -#[derive(Debug)] -pub struct MemoryToPeripheral<'wo, Peripheral, Memory> -where - Peripheral: Payload, - Memory: Payload, -{ - buffers: TransferBuffers<'wo, Peripheral, Memory>, -} - -impl<'wo, Peripheral, Memory> MemoryToPeripheral<'wo, Peripheral, Memory> -where - Peripheral: Payload, - Memory: Payload, -{ - pub fn new(buffers: TransferBuffers<'wo, Peripheral, Memory>) -> Self { - let s = Self { buffers }; - - s.check_self(); - - s - } - - pub fn buffers(&self) -> &TransferBuffers<'wo, Peripheral, Memory> { - &self.buffers - } - - pub fn buffers_mut(&mut self, op: F) - where - for<'a> F: FnOnce(&'a mut TransferBuffers<'wo, Peripheral, Memory>), - { - op(&mut self.buffers); - - self.check_self(); - } - - pub unsafe fn buffers_mut_unchecked( - &mut self, - ) -> &mut TransferBuffers<'wo, Peripheral, Memory> { - &mut self.buffers - } - - pub fn free(self) -> TransferBuffers<'wo, Peripheral, Memory> { - self.buffers - } - - fn check_self(&self) { - assert!(self.buffers.get().peripheral_buffer.is_write()); - assert!(self.buffers.get().memory_buffer.is_read()); - } -} - -#[derive(Debug)] -pub struct MemoryToMemory<'wo, Source, Dest> -where - Source: Payload, - Dest: Payload, -{ - buffers: TransferBuffers<'wo, Source, Dest>, -} - -impl<'wo, Source, Dest> MemoryToMemory<'wo, Source, Dest> -where - Source: Payload, - Dest: Payload, -{ - pub fn new(buffers: TransferBuffers<'wo, Source, Dest>) -> Self { - let s = Self { buffers }; - - s.check_self(); - - s - } - - pub fn buffers(&self) -> &TransferBuffers<'wo, Source, Dest> { - &self.buffers - } - - pub fn buffers_mut(&mut self, op: F) - where - for<'a> F: FnOnce(&'a mut TransferBuffers<'wo, Source, Dest>), - { - op(&mut self.buffers); - - self.check_self(); - } - - pub unsafe fn buffers_mut_unchecked( - &mut self, - ) -> &mut TransferBuffers<'wo, Source, Dest> { - &mut self.buffers - } - - pub fn source_buffer(&self) -> &Buffer<'wo, Source> { - &self.buffers.get().peripheral_buffer - } - - pub fn dest_buffer(&self) -> &MemoryBuffer { - &self.buffers.get().memory_buffer.as_single_buffer().unwrap() - } - - pub fn dest_buffer_mut(&mut self, op: F) - where - for<'a> F: FnOnce(&'a mut MemoryBuffer), - { - self.buffers.get_mut(move |b| { - op(&mut b.memory_buffer.as_single_buffer_mut().unwrap()) - }); - } - - pub unsafe fn dest_buffer_mut_unchecked( - &mut self, - ) -> &mut MemoryBuffer { - self.buffers - .get_mut_unchecked() - .memory_buffer - .as_single_buffer_mut() - .unwrap() - } - - pub fn free(self) -> TransferBuffers<'wo, Source, Dest> { - self.buffers - } - - fn check_self(&self) { - assert!(self.buffers.get().peripheral_buffer.is_read()); - assert!(self.buffers.get().memory_buffer.is_write()); - - assert!(self.buffers.get().memory_buffer.is_single_buffer()); - } -} - #[derive(Debug)] pub struct Buffers<'wo, Peripheral, Memory> where From 8dd0fa8a5072cf66995d2887227dbea36d71db24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ad=C3=A4?= Date: Tue, 21 Apr 2020 18:33:18 +0200 Subject: [PATCH 088/103] Implemented methods for transfer --- src/dma/stream/mod.rs | 12 ++++++-- src/dma/transfer/config.rs | 33 +++++++++++++++++++++ src/dma/transfer/mod.rs | 61 ++++++++++++++++++++++++++++++++++++-- 3 files changed, 101 insertions(+), 5 deletions(-) diff --git a/src/dma/stream/mod.rs b/src/dma/stream/mod.rs index 240915a7..1187e270 100644 --- a/src/dma/stream/mod.rs +++ b/src/dma/stream/mod.rs @@ -532,10 +532,14 @@ where { /// Sets the Memory-0 Address on the fly /// + /// # Safety + /// + /// Aliasing rules aren't enforced. + /// /// # Panic /// /// This panics if the stream is not in Double Buffer Mode. - pub fn set_m0a(&mut self, m0a: M0a) -> nb::Result<(), Infallible> { + pub unsafe fn set_m0a(&mut self, m0a: M0a) -> nb::Result<(), Infallible> { self.check_double_buffer(); if self.current_target() == CurrentTarget::M0a && self.is_enabled() { @@ -549,10 +553,14 @@ where /// Sets the Memory-1 Address on the fly /// + /// # Safety + /// + /// Aliasing rules aren't enforced. + /// /// # Panic /// /// This panics if the stream is not in Double Buffer Mode. - pub fn set_m1a(&mut self, m1a: M1a) -> nb::Result<(), Infallible> { + pub unsafe fn set_m1a(&mut self, m1a: M1a) -> nb::Result<(), Infallible> { self.check_double_buffer(); if self.current_target() == CurrentTarget::M1a && self.is_enabled() { diff --git a/src/dma/transfer/config.rs b/src/dma/transfer/config.rs index 5fedc00e..439653ec 100644 --- a/src/dma/transfer/config.rs +++ b/src/dma/transfer/config.rs @@ -38,6 +38,20 @@ where s } + pub fn from_stream_config(conf: StreamConfig, buffers: TransferBuffers<'wo, Peripheral, Memory>) -> Self { + let additional_config = conf.into(); + let transfer_direction = match conf.transfer_direction { + TransferDirectionConf::P2M(_) => TransferDirection::P2M(PeripheralToMemory::new(buffers)), + TransferDirectionConf::M2P(_) => TransferDirection::M2P(MemoryToPeripheral::new(buffers)), + TransferDirectionConf::M2M(_) => TransferDirection::M2M(MemoryToMemory::new(buffers)), + }; + + Self { + transfer_direction, + additional_config, + } + } + pub fn additional_config(&self) -> AdditionalConfig { self.additional_config } @@ -530,6 +544,25 @@ pub struct AdditionalConfig { pub flow_controller: FlowControllerTransferConf, } +impl From for AdditionalConfig { + fn from(x: StreamConfig) -> Self { + match x.transfer_direction { + TransferDirectionConf::P2M(conf) | TransferDirectionConf::M2P(conf) => { + Self { + transfer_mode: conf.transfer_mode.into(), + flow_controller: conf.flow_controller.into() + } + } + TransferDirectionConf::M2M(conf) => { + Self { + transfer_mode: TransferModeTransferConf::Fifo(conf.into()), + flow_controller: FlowControllerTransferConf::Dma(CircularModeTransferConf::Disabled), + } + } + } + } +} + #[derive(Copy, Clone, PartialEq, Eq, Debug)] pub enum TransferModeTransferConf { Direct, diff --git a/src/dma/transfer/mod.rs b/src/dma/transfer/mod.rs index affcd690..ea19f3bb 100644 --- a/src/dma/transfer/mod.rs +++ b/src/dma/transfer/mod.rs @@ -4,10 +4,10 @@ pub mod buffer; pub mod config; use self::buffer::MemoryBufferType; -use super::stream::config::{MSize, PSize}; -use super::stream::{Disabled, Enabled, IsrCleared, IsrUncleared}; +use super::stream::config::{MSize, PSize, TransferDirectionConf}; +use super::stream::{Disabled, Enabled, IsrCleared, IsrUncleared, StreamIsr, Error as StreamError}; use super::{ChannelId, Stream}; -use crate::private; +use crate::{nb, private}; use core::fmt::Debug; use core::marker::PhantomData; use core::mem; @@ -58,6 +58,61 @@ where stream.apply_config(conf); } + + pub fn free(self) -> Config<'wo, Peripheral, Memory> { + self.state.conf + } +} + +impl<'wo, Peripheral, Memory, CXX> Transfer<'wo, Ongoing<'wo, Peripheral, Memory, CXX>> +where + Peripheral: Payload, + Memory: Payload, + CXX: ChannelId, +{ + pub fn stream(&self) -> &Stream { + &self.state.stream + } + + pub fn stream_mut(&mut self) -> &mut Stream { + &mut self.state.stream + } + + pub fn wait_until_completed(&self, isr: &StreamIsr) -> nb::Result<(), StreamError> { + self.state.stream.wait_until_completed(isr) + } + + pub fn wait_until_completed_clear(&self, isr: &mut StreamIsr) -> nb::Result<(), StreamError> { + self.state.stream.wait_until_completed_clear(isr) + } + + pub fn wait_until_half_transfer(&self, isr: &StreamIsr) -> nb::Result<(), StreamError> { + self.state.stream.wait_until_half_transfer(isr) + } + + pub fn wait_until_half_transfer_clear(&self, isr: &mut StreamIsr) -> nb::Result<(), StreamError> { + self.state.stream.wait_until_half_transfer_clear(isr) + } + + pub fn wait_until_next_half(&self, isr: &StreamIsr) -> nb::Result<(), StreamError> { + self.state.stream.wait_until_next_half(isr) + } + + pub fn wait_until_next_half_clear(&self, isr: &mut StreamIsr) -> nb::Result<(), StreamError> { + self.state.stream.wait_until_next_half_clear(isr) + } + + pub fn stop(self) -> (Transfer<'wo, Start<'wo, Peripheral, Memory>>, Stream) { + let stream = self.state.stream.disable(); + + let conf = Config::from_stream_config(stream.config(), self.state.buffers); + let transfer = Transfer { + state: Start { conf }, + _phantom: PhantomData, + }; + + (transfer, stream) + } } pub trait TransferState<'wo>: Send + Sync + private::Sealed { From 4b888cff6ab57c274ca7f7a96d21f2bf85650bb8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ad=C3=A4?= Date: Tue, 21 Apr 2020 19:07:42 +0200 Subject: [PATCH 089/103] fmt + doc --- src/dma/transfer/config.rs | 40 +++++++++++++++++------------ src/dma/transfer/mod.rs | 52 ++++++++++++++++++++++++++++---------- 2 files changed, 62 insertions(+), 30 deletions(-) diff --git a/src/dma/transfer/config.rs b/src/dma/transfer/config.rs index 439653ec..7a33ad8a 100644 --- a/src/dma/transfer/config.rs +++ b/src/dma/transfer/config.rs @@ -38,12 +38,21 @@ where s } - pub fn from_stream_config(conf: StreamConfig, buffers: TransferBuffers<'wo, Peripheral, Memory>) -> Self { + pub fn from_stream_config( + conf: StreamConfig, + buffers: TransferBuffers<'wo, Peripheral, Memory>, + ) -> Self { let additional_config = conf.into(); let transfer_direction = match conf.transfer_direction { - TransferDirectionConf::P2M(_) => TransferDirection::P2M(PeripheralToMemory::new(buffers)), - TransferDirectionConf::M2P(_) => TransferDirection::M2P(MemoryToPeripheral::new(buffers)), - TransferDirectionConf::M2M(_) => TransferDirection::M2M(MemoryToMemory::new(buffers)), + TransferDirectionConf::P2M(_) => { + TransferDirection::P2M(PeripheralToMemory::new(buffers)) + } + TransferDirectionConf::M2P(_) => { + TransferDirection::M2P(MemoryToPeripheral::new(buffers)) + } + TransferDirectionConf::M2M(_) => { + TransferDirection::M2M(MemoryToMemory::new(buffers)) + } }; Self { @@ -547,18 +556,17 @@ pub struct AdditionalConfig { impl From for AdditionalConfig { fn from(x: StreamConfig) -> Self { match x.transfer_direction { - TransferDirectionConf::P2M(conf) | TransferDirectionConf::M2P(conf) => { - Self { - transfer_mode: conf.transfer_mode.into(), - flow_controller: conf.flow_controller.into() - } - } - TransferDirectionConf::M2M(conf) => { - Self { - transfer_mode: TransferModeTransferConf::Fifo(conf.into()), - flow_controller: FlowControllerTransferConf::Dma(CircularModeTransferConf::Disabled), - } - } + TransferDirectionConf::P2M(conf) + | TransferDirectionConf::M2P(conf) => Self { + transfer_mode: conf.transfer_mode.into(), + flow_controller: conf.flow_controller.into(), + }, + TransferDirectionConf::M2M(conf) => Self { + transfer_mode: TransferModeTransferConf::Fifo(conf.into()), + flow_controller: FlowControllerTransferConf::Dma( + CircularModeTransferConf::Disabled, + ), + }, } } } diff --git a/src/dma/transfer/mod.rs b/src/dma/transfer/mod.rs index ea19f3bb..2bd16257 100644 --- a/src/dma/transfer/mod.rs +++ b/src/dma/transfer/mod.rs @@ -5,7 +5,10 @@ pub mod config; use self::buffer::MemoryBufferType; use super::stream::config::{MSize, PSize, TransferDirectionConf}; -use super::stream::{Disabled, Enabled, IsrCleared, IsrUncleared, StreamIsr, Error as StreamError}; +use super::stream::{ + Disabled, Enabled, Error as StreamError, IsrCleared, IsrUncleared, + StreamIsr, +}; use super::{ChannelId, Stream}; use crate::{nb, private}; use core::fmt::Debug; @@ -64,7 +67,8 @@ where } } -impl<'wo, Peripheral, Memory, CXX> Transfer<'wo, Ongoing<'wo, Peripheral, Memory, CXX>> +impl<'wo, Peripheral, Memory, CXX> + Transfer<'wo, Ongoing<'wo, Peripheral, Memory, CXX>> where Peripheral: Payload, Memory: Payload, @@ -78,34 +82,58 @@ where &mut self.state.stream } - pub fn wait_until_completed(&self, isr: &StreamIsr) -> nb::Result<(), StreamError> { + pub fn wait_until_completed( + &self, + isr: &StreamIsr, + ) -> nb::Result<(), StreamError> { self.state.stream.wait_until_completed(isr) } - pub fn wait_until_completed_clear(&self, isr: &mut StreamIsr) -> nb::Result<(), StreamError> { + pub fn wait_until_completed_clear( + &self, + isr: &mut StreamIsr, + ) -> nb::Result<(), StreamError> { self.state.stream.wait_until_completed_clear(isr) } - pub fn wait_until_half_transfer(&self, isr: &StreamIsr) -> nb::Result<(), StreamError> { + pub fn wait_until_half_transfer( + &self, + isr: &StreamIsr, + ) -> nb::Result<(), StreamError> { self.state.stream.wait_until_half_transfer(isr) } - pub fn wait_until_half_transfer_clear(&self, isr: &mut StreamIsr) -> nb::Result<(), StreamError> { + pub fn wait_until_half_transfer_clear( + &self, + isr: &mut StreamIsr, + ) -> nb::Result<(), StreamError> { self.state.stream.wait_until_half_transfer_clear(isr) } - pub fn wait_until_next_half(&self, isr: &StreamIsr) -> nb::Result<(), StreamError> { + pub fn wait_until_next_half( + &self, + isr: &StreamIsr, + ) -> nb::Result<(), StreamError> { self.state.stream.wait_until_next_half(isr) } - pub fn wait_until_next_half_clear(&self, isr: &mut StreamIsr) -> nb::Result<(), StreamError> { + pub fn wait_until_next_half_clear( + &self, + isr: &mut StreamIsr, + ) -> nb::Result<(), StreamError> { self.state.stream.wait_until_next_half_clear(isr) } - pub fn stop(self) -> (Transfer<'wo, Start<'wo, Peripheral, Memory>>, Stream) { + pub fn stop( + self, + ) -> ( + Transfer<'wo, Start<'wo, Peripheral, Memory>>, + Stream, + ) { let stream = self.state.stream.disable(); - let conf = Config::from_stream_config(stream.config(), self.state.buffers); + let conf = + Config::from_stream_config(stream.config(), self.state.buffers); let transfer = Transfer { state: Start { conf }, _phantom: PhantomData, @@ -362,10 +390,6 @@ where Peripheral: Payload, Memory: Payload, { - /// # Args - /// - /// * `peripheral_buffer`: Usually `Buffer::Peripheral`, except for `M2M`-transfers (Memory to Memory), where the source buffer is `Buffer::Memory`. - /// * `memory_buffer`: The `MemoryBuffer` of the transfer. pub fn new(buffers: Buffers<'wo, Peripheral, Memory>) -> Self { let s = Self { buffers }; From 4deac5c1c1b182d58e796f352ddb884b0617dcb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ad=C3=A4?= Date: Tue, 21 Apr 2020 20:44:17 +0200 Subject: [PATCH 090/103] update --- src/dma/transfer/config.rs | 5 +---- src/dma/transfer/mod.rs | 2 +- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/dma/transfer/config.rs b/src/dma/transfer/config.rs index 7a33ad8a..18e756e8 100644 --- a/src/dma/transfer/config.rs +++ b/src/dma/transfer/config.rs @@ -55,10 +55,7 @@ where } }; - Self { - transfer_direction, - additional_config, - } + Self::new(transfer_direction, additional_config) } pub fn additional_config(&self) -> AdditionalConfig { diff --git a/src/dma/transfer/mod.rs b/src/dma/transfer/mod.rs index 2bd16257..707f5254 100644 --- a/src/dma/transfer/mod.rs +++ b/src/dma/transfer/mod.rs @@ -4,7 +4,7 @@ pub mod buffer; pub mod config; use self::buffer::MemoryBufferType; -use super::stream::config::{MSize, PSize, TransferDirectionConf}; +use super::stream::config::{MSize, PSize}; use super::stream::{ Disabled, Enabled, Error as StreamError, IsrCleared, IsrUncleared, StreamIsr, From e599f51790f5a14209e1d0aaac91f2c606b88594 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ad=C3=A4?= Date: Thu, 23 Apr 2020 17:00:19 +0200 Subject: [PATCH 091/103] Removed TransferBuffers struct as TransferDirection already checks its invariants --- src/dma/transfer/buffer.rs | 12 +++++ src/dma/transfer/config.rs | 96 ++++++++++++++++++-------------------- src/dma/transfer/mod.rs | 75 ++++------------------------- 3 files changed, 68 insertions(+), 115 deletions(-) diff --git a/src/dma/transfer/buffer.rs b/src/dma/transfer/buffer.rs index 138bde15..c114f6f6 100644 --- a/src/dma/transfer/buffer.rs +++ b/src/dma/transfer/buffer.rs @@ -609,6 +609,18 @@ where } } +impl AsRef> for MemoryBuffer { + fn as_ref(&self) -> &Buffer<'static, Memory> { + &self.buffer + } +} + +impl From> for Buffer<'static, Memory> { + fn from(x: MemoryBuffer) -> Self { + x.buffer + } +} + #[derive(Debug, EnumAsInner)] pub enum MemoryBufferType where diff --git a/src/dma/transfer/config.rs b/src/dma/transfer/config.rs index 18e756e8..8b3d6d96 100644 --- a/src/dma/transfer/config.rs +++ b/src/dma/transfer/config.rs @@ -5,7 +5,7 @@ use super::super::stream::config::{ PincConf, Pincos, TransferDirectionConf, TransferModeConf, }; use super::buffer::{IncrementedBuffer, MemoryBuffer, MemoryBufferType}; -use super::{Buffer, IPayloadSize, Payload, PayloadSize, TransferBuffers}; +use super::{Buffer, Buffers, IPayloadSize, Payload, PayloadSize}; use core::convert::TryFrom; use enum_as_inner::EnumAsInner; @@ -40,7 +40,7 @@ where pub fn from_stream_config( conf: StreamConfig, - buffers: TransferBuffers<'wo, Peripheral, Memory>, + buffers: Buffers<'wo, Peripheral, Memory>, ) -> Self { let additional_config = conf.into(); let transfer_direction = match conf.transfer_direction { @@ -119,7 +119,7 @@ where } fn pinc(&self) -> Pinc { - let buffers = self.buffers().get(); + let buffers = self.buffers(); if buffers.peripheral_buffer.is_fixed() { Pinc::Fixed @@ -129,7 +129,7 @@ where } fn pincos(&self) -> Option { - let buffers = self.buffers().get(); + let buffers = self.buffers(); match &buffers.peripheral_buffer { Buffer::Fixed(_) => None, @@ -141,7 +141,7 @@ where } fn minc(&self) -> Minc { - let buffers = self.buffers().get(); + let buffers = self.buffers(); match &buffers.memory_buffer.m0a().get() { Buffer::Fixed(_) => Minc::Fixed, @@ -168,11 +168,11 @@ where } pub fn pa(&self) -> Pa { - Pa(self.buffers().get().peripheral_buffer.as_ptr(Some(0)) as u32) + Pa(self.buffers().peripheral_buffer.as_ptr(Some(0)) as u32) } pub fn m0a(&self) -> M0a { - match &self.buffers().get().memory_buffer { + match &self.buffers().memory_buffer { MemoryBufferType::SingleBuffer(memory) => { M0a(memory.get().as_ptr(Some(0)) as u32) } @@ -184,7 +184,7 @@ where pub fn m1a(&self) -> Option { if let MemoryBufferType::DoubleBuffer(buffer) = - &self.buffers().get().memory_buffer + &self.buffers().memory_buffer { Some(M1a(buffer.memories()[1].get().as_ptr(Some(0)) as u32)) } else { @@ -195,7 +195,7 @@ where pub fn stream_config(&self, conf: &mut StreamConfig) { conf.transfer_direction = self.transfer_direction_conf(); - let buffers = self.buffers().get(); + let buffers = self.buffers(); // Configure ndt @@ -240,13 +240,13 @@ where conf.minc = self.minc(); } - pub fn buffers(&self) -> &TransferBuffers<'wo, Peripheral, Memory> { + pub fn buffers(&self) -> &Buffers<'wo, Peripheral, Memory> { self.transfer_direction.buffers() } pub fn buffers_mut(&mut self, op: F) where - for<'a> F: FnOnce(&'a mut TransferBuffers<'wo, Peripheral, Memory>), + for<'a> F: FnOnce(&'a mut Buffers<'wo, Peripheral, Memory>), { self.transfer_direction.buffers_mut(op); @@ -255,7 +255,7 @@ where pub unsafe fn buffers_mut_unchecked( &mut self, - ) -> &mut TransferBuffers<'wo, Peripheral, Memory> { + ) -> &mut Buffers<'wo, Peripheral, Memory> { self.transfer_direction.buffers_mut_unchecked() } @@ -264,7 +264,7 @@ where } fn check_self(&self) { - let buffers = self.buffers().get(); + let buffers = self.buffers(); // Check Buffer Mode if matches!( @@ -324,7 +324,7 @@ where Peripheral: Payload, Memory: Payload, { - pub fn buffers(&self) -> &TransferBuffers<'wo, Peripheral, Memory> { + pub fn buffers(&self) -> &Buffers<'wo, Peripheral, Memory> { match self { TransferDirection::P2M(p2m) => p2m.buffers(), TransferDirection::M2P(m2p) => m2p.buffers(), @@ -334,7 +334,7 @@ where pub fn buffers_mut(&mut self, op: F) where - for<'a> F: FnOnce(&'a mut TransferBuffers<'wo, Peripheral, Memory>), + for<'a> F: FnOnce(&'a mut Buffers<'wo, Peripheral, Memory>), { match self { TransferDirection::P2M(p2m) => p2m.buffers_mut(op), @@ -345,7 +345,7 @@ where pub unsafe fn buffers_mut_unchecked( &mut self, - ) -> &mut TransferBuffers<'wo, Peripheral, Memory> { + ) -> &mut Buffers<'wo, Peripheral, Memory> { match self { TransferDirection::P2M(p2m) => p2m.buffers_mut_unchecked(), TransferDirection::M2P(m2p) => m2p.buffers_mut_unchecked(), @@ -353,7 +353,7 @@ where } } - pub fn free(self) -> TransferBuffers<'wo, Peripheral, Memory> { + pub fn free(self) -> Buffers<'wo, Peripheral, Memory> { match self { TransferDirection::P2M(p2m) => p2m.free(), TransferDirection::M2P(m2p) => m2p.free(), @@ -368,7 +368,7 @@ where Peripheral: Payload, Memory: Payload, { - buffers: TransferBuffers<'wo, Peripheral, Memory>, + buffers: Buffers<'wo, Peripheral, Memory>, } impl<'wo, Peripheral, Memory> PeripheralToMemory<'wo, Peripheral, Memory> @@ -376,7 +376,7 @@ where Peripheral: Payload, Memory: Payload, { - pub fn new(buffers: TransferBuffers<'wo, Peripheral, Memory>) -> Self { + pub fn new(buffers: Buffers<'wo, Peripheral, Memory>) -> Self { let s = Self { buffers }; s.check_self(); @@ -384,13 +384,13 @@ where s } - pub fn buffers(&self) -> &TransferBuffers<'wo, Peripheral, Memory> { + pub fn buffers(&self) -> &Buffers<'wo, Peripheral, Memory> { &self.buffers } pub fn buffers_mut(&mut self, op: F) where - for<'a> F: FnOnce(&'a mut TransferBuffers<'wo, Peripheral, Memory>), + for<'a> F: FnOnce(&'a mut Buffers<'wo, Peripheral, Memory>), { op(&mut self.buffers); @@ -399,17 +399,17 @@ where pub unsafe fn buffers_mut_unchecked( &mut self, - ) -> &mut TransferBuffers<'wo, Peripheral, Memory> { + ) -> &mut Buffers<'wo, Peripheral, Memory> { &mut self.buffers } - pub fn free(self) -> TransferBuffers<'wo, Peripheral, Memory> { + pub fn free(self) -> Buffers<'wo, Peripheral, Memory> { self.buffers } fn check_self(&self) { - assert!(self.buffers.get().peripheral_buffer.is_read()); - assert!(self.buffers.get().memory_buffer.is_read()); + assert!(self.buffers.peripheral_buffer.is_read()); + assert!(self.buffers.memory_buffer.is_read()); } } @@ -419,7 +419,7 @@ where Peripheral: Payload, Memory: Payload, { - buffers: TransferBuffers<'wo, Peripheral, Memory>, + buffers: Buffers<'wo, Peripheral, Memory>, } impl<'wo, Peripheral, Memory> MemoryToPeripheral<'wo, Peripheral, Memory> @@ -427,7 +427,7 @@ where Peripheral: Payload, Memory: Payload, { - pub fn new(buffers: TransferBuffers<'wo, Peripheral, Memory>) -> Self { + pub fn new(buffers: Buffers<'wo, Peripheral, Memory>) -> Self { let s = Self { buffers }; s.check_self(); @@ -435,13 +435,13 @@ where s } - pub fn buffers(&self) -> &TransferBuffers<'wo, Peripheral, Memory> { + pub fn buffers(&self) -> &Buffers<'wo, Peripheral, Memory> { &self.buffers } pub fn buffers_mut(&mut self, op: F) where - for<'a> F: FnOnce(&'a mut TransferBuffers<'wo, Peripheral, Memory>), + for<'a> F: FnOnce(&'a mut Buffers<'wo, Peripheral, Memory>), { op(&mut self.buffers); @@ -450,17 +450,17 @@ where pub unsafe fn buffers_mut_unchecked( &mut self, - ) -> &mut TransferBuffers<'wo, Peripheral, Memory> { + ) -> &mut Buffers<'wo, Peripheral, Memory> { &mut self.buffers } - pub fn free(self) -> TransferBuffers<'wo, Peripheral, Memory> { + pub fn free(self) -> Buffers<'wo, Peripheral, Memory> { self.buffers } fn check_self(&self) { - assert!(self.buffers.get().peripheral_buffer.is_write()); - assert!(self.buffers.get().memory_buffer.is_read()); + assert!(self.buffers.peripheral_buffer.is_write()); + assert!(self.buffers.memory_buffer.is_read()); } } @@ -470,7 +470,7 @@ where Source: Payload, Dest: Payload, { - buffers: TransferBuffers<'wo, Source, Dest>, + buffers: Buffers<'wo, Source, Dest>, } impl<'wo, Source, Dest> MemoryToMemory<'wo, Source, Dest> @@ -478,7 +478,7 @@ where Source: Payload, Dest: Payload, { - pub fn new(buffers: TransferBuffers<'wo, Source, Dest>) -> Self { + pub fn new(buffers: Buffers<'wo, Source, Dest>) -> Self { let s = Self { buffers }; s.check_self(); @@ -486,13 +486,13 @@ where s } - pub fn buffers(&self) -> &TransferBuffers<'wo, Source, Dest> { + pub fn buffers(&self) -> &Buffers<'wo, Source, Dest> { &self.buffers } pub fn buffers_mut(&mut self, op: F) where - for<'a> F: FnOnce(&'a mut TransferBuffers<'wo, Source, Dest>), + for<'a> F: FnOnce(&'a mut Buffers<'wo, Source, Dest>), { op(&mut self.buffers); @@ -501,23 +501,23 @@ where pub unsafe fn buffers_mut_unchecked( &mut self, - ) -> &mut TransferBuffers<'wo, Source, Dest> { + ) -> &mut Buffers<'wo, Source, Dest> { &mut self.buffers } pub fn source_buffer(&self) -> &Buffer<'wo, Source> { - &self.buffers.get().peripheral_buffer + &self.buffers.peripheral_buffer } pub fn dest_buffer(&self) -> &MemoryBuffer { - &self.buffers.get().memory_buffer.as_single_buffer().unwrap() + &self.buffers.memory_buffer.as_single_buffer().unwrap() } pub fn dest_buffer_mut(&mut self, op: F) where for<'a> F: FnOnce(&'a mut MemoryBuffer), { - self.buffers.get_mut(move |b| { + self.buffers_mut(move |b| { op(&mut b.memory_buffer.as_single_buffer_mut().unwrap()) }); } @@ -525,22 +525,18 @@ where pub unsafe fn dest_buffer_mut_unchecked( &mut self, ) -> &mut MemoryBuffer { - self.buffers - .get_mut_unchecked() - .memory_buffer - .as_single_buffer_mut() - .unwrap() + self.buffers.memory_buffer.as_single_buffer_mut().unwrap() } - pub fn free(self) -> TransferBuffers<'wo, Source, Dest> { + pub fn free(self) -> Buffers<'wo, Source, Dest> { self.buffers } fn check_self(&self) { - assert!(self.buffers.get().peripheral_buffer.is_read()); - assert!(self.buffers.get().memory_buffer.is_write()); + assert!(self.buffers.peripheral_buffer.is_read()); + assert!(self.buffers.memory_buffer.is_write()); - assert!(self.buffers.get().memory_buffer.is_single_buffer()); + assert!(self.buffers.memory_buffer.is_single_buffer()); } } diff --git a/src/dma/transfer/mod.rs b/src/dma/transfer/mod.rs index 707f5254..41f3e7d5 100644 --- a/src/dma/transfer/mod.rs +++ b/src/dma/transfer/mod.rs @@ -147,17 +147,15 @@ pub trait TransferState<'wo>: Send + Sync + private::Sealed { type Peripheral: Payload; type Memory: Payload; - fn buffers(&self) -> &TransferBuffers<'wo, Self::Peripheral, Self::Memory>; + fn buffers(&self) -> &Buffers<'wo, Self::Peripheral, Self::Memory>; fn buffers_mut(&mut self, op: F) where - for<'a> F: FnOnce( - &'a mut TransferBuffers<'wo, Self::Peripheral, Self::Memory>, - ); + for<'a> F: FnOnce(&'a mut Buffers<'wo, Self::Peripheral, Self::Memory>); unsafe fn buffers_mut_unchecked( &mut self, - ) -> &mut TransferBuffers<'wo, Self::Peripheral, Self::Memory>; + ) -> &mut Buffers<'wo, Self::Peripheral, Self::Memory>; } pub struct Start<'wo, Peripheral, Memory> @@ -184,20 +182,20 @@ where type Peripheral = Peripheral; type Memory = Memory; - fn buffers(&self) -> &TransferBuffers<'wo, Peripheral, Memory> { + fn buffers(&self) -> &Buffers<'wo, Peripheral, Memory> { self.conf.transfer_direction().buffers() } fn buffers_mut(&mut self, op: F) where - for<'a> F: FnOnce(&'a mut TransferBuffers<'wo, Peripheral, Memory>), + for<'a> F: FnOnce(&'a mut Buffers<'wo, Peripheral, Memory>), { self.conf.transfer_direction_mut(|t| t.buffers_mut(op)); } unsafe fn buffers_mut_unchecked( &mut self, - ) -> &mut TransferBuffers<'wo, Peripheral, Memory> { + ) -> &mut Buffers<'wo, Peripheral, Memory> { self.conf .transfer_direction_mut_unchecked() .buffers_mut_unchecked() @@ -211,7 +209,7 @@ where CXX: ChannelId, { stream: Stream, - buffers: TransferBuffers<'wo, Peripheral, Memory>, + buffers: Buffers<'wo, Peripheral, Memory>, } impl private::Sealed @@ -233,20 +231,20 @@ where type Peripheral = Peripheral; type Memory = Memory; - fn buffers(&self) -> &TransferBuffers<'wo, Peripheral, Memory> { + fn buffers(&self) -> &Buffers<'wo, Peripheral, Memory> { &self.buffers } fn buffers_mut(&mut self, op: F) where - for<'a> F: FnOnce(&'a mut TransferBuffers<'wo, Peripheral, Memory>), + for<'a> F: FnOnce(&'a mut Buffers<'wo, Peripheral, Memory>), { op(&mut self.buffers) } unsafe fn buffers_mut_unchecked( &mut self, - ) -> &mut TransferBuffers<'wo, Peripheral, Memory> { + ) -> &mut Buffers<'wo, Peripheral, Memory> { &mut self.buffers } } @@ -376,59 +374,6 @@ where pub memory_buffer: MemoryBufferType, } -#[derive(Debug)] -pub struct TransferBuffers<'wo, Peripheral, Memory> -where - Peripheral: Payload, - Memory: Payload, -{ - buffers: Buffers<'wo, Peripheral, Memory>, -} - -impl<'wo, Peripheral, Memory> TransferBuffers<'wo, Peripheral, Memory> -where - Peripheral: Payload, - Memory: Payload, -{ - pub fn new(buffers: Buffers<'wo, Peripheral, Memory>) -> Self { - let s = Self { buffers }; - - s.check_self(); - - s - } - - pub fn get(&self) -> &Buffers<'wo, Peripheral, Memory> { - &self.buffers - } - - pub fn get_mut(&mut self, op: F) - where - for<'a> F: FnOnce(&'a mut Buffers<'wo, Peripheral, Memory>), - { - op(&mut self.buffers); - - self.check_self(); - } - - pub unsafe fn get_mut_unchecked( - &mut self, - ) -> &mut Buffers<'wo, Peripheral, Memory> { - &mut self.buffers - } - - pub fn free(self) -> Buffers<'wo, Peripheral, Memory> { - self.buffers - } - - fn check_self(&self) { - assert_ne!( - self.buffers.peripheral_buffer.is_read(), - self.buffers.memory_buffer.is_read() - ); - } -} - #[derive(Copy, Clone, Debug, EnumAsInner)] pub enum PayloadPort where From 3d33487bc603bf2df8a126bac998741cbd05ddce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ad=C3=A4?= Date: Thu, 23 Apr 2020 18:13:27 +0200 Subject: [PATCH 092/103] Implemented more methods for transfer --- src/dma/transfer/mod.rs | 76 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 75 insertions(+), 1 deletion(-) diff --git a/src/dma/transfer/mod.rs b/src/dma/transfer/mod.rs index 41f3e7d5..93723d8a 100644 --- a/src/dma/transfer/mod.rs +++ b/src/dma/transfer/mod.rs @@ -6,7 +6,7 @@ pub mod config; use self::buffer::MemoryBufferType; use super::stream::config::{MSize, PSize}; use super::stream::{ - Disabled, Enabled, Error as StreamError, IsrCleared, IsrUncleared, + Disabled, Enabled, Error as StreamError, Event, IsrCleared, IsrUncleared, StreamIsr, }; use super::{ChannelId, Stream}; @@ -82,6 +82,13 @@ where &mut self.state.stream } + pub fn check_isr( + &self, + isr: &StreamIsr, + ) -> Result, StreamError> { + self.state.stream.check_isr(isr) + } + pub fn wait_until_completed( &self, isr: &StreamIsr, @@ -124,6 +131,50 @@ where self.state.stream.wait_until_next_half_clear(isr) } + pub fn current_peripheral_index_(&self) -> Option { + match &self.state.buffers.peripheral_buffer { + Buffer::Fixed(_) => None, + Buffer::Incremented(buffer) => { + let ndt = u16::from(self.state.stream.ndt()) as usize; + + if ndt == 0 { + None + } else { + Some(buffer.len() - ndt) + } + } + } + } + + pub fn current_memory_index(&self) -> Option { + match &self.state.buffers.memory_buffer.m0a().get() { + Buffer::Fixed(_) => None, + Buffer::Incremented(buffer) => { + let ndt = u16::from(self.state.stream.ndt()) as usize; + let p_size: usize = + PayloadSize::from_payload::().into(); + let m_size: usize = + PayloadSize::from_payload::().into(); + + let ndt_bytes = ndt * p_size; + + let remaining_memory_items; + + if ndt_bytes % m_size == 0 { + remaining_memory_items = ndt_bytes / m_size; + } else { + remaining_memory_items = ndt_bytes / m_size + 1; + } + + if ndt == 0 { + None + } else { + Some(buffer.len() - remaining_memory_items) + } + } + } + } + pub fn stop( self, ) -> ( @@ -143,6 +194,29 @@ where } } +impl<'wo, State> Transfer<'wo, State> +where + State: TransferState<'wo>, +{ + pub fn buffers(&self) -> &Buffers<'wo, State::Peripheral, State::Memory> { + self.state.buffers() + } + + pub fn buffers_mut(&mut self, op: F) + where + for<'a> F: + FnOnce(&'a mut Buffers<'wo, State::Peripheral, State::Memory>), + { + self.state.buffers_mut(op); + } + + pub unsafe fn buffers_mut_unchecked( + &mut self, + ) -> &mut Buffers<'wo, State::Peripheral, State::Memory> { + self.state.buffers_mut_unchecked() + } +} + pub trait TransferState<'wo>: Send + Sync + private::Sealed { type Peripheral: Payload; type Memory: Payload; From be2378edc08b8673b8f647d60fd0548078931531 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ad=C3=A4?= Date: Thu, 23 Apr 2020 19:54:01 +0200 Subject: [PATCH 093/103] update --- src/dma/transfer/mod.rs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/dma/transfer/mod.rs b/src/dma/transfer/mod.rs index 93723d8a..29dce1ff 100644 --- a/src/dma/transfer/mod.rs +++ b/src/dma/transfer/mod.rs @@ -131,7 +131,7 @@ where self.state.stream.wait_until_next_half_clear(isr) } - pub fn current_peripheral_index_(&self) -> Option { + pub fn current_peripheral_index(&self) -> Option { match &self.state.buffers.peripheral_buffer { Buffer::Fixed(_) => None, Buffer::Incremented(buffer) => { @@ -151,6 +151,11 @@ where Buffer::Fixed(_) => None, Buffer::Incremented(buffer) => { let ndt = u16::from(self.state.stream.ndt()) as usize; + + if ndt == 0 { + return None; + } + let p_size: usize = PayloadSize::from_payload::().into(); let m_size: usize = @@ -166,11 +171,7 @@ where remaining_memory_items = ndt_bytes / m_size + 1; } - if ndt == 0 { - None - } else { - Some(buffer.len() - remaining_memory_items) - } + Some(buffer.len() - remaining_memory_items) } } } From e7beb6be5d4bc46deda1e61d36f998797d750c2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ad=C3=A4?= Date: Fri, 24 Apr 2020 17:24:38 +0200 Subject: [PATCH 094/103] update --- src/dma/transfer/buffer.rs | 22 ++++- src/dma/transfer/mod.rs | 167 ++++++++++--------------------------- 2 files changed, 61 insertions(+), 128 deletions(-) diff --git a/src/dma/transfer/buffer.rs b/src/dma/transfer/buffer.rs index c114f6f6..873b6845 100644 --- a/src/dma/transfer/buffer.rs +++ b/src/dma/transfer/buffer.rs @@ -319,6 +319,10 @@ where slice.len() } } + + pub fn inner(&self) -> *const [P] { + self.0 + } } unsafe impl

Send for RegularOffsetBufferR

where P: Payload {} @@ -376,6 +380,10 @@ where slice.len() } } + + pub fn inner(&self) -> *mut [P] { + self.0 + } } unsafe impl

Send for RegularOffsetBufferW

where P: Payload {} @@ -456,7 +464,7 @@ where pub fn new(buffer: &'wo [&'static P]) -> Self { check_buffer_not_empty(buffer); - let buffer = unsafe { &*(buffer as *const _ as *const _) }; + let buffer = unsafe { &*(buffer as *const _ as *const [*const P]) }; check_word_offset(buffer); @@ -474,6 +482,10 @@ where pub fn len(self) -> usize { self.0.len() } + + pub fn inner(&self) -> &'wo [*const P] { + self.0 + } } unsafe impl

Send for WordOffsetBufferR<'_, P> where P: Payload {} @@ -494,9 +506,9 @@ where check_buffer_not_empty(buffer); unsafe { - check_word_offset::

(&*(buffer as *const _ as *const _)); + check_word_offset::

(&*(buffer as *const _ as *const [*const P])); - WordOffsetBufferW(&mut *(buffer as *mut _ as *mut _)) + WordOffsetBufferW(&mut *(buffer as *mut _ as *mut [*mut P])) } } @@ -525,6 +537,10 @@ where pub fn len(&self) -> usize { self.0.len() } + + pub fn inner(&self) -> &[*mut P] { + &*self.0 + } } unsafe impl

Send for WordOffsetBufferW<'_, P> where P: Payload {} diff --git a/src/dma/transfer/mod.rs b/src/dma/transfer/mod.rs index 29dce1ff..65f0006f 100644 --- a/src/dma/transfer/mod.rs +++ b/src/dma/transfer/mod.rs @@ -19,19 +19,26 @@ use enum_as_inner::EnumAsInner; pub use self::buffer::Buffer; pub use self::config::Config; -pub struct Transfer<'wo, State: TransferState<'wo>> { +pub struct Transfer<'wo, Peripheral, Memory, State> +where + Peripheral: Payload, + Memory: Payload, + State: TransferState, +{ + conf: Config<'wo, Peripheral, Memory>, state: State, _phantom: PhantomData<&'wo ()>, } -impl<'wo, Peripheral, Memory> Transfer<'wo, Start<'wo, Peripheral, Memory>> +impl<'wo, Peripheral, Memory> Transfer<'wo, Peripheral, Memory, Start> where Peripheral: Payload, Memory: Payload, { pub fn new(conf: Config<'wo, Peripheral, Memory>) -> Self { Self { - state: Start { conf }, + conf, + state: Start, _phantom: PhantomData, } } @@ -39,13 +46,13 @@ where pub fn start( self, mut stream: Stream, - ) -> Transfer<'wo, Ongoing<'wo, Peripheral, Memory, CXX>> { + ) -> Transfer<'wo, Peripheral, Memory, Ongoing> { self.configure_stream(&mut stream); Transfer { + conf: self.conf, state: Ongoing { stream: unsafe { stream.enable() }, - buffers: self.state.conf.free().free(), }, _phantom: PhantomData, } @@ -57,18 +64,25 @@ where ) { let mut conf = stream.config(); - self.state.conf.stream_config(&mut conf); + self.conf.stream_config(&mut conf); stream.apply_config(conf); } + pub fn buffers_mut(&mut self, op: F) + where + for<'a> F: FnOnce(&'a mut Buffers<'wo, Peripheral, Memory>), + { + self.conf.buffers_mut(op); + } + pub fn free(self) -> Config<'wo, Peripheral, Memory> { - self.state.conf + self.conf } } impl<'wo, Peripheral, Memory, CXX> - Transfer<'wo, Ongoing<'wo, Peripheral, Memory, CXX>> + Transfer<'wo, Peripheral, Memory, Ongoing> where Peripheral: Payload, Memory: Payload, @@ -132,7 +146,7 @@ where } pub fn current_peripheral_index(&self) -> Option { - match &self.state.buffers.peripheral_buffer { + match &self.conf.buffers().peripheral_buffer { Buffer::Fixed(_) => None, Buffer::Incremented(buffer) => { let ndt = u16::from(self.state.stream.ndt()) as usize; @@ -147,7 +161,7 @@ where } pub fn current_memory_index(&self) -> Option { - match &self.state.buffers.memory_buffer.m0a().get() { + match self.conf.buffers().memory_buffer.m0a().get() { Buffer::Fixed(_) => None, Buffer::Incremented(buffer) => { let ndt = u16::from(self.state.stream.ndt()) as usize; @@ -179,15 +193,14 @@ where pub fn stop( self, ) -> ( - Transfer<'wo, Start<'wo, Peripheral, Memory>>, + Transfer<'wo, Peripheral, Memory, Start>, Stream, ) { let stream = self.state.stream.disable(); - let conf = - Config::from_stream_config(stream.config(), self.state.buffers); let transfer = Transfer { - state: Start { conf }, + conf: self.conf, + state: Start, _phantom: PhantomData, }; @@ -195,134 +208,38 @@ where } } -impl<'wo, State> Transfer<'wo, State> +impl<'wo, Peripheral, Memory, State> Transfer<'wo, Peripheral, Memory, State> where - State: TransferState<'wo>, + Peripheral: Payload, + Memory: Payload, + State: TransferState, { - pub fn buffers(&self) -> &Buffers<'wo, State::Peripheral, State::Memory> { - self.state.buffers() - } - - pub fn buffers_mut(&mut self, op: F) - where - for<'a> F: - FnOnce(&'a mut Buffers<'wo, State::Peripheral, State::Memory>), - { - self.state.buffers_mut(op); + pub fn buffers(&self) -> &Buffers<'wo, Peripheral, Memory> { + self.conf.buffers() } pub unsafe fn buffers_mut_unchecked( &mut self, - ) -> &mut Buffers<'wo, State::Peripheral, State::Memory> { - self.state.buffers_mut_unchecked() + ) -> &mut Buffers<'wo, Peripheral, Memory> { + self.conf.buffers_mut_unchecked() } } -pub trait TransferState<'wo>: Send + Sync + private::Sealed { - type Peripheral: Payload; - type Memory: Payload; - - fn buffers(&self) -> &Buffers<'wo, Self::Peripheral, Self::Memory>; - - fn buffers_mut(&mut self, op: F) - where - for<'a> F: FnOnce(&'a mut Buffers<'wo, Self::Peripheral, Self::Memory>); - - unsafe fn buffers_mut_unchecked( - &mut self, - ) -> &mut Buffers<'wo, Self::Peripheral, Self::Memory>; -} - -pub struct Start<'wo, Peripheral, Memory> -where - Peripheral: Payload, - Memory: Payload, -{ - conf: Config<'wo, Peripheral, Memory>, -} - -impl private::Sealed for Start<'_, Peripheral, Memory> -where - Peripheral: Payload, - Memory: Payload, -{ -} - -impl<'wo, Peripheral, Memory> TransferState<'wo> - for Start<'wo, Peripheral, Memory> -where - Peripheral: Payload, - Memory: Payload, -{ - type Peripheral = Peripheral; - type Memory = Memory; +pub trait TransferState: Send + Sync + private::Sealed {} - fn buffers(&self) -> &Buffers<'wo, Peripheral, Memory> { - self.conf.transfer_direction().buffers() - } +pub struct Start; - fn buffers_mut(&mut self, op: F) - where - for<'a> F: FnOnce(&'a mut Buffers<'wo, Peripheral, Memory>), - { - self.conf.transfer_direction_mut(|t| t.buffers_mut(op)); - } +impl private::Sealed for Start {} - unsafe fn buffers_mut_unchecked( - &mut self, - ) -> &mut Buffers<'wo, Peripheral, Memory> { - self.conf - .transfer_direction_mut_unchecked() - .buffers_mut_unchecked() - } -} +impl TransferState for Start {} -pub struct Ongoing<'wo, Peripheral, Memory, CXX> -where - Peripheral: Payload, - Memory: Payload, - CXX: ChannelId, -{ +pub struct Ongoing { stream: Stream, - buffers: Buffers<'wo, Peripheral, Memory>, } -impl private::Sealed - for Ongoing<'_, Peripheral, Memory, CXX> -where - Peripheral: Payload, - Memory: Payload, - CXX: ChannelId, -{ -} - -impl<'wo, Peripheral, Memory, CXX> TransferState<'wo> - for Ongoing<'wo, Peripheral, Memory, CXX> -where - Peripheral: Payload, - Memory: Payload, - CXX: ChannelId, -{ - type Peripheral = Peripheral; - type Memory = Memory; - - fn buffers(&self) -> &Buffers<'wo, Peripheral, Memory> { - &self.buffers - } - - fn buffers_mut(&mut self, op: F) - where - for<'a> F: FnOnce(&'a mut Buffers<'wo, Peripheral, Memory>), - { - op(&mut self.buffers) - } +impl private::Sealed for Ongoing {} - unsafe fn buffers_mut_unchecked( - &mut self, - ) -> &mut Buffers<'wo, Peripheral, Memory> { - &mut self.buffers - } -} +impl TransferState for Ongoing {} /// # Safety /// From baeda153eb03c0e802afff73ac7b8e1e7fc73711 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ad=C3=A4?= Date: Sat, 25 Apr 2020 00:17:38 +0200 Subject: [PATCH 095/103] update --- src/dma/macros.rs | 18 +++- src/dma/stream/config.rs | 142 +++++++++++++++++++++++++++ src/dma/stream/mod.rs | 203 +++++++++------------------------------ src/dma/transfer/mod.rs | 53 ++++++++-- 4 files changed, 250 insertions(+), 166 deletions(-) diff --git a/src/dma/macros.rs b/src/dma/macros.rs index c3d4e92c..a5476d43 100644 --- a/src/dma/macros.rs +++ b/src/dma/macros.rs @@ -1,8 +1,14 @@ //! Macros macro_rules! type_state { - ($trait:ident, $($type_state:ident),*) => { - pub trait $trait: Copy + Clone + PartialEq + Eq + core::fmt::Debug + crate::private::Sealed {} + ($trait:ident $({$($item_def:item),*})?, $($type_state:ident $({$($item_impl:item),*})?),*) => { + pub trait $trait: Copy + Clone + PartialEq + Eq + core::fmt::Debug + crate::private::Sealed { + $( + $( + $item_def + )* + )? + } $( #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] @@ -10,7 +16,13 @@ macro_rules! type_state { impl crate::private::Sealed for $type_state {} - impl $trait for $type_state {} + impl $trait for $type_state { + $( + $( + $item_impl + )* + )? + } )* }; } diff --git a/src/dma/stream/config.rs b/src/dma/stream/config.rs index e05a96fb..fa8c0b0c 100644 --- a/src/dma/stream/config.rs +++ b/src/dma/stream/config.rs @@ -2,6 +2,144 @@ // CONFIG ///////////////////////////////////////////////////////////////////////// +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +pub struct CheckedConfig { + config: Config, +} + +impl CheckedConfig { + pub fn new(config: Config) -> Self { + let s = Self { config }; + + s.check_config(); + + s + } + + pub unsafe fn new_unchecked(config: Config) -> Self { + Self { config } + } + + pub fn config(&self) -> Config { + self.config + } + + /// Checks the config for data integrity + fn check_config(&self) { + if self.config.circular_mode() == CircularMode::Enabled { + self.check_config_circular(); + } + + if self.config.transfer_mode() == TransferMode::Fifo { + self.check_config_fifo(); + } + + self.check_ndt(); + } + + /// Checks the circular config. + // + // Reference: RM0433 Rev 6 - Chapter 15.3.10 + fn check_config_circular(&self) { + // Check invariants + if self.config.transfer_mode() == TransferMode::Fifo { + let ndt = self.config.ndt.value() as usize; + let m_burst = self.config.m_burst().into_num(); + let p_burst = self.config.p_burst().into_num(); + let m_size = self.config.m_size().into_num(); + let p_size = self.config.p_size.into_num(); + + if self.config.m_burst() != MBurst::Single + && ndt % (m_burst * m_size / p_size) != 0 + { + panic!( + "Data integrity not guaranteed, because \ + `num_data_items != Multiple of (m_burst * (m_size / p_size))`" + ); + } + + if ndt % (p_burst * p_size) != 0 { + panic!( + "Data integrity not guaranteed, because \ + `num_data_items != Multiple of (p_burst * p_size)`" + ); + } + } else { + let ndt = self.config.ndt.value() as usize; + let p_size = self.config.p_size.into_num(); + + if ndt % p_size != 0 { + panic!( + "Data integrity not guaranteed, because \ + `num_data_items != Multiple of (p_size)`" + ); + } + } + } + + /// Checks the fifo config. + fn check_config_fifo(&self) { + if self.config.m_burst() != MBurst::Single { + self.check_config_fifo_m_burst(); + } + + if self.config.p_burst() != PBurst::Single { + self.check_config_fifo_p_burst(); + } + } + + /// Checks the memory config of fifo stream. + // + // Reference: RM0433 Rev 6 - Chapter 15.3.14 + fn check_config_fifo_m_burst(&self) { + let m_size = self.config.m_size().into_num(); + let m_burst = self.config.m_burst().into_num(); + // Fifo Size in bytes + let fifo_size = self.config.fifo_threshold().unwrap().into_num() * 4; + + if m_size * m_burst > fifo_size { + panic!("FIFO configuration invalid, because `msize * mburst > fifo_size`"); + } + + if fifo_size % (m_size * m_burst) != 0 { + panic!("FIFO configuration invalid, because `fifo_size % (msize * mburst) != 0`"); + } + } + + /// Checks the peripheral config of fifio stream. + // + // Reference: RM0433 Rev 6 - Chapter 15.3.14 + fn check_config_fifo_p_burst(&self) { + let p_burst = self.config.p_burst().into_num(); + let p_size = self.config.p_size.into_num(); + // 4 Words = 16 Bytes + const FULL_FIFO_BYTES: usize = 16; + + if p_burst * p_size == FULL_FIFO_BYTES + && self.config.fifo_threshold().unwrap() == FifoThreshold::F3_4 + { + panic!( + "FIFO configuration invalid, because \ + `pburst * psize == FULL_FIFO_SIZE` and \ + `fifo_threshold == 3/4`" + ); + } + } + + /// Checks the NDT register + // + // Reference: RM0433 Rev 6 - Chapter 15.3.12 + fn check_ndt(&self) { + let m_size = self.config.m_size().into_num(); + let p_size = self.config.p_size.into_num(); + let ndt = self.config.ndt.value() as usize; + + if m_size > p_size && ndt % (m_size / p_size) != 0 { + panic!("`NDT` must be a multiple of (`m_size / p_size`)."); + } + } +} + #[derive(Debug, PartialEq, Eq, Clone, Copy)] pub struct Config { pub transfer_complete_interrupt: TransferCompleteInterrupt, @@ -19,6 +157,10 @@ pub struct Config { } impl Config { + pub fn check(&self) -> CheckedConfig { + CheckedConfig::new(*self) + } + pub fn transfer_direction(self) -> TransferDirection { self.transfer_direction.into() } diff --git a/src/dma/stream/mod.rs b/src/dma/stream/mod.rs index 1187e270..9a0bd7c1 100644 --- a/src/dma/stream/mod.rs +++ b/src/dma/stream/mod.rs @@ -6,11 +6,10 @@ use self::config::{ BufferMode, BufferModeConf, CircularMode, CircularModeConf, CurrentTarget, DirectConf, DirectModeErrorInterrupt, DoubleBufferConf, FifoConf, FifoErrorInterrupt, FifoThreshold, FlowController, FlowControllerConf, - HalfTransferInterrupt, IntoNum, M0a, M1a, MBurst, MSize, Minc, Ndt, - NotM2MConf, PBurst, PBurstConf, PSize, Pa, Pinc, PincConf, Pincos, - PriorityLevel, TransferCompleteInterrupt, TransferDirection, - TransferDirectionConf, TransferErrorInterrupt, TransferMode, - TransferModeConf, + HalfTransferInterrupt, M0a, M1a, MBurst, MSize, Minc, Ndt, NotM2MConf, + PBurst, PBurstConf, PSize, Pa, Pinc, PincConf, Pincos, PriorityLevel, + TransferCompleteInterrupt, TransferDirection, TransferDirectionConf, + TransferErrorInterrupt, TransferMode, TransferModeConf, }; use super::{ChannelId, DmaPeripheral}; use crate::nb::Error as NbError; @@ -18,7 +17,7 @@ use crate::stm32::dma1::{HIFCR, HISR, LIFCR, LISR, ST}; use core::convert::{Infallible, TryInto}; use core::marker::PhantomData; -pub use self::config::Config; +pub use self::config::{CheckedConfig, Config}; /// DMA Stream pub struct Stream @@ -55,8 +54,8 @@ where ED: IED, IsrState: IIsrState, { - pub fn config(&self) -> Config { - Config { + pub fn config(&self) -> CheckedConfig { + let conf = Config { transfer_complete_interrupt: self.transfer_complete_interrupt(), half_transfer_interrupt: self.half_transfer_interrupt(), transfer_error_interrupt: self.transfer_error_interrupt(), @@ -69,7 +68,9 @@ where pa: self.pa(), m0a: self.m0a(), transfer_direction: self.transfer_direction_config(), - } + }; + + unsafe { CheckedConfig::new_unchecked(conf) } } fn transfer_direction_config(&self) -> TransferDirectionConf { @@ -181,7 +182,7 @@ where } /// Sets the Transfer Complete Interrupt config flag - fn set_transfer_complete_interrupt( + pub fn set_transfer_complete_interrupt( &mut self, tc_intrpt: TransferCompleteInterrupt, ) { @@ -194,7 +195,7 @@ where } /// Sets the Half Transfer Interrupt config flag - fn set_half_transfer_interrupt( + pub fn set_half_transfer_interrupt( &mut self, ht_intrpt: HalfTransferInterrupt, ) { @@ -207,7 +208,7 @@ where } /// Sets the Transfer Error Interrupt config flag - fn set_transfer_error_interrupt( + pub fn set_transfer_error_interrupt( &mut self, te_intrpt: TransferErrorInterrupt, ) { @@ -220,7 +221,7 @@ where } /// Sets the Direct Mode Error Interrupt config flag - fn set_direct_mode_error_interrupt( + pub fn set_direct_mode_error_interrupt( &mut self, dme_intrpt: DirectModeErrorInterrupt, ) { @@ -233,7 +234,7 @@ where } /// Sets the Fifo Error Interrupt config flag - fn set_fifo_error_interrupt(&mut self, fe_intrpt: FifoErrorInterrupt) { + pub fn set_fifo_error_interrupt(&mut self, fe_intrpt: FifoErrorInterrupt) { self.rb.fcr.modify(|_, w| w.feie().bit(fe_intrpt.into())); } @@ -374,7 +375,9 @@ where CXX: ChannelId, IsrState: IIsrState, { - pub fn apply_config(&mut self, config: Config) { + pub fn apply_config(&mut self, config: CheckedConfig) { + let config = config.config(); + self.set_transfer_complete_interrupt( config.transfer_complete_interrupt, ); @@ -590,146 +593,10 @@ where /// /// Aliasing rules aren't enforced. pub unsafe fn enable(self) -> Stream { - self.check_config(); - - self.enable_unchecked() - } - - /// Enables the stream without checking the config - /// - /// Consider using the checked version instead (`enable`). - /// - /// # Safety - /// - /// - Aliasing rules aren't enforced - /// - Config is not checked for guaranteeing data integrity - pub unsafe fn enable_unchecked(self) -> Stream { self.rb.cr.modify(|_, w| w.en().set_bit()); self.transmute() } - - /// Checks the config for data integrity - fn check_config(&self) { - if self.circular_mode() == CircularMode::Enabled { - self.check_config_circular(); - } - - if self.transfer_mode() == TransferMode::Fifo { - self.check_config_fifo(); - } - - self.check_ndt(); - } - - /// Checks the circular config. - // - // Reference: RM0433 Rev 6 - Chapter 15.3.10 - fn check_config_circular(&self) { - // Check for clashing config values - if self.transfer_direction() == TransferDirection::M2M - || self.flow_controller() == FlowController::Peripheral - { - panic!("For circular streams, the transfer direction must not be `M2M` and the FlowController must not be `Peripheral`."); - } - - // Check invariants - if self.transfer_mode() == TransferMode::Fifo { - let ndt = self.ndt().value() as usize; - let m_burst = self.m_burst().into_num(); - let p_burst = self.p_burst().into_num(); - let m_size = self.m_size().into_num(); - let p_size = self.p_size().into_num(); - - if self.m_burst() != MBurst::Single - && ndt % (m_burst * m_size / p_size) != 0 - { - panic!( - "Data integrity not guaranteed, because \ - `num_data_items != Multiple of (m_burst * (m_size / p_size))`" - ); - } - - if ndt % (p_burst * p_size) != 0 { - panic!( - "Data integrity not guaranteed, because \ - `num_data_items != Multiple of (p_burst * p_size)`" - ); - } - } else { - let ndt = self.ndt().value() as usize; - let p_size = self.p_size().into_num(); - - if ndt % p_size != 0 { - panic!( - "Data integrity not guaranteed, because \ - `num_data_items != Multiple of (p_size)`" - ); - } - } - } - - /// Checks the fifo config. - fn check_config_fifo(&self) { - if self.m_burst() != MBurst::Single { - self.check_config_fifo_m_burst(); - } - - if self.p_burst() != PBurst::Single { - self.check_config_fifo_p_burst(); - } - } - - /// Checks the memory config of fifo stream. - // - // Reference: RM0433 Rev 6 - Chapter 15.3.14 - fn check_config_fifo_m_burst(&self) { - let m_size = self.m_size().into_num(); - let m_burst = self.m_burst().into_num(); - // Fifo Size in bytes - let fifo_size = self.fifo_threshold().unwrap().into_num() * 4; - - if m_size * m_burst > fifo_size { - panic!("FIFO configuration invalid, because `msize * mburst > fifo_size`"); - } - - if fifo_size % (m_size * m_burst) != 0 { - panic!("FIFO configuration invalid, because `fifo_size % (msize * mburst) != 0`"); - } - } - - /// Checks the peripheral config of fifio stream. - // - // Reference: RM0433 Rev 6 - Chapter 15.3.14 - fn check_config_fifo_p_burst(&self) { - let p_burst = self.p_burst().into_num(); - let p_size = self.p_size().into_num(); - // 4 Words = 16 Bytes - const FULL_FIFO_BYTES: usize = 16; - - if p_burst * p_size == FULL_FIFO_BYTES - && self.fifo_threshold().unwrap() == FifoThreshold::F3_4 - { - panic!( - "FIFO configuration invalid, because \ - `pburst * psize == FULL_FIFO_SIZE` and \ - `fifo_threshhold == 3/4`" - ); - } - } - - /// Checks the NDT register - // - // Reference: RM0433 Rev 6 - Chapter 15.3.12 - fn check_ndt(&self) { - let m_size = self.m_size().into_num(); - let p_size = self.p_size().into_num(); - let ndt = self.config_ndt.value() as usize; - - if m_size > p_size && ndt % (m_size / p_size) != 0 { - panic!("`NDT` must be a multiple of (`m_size / p_size`)."); - } - } } impl Stream @@ -772,21 +639,45 @@ where None }; - let crashed = !self.is_enabled() && self.ndt().value() != 0; - if transfer_error || direct_mode_error || fifo_error { Err(Error { transfer_error, direct_mode_error, fifo_error, event, - crashed, + crashed: self.is_crashed(), }) } else { Ok(event) } } + /// Checks if the stream crashed + /// + /// Returns `None` if the stream is disabled and in disabled state (as stream could have been halted). + fn is_crashed(&self) -> Option { + // If the stream has been correctly disabled, no statement can be made. + if !ED::IS_ENABLED { + return None; + } + + // Check if stream is still enabled + if self.is_enabled() { + return Some(false); + } + + // If Circular-Mode is enabled, the stream wouldn't disable itself + // -> Stream crashed + if self.circular_mode() == CircularMode::Enabled { + return Some(true); + } + + // Else, if `ndt` has reached 0, the stream disabled itself automatically + // -> No crash + // Otherwise, the stream has crashed + Some(self.ndt().value() != 0) + } + /// Returns the Transfer Complete flag pub fn transfer_complete_flag(&self, isr: &StreamIsr) -> bool { match self.id() { @@ -1149,7 +1040,7 @@ where } type_state! { - IED, Disabled, Enabled + IED { const IS_ENABLED: bool; }, Disabled { const IS_ENABLED: bool = false; }, Enabled { const IS_ENABLED: bool = true; } } type_state! { @@ -1204,5 +1095,5 @@ pub struct Error { pub direct_mode_error: bool, pub fifo_error: bool, pub event: Option, - pub crashed: bool, + pub crashed: Option, } diff --git a/src/dma/transfer/mod.rs b/src/dma/transfer/mod.rs index 65f0006f..5b78d44a 100644 --- a/src/dma/transfer/mod.rs +++ b/src/dma/transfer/mod.rs @@ -4,10 +4,13 @@ pub mod buffer; pub mod config; use self::buffer::MemoryBufferType; -use super::stream::config::{MSize, PSize}; +use super::stream::config::{ + DirectModeErrorInterrupt, FifoErrorInterrupt, HalfTransferInterrupt, MSize, + PSize, TransferCompleteInterrupt, TransferErrorInterrupt, +}; use super::stream::{ - Disabled, Enabled, Error as StreamError, Event, IsrCleared, IsrUncleared, - StreamIsr, + CheckedConfig, Disabled, Enabled, Error as StreamError, Event, IsrCleared, + IsrUncleared, StreamIsr, }; use super::{ChannelId, Stream}; use crate::{nb, private}; @@ -62,11 +65,15 @@ where &self, stream: &mut Stream, ) { - let mut conf = stream.config(); + let mut conf = stream.config().config(); self.conf.stream_config(&mut conf); - stream.apply_config(conf); + stream.apply_config(CheckedConfig::new(conf)); + } + + pub fn config_mut(&mut self) -> &mut Config<'wo, Peripheral, Memory> { + &mut self.conf } pub fn buffers_mut(&mut self, op: F) @@ -92,8 +99,30 @@ where &self.state.stream } - pub fn stream_mut(&mut self) -> &mut Stream { - &mut self.state.stream + pub fn set_transfer_complete_interrupt( + &mut self, + tc: TransferCompleteInterrupt, + ) { + self.state.stream.set_transfer_complete_interrupt(tc); + } + + pub fn set_half_transfer_interrupt(&mut self, ht: HalfTransferInterrupt) { + self.state.stream.set_half_transfer_interrupt(ht); + } + + pub fn set_transfer_error_interrupt(&mut self, te: TransferErrorInterrupt) { + self.state.stream.set_transfer_error_interrupt(te); + } + + pub fn set_direct_mode_error_interrupt( + &mut self, + dme: DirectModeErrorInterrupt, + ) { + self.state.stream.set_direct_mode_error_interrupt(dme); + } + + pub fn set_fifo_error_interrupt(&mut self, fe: FifoErrorInterrupt) { + self.state.stream.set_fifo_error_interrupt(fe); } pub fn check_isr( @@ -214,6 +243,16 @@ where Memory: Payload, State: TransferState, { + pub fn config(&self) -> &Config<'wo, Peripheral, Memory> { + &self.conf + } + + pub unsafe fn config_mut_unchecked( + &mut self, + ) -> &mut Config<'wo, Peripheral, Memory> { + &mut self.conf + } + pub fn buffers(&self) -> &Buffers<'wo, Peripheral, Memory> { self.conf.buffers() } From b1f9feb1ce12d7c7c6c97ca0a63318a446344c7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ad=C3=A4?= Date: Sat, 25 Apr 2020 13:41:10 +0200 Subject: [PATCH 096/103] update --- src/dma/transfer/buffer.rs | 193 +++++++++++++++++++------------------ src/dma/transfer/config.rs | 34 +------ src/dma/transfer/mod.rs | 99 +++++++++++++------ 3 files changed, 169 insertions(+), 157 deletions(-) diff --git a/src/dma/transfer/buffer.rs b/src/dma/transfer/buffer.rs index 873b6845..498a3f69 100644 --- a/src/dma/transfer/buffer.rs +++ b/src/dma/transfer/buffer.rs @@ -29,17 +29,17 @@ where } } - pub fn is_read(&self) -> bool { + pub fn is_ref(&self) -> bool { match self { - Buffer::Fixed(buffer) => buffer.is_read(), - Buffer::Incremented(buffer) => buffer.is_read(), + Buffer::Fixed(buffer) => buffer.is_ref(), + Buffer::Incremented(buffer) => buffer.is_ref(), } } - pub fn is_write(&self) -> bool { + pub fn is_mut(&self) -> bool { match self { - Buffer::Fixed(buffer) => buffer.is_write(), - Buffer::Incremented(buffer) => buffer.is_write(), + Buffer::Fixed(buffer) => buffer.is_mut(), + Buffer::Incremented(buffer) => buffer.is_mut(), } } @@ -111,17 +111,17 @@ where } } - pub fn is_read(&self) -> bool { + pub fn is_ref(&self) -> bool { match self { - IncrementedBuffer::RegularOffset(buffer) => buffer.is_read(), - IncrementedBuffer::WordOffset(buffer) => buffer.is_read(), + IncrementedBuffer::RegularOffset(buffer) => buffer.is_ref(), + IncrementedBuffer::WordOffset(buffer) => buffer.is_ref(), } } - pub fn is_write(&self) -> bool { + pub fn is_mut(&self) -> bool { match self { - IncrementedBuffer::RegularOffset(buffer) => buffer.is_write(), - IncrementedBuffer::WordOffset(buffer) => buffer.is_write(), + IncrementedBuffer::RegularOffset(buffer) => buffer.is_mut(), + IncrementedBuffer::WordOffset(buffer) => buffer.is_mut(), } } } @@ -131,54 +131,54 @@ pub enum FixedBuffer

where P: Payload, { - Read(FixedBufferR

), - Write(FixedBufferW

), + Ref(FixedBufferRef

), + Mut(FixedBufferMut

), } impl

FixedBuffer

where P: Payload, { - pub fn is_read(&self) -> bool { + pub fn is_ref(&self) -> bool { match self { - FixedBuffer::Read(_) => true, - FixedBuffer::Write(_) => false, + FixedBuffer::Ref(_) => true, + FixedBuffer::Mut(_) => false, } } - pub fn is_write(&self) -> bool { + pub fn is_mut(&self) -> bool { match self { - FixedBuffer::Write(_) => true, - FixedBuffer::Read(_) => false, + FixedBuffer::Mut(_) => true, + FixedBuffer::Ref(_) => false, } } pub unsafe fn get(&self) -> P { match self { - FixedBuffer::Read(buffer) => buffer.get(), - FixedBuffer::Write(buffer) => buffer.get(), + FixedBuffer::Ref(buffer) => buffer.get(), + FixedBuffer::Mut(buffer) => buffer.get(), } } pub fn as_ptr(&self) -> *const P { match self { - FixedBuffer::Read(buffer) => buffer.as_ptr(), - FixedBuffer::Write(buffer) => buffer.as_ptr(), + FixedBuffer::Ref(buffer) => buffer.as_ptr(), + FixedBuffer::Mut(buffer) => buffer.as_ptr(), } } } #[derive(Debug, Clone, Copy)] -pub struct FixedBufferR

(*const P) +pub struct FixedBufferRef

(*const P) where P: Payload; -impl

FixedBufferR

+impl

FixedBufferRef

where P: Payload, { pub fn new(buffer: &'static P) -> Self { - FixedBufferR(buffer) + FixedBufferRef(buffer) } pub fn get(self) -> P { @@ -190,21 +190,21 @@ where } } -unsafe impl

Send for FixedBufferR

where P: Payload {} +unsafe impl

Send for FixedBufferRef

where P: Payload {} -unsafe impl

Sync for FixedBufferR

where P: Payload {} +unsafe impl

Sync for FixedBufferRef

where P: Payload {} #[derive(Debug)] -pub struct FixedBufferW

(*mut P) +pub struct FixedBufferMut

(*mut P) where P: Payload; -impl

FixedBufferW

+impl

FixedBufferMut

where P: Payload, { pub fn new(buffer: &'static mut P) -> Self { - FixedBufferW(buffer) + FixedBufferMut(buffer) } /// # Safety @@ -230,17 +230,17 @@ where } } -unsafe impl

Send for FixedBufferW

where P: Payload {} +unsafe impl

Send for FixedBufferMut

where P: Payload {} -unsafe impl

Sync for FixedBufferW

where P: Payload {} +unsafe impl

Sync for FixedBufferMut

where P: Payload {} #[derive(Debug, EnumAsInner)] pub enum RegularOffsetBuffer

where P: Payload, { - Read(RegularOffsetBufferR

), - Write(RegularOffsetBufferW

), + Ref(RegularOffsetBufferRef

), + Mut(RegularOffsetBufferMut

), } #[allow(clippy::len_without_is_empty)] @@ -248,17 +248,17 @@ impl

RegularOffsetBuffer

where P: Payload, { - pub fn is_read(&self) -> bool { + pub fn is_ref(&self) -> bool { match self { - RegularOffsetBuffer::Read(_) => true, - RegularOffsetBuffer::Write(_) => false, + RegularOffsetBuffer::Ref(_) => true, + RegularOffsetBuffer::Mut(_) => false, } } - pub fn is_write(&self) -> bool { + pub fn is_mut(&self) -> bool { match self { - RegularOffsetBuffer::Write(_) => true, - RegularOffsetBuffer::Read(_) => false, + RegularOffsetBuffer::Mut(_) => true, + RegularOffsetBuffer::Ref(_) => false, } } @@ -266,40 +266,40 @@ where pub unsafe fn get(&self, index: usize) -> P { match self { - RegularOffsetBuffer::Read(buffer) => buffer.get(index), - RegularOffsetBuffer::Write(buffer) => buffer.get(index), + RegularOffsetBuffer::Ref(buffer) => buffer.get(index), + RegularOffsetBuffer::Mut(buffer) => buffer.get(index), } } pub fn as_ptr(&self, index: usize) -> *const P { match self { - RegularOffsetBuffer::Read(buffer) => buffer.as_ptr(index), - RegularOffsetBuffer::Write(buffer) => buffer.as_ptr(index), + RegularOffsetBuffer::Ref(buffer) => buffer.as_ptr(index), + RegularOffsetBuffer::Mut(buffer) => buffer.as_ptr(index), } } pub fn len(&self) -> usize { match self { - RegularOffsetBuffer::Read(buffer) => buffer.len(), - RegularOffsetBuffer::Write(buffer) => buffer.len(), + RegularOffsetBuffer::Ref(buffer) => buffer.len(), + RegularOffsetBuffer::Mut(buffer) => buffer.len(), } } } #[derive(Debug, Clone, Copy)] -pub struct RegularOffsetBufferR

(*const [P]) +pub struct RegularOffsetBufferRef

(*const [P]) where P: Payload; #[allow(clippy::len_without_is_empty)] -impl

RegularOffsetBufferR

+impl

RegularOffsetBufferRef

where P: Payload, { pub fn new(buffer: &'static [P]) -> Self { check_buffer_not_empty(buffer); - RegularOffsetBufferR(buffer) + RegularOffsetBufferRef(buffer) } pub fn get(self, index: usize) -> P { @@ -320,29 +320,29 @@ where } } - pub fn inner(&self) -> *const [P] { + pub fn inner(self) -> *const [P] { self.0 } } -unsafe impl

Send for RegularOffsetBufferR

where P: Payload {} +unsafe impl

Send for RegularOffsetBufferRef

where P: Payload {} -unsafe impl

Sync for RegularOffsetBufferR

where P: Payload {} +unsafe impl

Sync for RegularOffsetBufferRef

where P: Payload {} #[derive(Debug)] -pub struct RegularOffsetBufferW

(*mut [P]) +pub struct RegularOffsetBufferMut

(*mut [P]) where P: Payload; #[allow(clippy::len_without_is_empty)] -impl

RegularOffsetBufferW

+impl

RegularOffsetBufferMut

where P: Payload, { pub fn new(buffer: &'static mut [P]) -> Self { check_buffer_not_empty(buffer); - RegularOffsetBufferW(buffer) + RegularOffsetBufferMut(buffer) } /// # Safety @@ -386,9 +386,9 @@ where } } -unsafe impl

Send for RegularOffsetBufferW

where P: Payload {} +unsafe impl

Send for RegularOffsetBufferMut

where P: Payload {} -unsafe impl

Sync for RegularOffsetBufferW

where P: Payload {} +unsafe impl

Sync for RegularOffsetBufferMut

where P: Payload {} unsafe fn read_volatile_slice_buffer

( slice_ptr: *const [P], @@ -406,8 +406,8 @@ pub enum WordOffsetBuffer<'wo, P> where P: Payload, { - Read(WordOffsetBufferR<'wo, P>), - Write(WordOffsetBufferW<'wo, P>), + Ref(WordOffsetBufferRef<'wo, P>), + Mut(WordOffsetBufferMut<'wo, P>), } #[allow(clippy::len_without_is_empty)] @@ -415,49 +415,49 @@ impl<'wo, P> WordOffsetBuffer<'wo, P> where P: Payload, { - pub fn is_read(&self) -> bool { + pub fn is_ref(&self) -> bool { match self { - WordOffsetBuffer::Read(_) => true, - WordOffsetBuffer::Write(_) => false, + WordOffsetBuffer::Ref(_) => true, + WordOffsetBuffer::Mut(_) => false, } } - pub fn is_write(&self) -> bool { + pub fn is_mut(&self) -> bool { match self { - WordOffsetBuffer::Write(_) => true, - WordOffsetBuffer::Read(_) => false, + WordOffsetBuffer::Mut(_) => true, + WordOffsetBuffer::Ref(_) => false, } } pub unsafe fn get(&self, index: usize) -> P { match self { - WordOffsetBuffer::Read(buffer) => buffer.get(index), - WordOffsetBuffer::Write(buffer) => buffer.get(index), + WordOffsetBuffer::Ref(buffer) => buffer.get(index), + WordOffsetBuffer::Mut(buffer) => buffer.get(index), } } pub fn as_ptr(&self, index: usize) -> *const P { match self { - WordOffsetBuffer::Read(buffer) => buffer.as_ptr(index), - WordOffsetBuffer::Write(buffer) => buffer.as_ptr(index), + WordOffsetBuffer::Ref(buffer) => buffer.as_ptr(index), + WordOffsetBuffer::Mut(buffer) => buffer.as_ptr(index), } } pub fn len(&self) -> usize { match self { - WordOffsetBuffer::Read(buffer) => buffer.len(), - WordOffsetBuffer::Write(buffer) => buffer.len(), + WordOffsetBuffer::Ref(buffer) => buffer.len(), + WordOffsetBuffer::Mut(buffer) => buffer.len(), } } } #[derive(Debug, Clone, Copy)] -pub struct WordOffsetBufferR<'wo, P>(&'wo [*const P]) +pub struct WordOffsetBufferRef<'wo, P>(&'wo [*const P]) where P: Payload; #[allow(clippy::len_without_is_empty)] -impl<'wo, P> WordOffsetBufferR<'wo, P> +impl<'wo, P> WordOffsetBufferRef<'wo, P> where P: Payload, { @@ -468,7 +468,7 @@ where check_word_offset(buffer); - WordOffsetBufferR(buffer) + WordOffsetBufferRef(buffer) } pub fn get(self, index: usize) -> P { @@ -483,22 +483,22 @@ where self.0.len() } - pub fn inner(&self) -> &'wo [*const P] { + pub fn inner(self) -> &'wo [*const P] { self.0 } } -unsafe impl

Send for WordOffsetBufferR<'_, P> where P: Payload {} +unsafe impl

Send for WordOffsetBufferRef<'_, P> where P: Payload {} -unsafe impl

Sync for WordOffsetBufferR<'_, P> where P: Payload {} +unsafe impl

Sync for WordOffsetBufferRef<'_, P> where P: Payload {} #[derive(Debug)] -pub struct WordOffsetBufferW<'wo, P>(&'wo mut [*mut P]) +pub struct WordOffsetBufferMut<'wo, P>(&'wo mut [*mut P]) where P: Payload; #[allow(clippy::len_without_is_empty)] -impl<'wo, P> WordOffsetBufferW<'wo, P> +impl<'wo, P> WordOffsetBufferMut<'wo, P> where P: Payload, { @@ -508,7 +508,7 @@ where unsafe { check_word_offset::

(&*(buffer as *const _ as *const [*const P])); - WordOffsetBufferW(&mut *(buffer as *mut _ as *mut [*mut P])) + WordOffsetBufferMut(&mut *(buffer as *mut _ as *mut [*mut P])) } } @@ -543,9 +543,9 @@ where } } -unsafe impl

Send for WordOffsetBufferW<'_, P> where P: Payload {} +unsafe impl

Send for WordOffsetBufferMut<'_, P> where P: Payload {} -unsafe impl

Sync for WordOffsetBufferW<'_, P> where P: Payload {} +unsafe impl

Sync for WordOffsetBufferMut<'_, P> where P: Payload {} fn check_buffer_not_empty

(buffer: &[P]) { if buffer.is_empty() { @@ -658,17 +658,20 @@ where self.as_double_buffer().is_some() } - pub fn is_read(&self) -> bool { - match self { - MemoryBufferType::SingleBuffer(buffer) => buffer.get().is_read(), - MemoryBufferType::DoubleBuffer(buffer) => { - buffer.memories[0].get().is_read() - } - } + pub fn is_ref(&self) -> bool { + self.m0a().get().is_ref() + } + + pub fn is_mut(&self) -> bool { + self.m0a().get().is_mut() } - pub fn is_write(&self) -> bool { - !self.is_read() + pub fn is_fixed(&self) -> bool { + self.m0a().get().is_fixed() + } + + pub fn is_incremented(&self) -> bool { + self.m0a().get().is_incremented() } pub fn m0a(&self) -> &MemoryBuffer { @@ -739,8 +742,8 @@ where fn check_self(&self) { assert_eq!( - self.memories[0].get().is_read(), - self.memories[1].get().is_read() + self.memories[0].get().is_ref(), + self.memories[1].get().is_ref() ); assert_eq!( self.memories[0].get().is_fixed(), diff --git a/src/dma/transfer/config.rs b/src/dma/transfer/config.rs index 8b3d6d96..c37665e6 100644 --- a/src/dma/transfer/config.rs +++ b/src/dma/transfer/config.rs @@ -4,7 +4,7 @@ use super::super::stream::config::{ M0a, M1a, MBurst, MSize, Minc, Ndt, NotM2MConf, PBurstConf, Pa, Pinc, PincConf, Pincos, TransferDirectionConf, TransferModeConf, }; -use super::buffer::{IncrementedBuffer, MemoryBuffer, MemoryBufferType}; +use super::buffer::{IncrementedBuffer, MemoryBufferType}; use super::{Buffer, Buffers, IPayloadSize, Payload, PayloadSize}; use core::convert::TryFrom; use enum_as_inner::EnumAsInner; @@ -408,8 +408,7 @@ where } fn check_self(&self) { - assert!(self.buffers.peripheral_buffer.is_read()); - assert!(self.buffers.memory_buffer.is_read()); + assert!(self.buffers.memory_buffer.is_mut()); } } @@ -459,8 +458,7 @@ where } fn check_self(&self) { - assert!(self.buffers.peripheral_buffer.is_write()); - assert!(self.buffers.memory_buffer.is_read()); + assert!(self.buffers.peripheral_buffer.is_mut()); } } @@ -505,36 +503,12 @@ where &mut self.buffers } - pub fn source_buffer(&self) -> &Buffer<'wo, Source> { - &self.buffers.peripheral_buffer - } - - pub fn dest_buffer(&self) -> &MemoryBuffer { - &self.buffers.memory_buffer.as_single_buffer().unwrap() - } - - pub fn dest_buffer_mut(&mut self, op: F) - where - for<'a> F: FnOnce(&'a mut MemoryBuffer), - { - self.buffers_mut(move |b| { - op(&mut b.memory_buffer.as_single_buffer_mut().unwrap()) - }); - } - - pub unsafe fn dest_buffer_mut_unchecked( - &mut self, - ) -> &mut MemoryBuffer { - self.buffers.memory_buffer.as_single_buffer_mut().unwrap() - } - pub fn free(self) -> Buffers<'wo, Source, Dest> { self.buffers } fn check_self(&self) { - assert!(self.buffers.peripheral_buffer.is_read()); - assert!(self.buffers.memory_buffer.is_write()); + assert!(self.buffers.memory_buffer.is_mut()); assert!(self.buffers.memory_buffer.is_single_buffer()); } diff --git a/src/dma/transfer/mod.rs b/src/dma/transfer/mod.rs index 5b78d44a..2763e14c 100644 --- a/src/dma/transfer/mod.rs +++ b/src/dma/transfer/mod.rs @@ -3,22 +3,25 @@ pub mod buffer; pub mod config; -use self::buffer::MemoryBufferType; +use self::buffer::{MemoryBuffer, MemoryBufferType}; use super::stream::config::{ - DirectModeErrorInterrupt, FifoErrorInterrupt, HalfTransferInterrupt, MSize, - PSize, TransferCompleteInterrupt, TransferErrorInterrupt, + DirectModeErrorInterrupt, FifoErrorInterrupt, HalfTransferInterrupt, M0a, + M1a, MSize, PSize, TransferCompleteInterrupt, TransferErrorInterrupt, }; use super::stream::{ - CheckedConfig, Disabled, Enabled, Error as StreamError, Event, IsrCleared, - IsrUncleared, StreamIsr, + Disabled, Enabled, Error as StreamError, Event, IsrCleared, IsrUncleared, + StreamIsr, }; use super::{ChannelId, Stream}; use crate::{nb, private}; use core::fmt::Debug; +use core::hint; use core::marker::PhantomData; use core::mem; use enum_as_inner::EnumAsInner; +use nb::block; + pub use self::buffer::Buffer; pub use self::config::Config; @@ -69,7 +72,7 @@ where self.conf.stream_config(&mut conf); - stream.apply_config(CheckedConfig::new(conf)); + stream.apply_config(conf.check()); } pub fn config_mut(&mut self) -> &mut Config<'wo, Peripheral, Memory> { @@ -206,19 +209,71 @@ where let ndt_bytes = ndt * p_size; - let remaining_memory_items; - - if ndt_bytes % m_size == 0 { - remaining_memory_items = ndt_bytes / m_size; + let remaining_memory_items = if ndt_bytes % m_size == 0 { + ndt_bytes / m_size } else { - remaining_memory_items = ndt_bytes / m_size + 1; - } + ndt_bytes / m_size + 1 + }; Some(buffer.len() - remaining_memory_items) } } } + pub fn replace_m0a( + &mut self, + memory_buffer: MemoryBuffer, + ) -> MemoryBuffer { + unsafe { + block!(self + .state + .stream + .set_m0a(M0a(memory_buffer.get().as_ptr(Some(0)) as u32))) + } + .unwrap(); + + let mut x = None; + self.conf.buffers_mut(|b| match &mut b.memory_buffer { + MemoryBufferType::SingleBuffer(_) => panic!( + "Cannot replace memory buffer on the fly for single buffer." + ), + MemoryBufferType::DoubleBuffer(buffer) => { + buffer.memories_mut(|b| { + x = Some(mem::replace(&mut b[0], memory_buffer)) + }) + } + }); + + x.unwrap_or_else(|| unsafe { hint::unreachable_unchecked() }) + } + + pub fn replace_m1a( + &mut self, + memory_buffer: MemoryBuffer, + ) -> MemoryBuffer { + unsafe { + block!(self + .state + .stream + .set_m1a(M1a(memory_buffer.get().as_ptr(Some(0)) as u32))) + } + .unwrap(); + + let mut x = None; + self.conf.buffers_mut(|b| match &mut b.memory_buffer { + MemoryBufferType::SingleBuffer(_) => panic!( + "Cannot replace memory buffer on the fly for single buffer." + ), + MemoryBufferType::DoubleBuffer(buffer) => { + buffer.memories_mut(|b| { + x = Some(mem::replace(&mut b[1], memory_buffer)) + }) + } + }); + + x.unwrap_or_else(|| unsafe { hint::unreachable_unchecked() }) + } + pub fn stop( self, ) -> ( @@ -404,23 +459,3 @@ where pub peripheral_buffer: Buffer<'wo, Peripheral>, pub memory_buffer: MemoryBufferType, } - -#[derive(Copy, Clone, Debug, EnumAsInner)] -pub enum PayloadPort -where - Peripheral: Payload, - Memory: Payload, -{ - Peripheral(Peripheral), - Memory(Memory), -} - -#[derive(Debug, EnumAsInner)] -pub enum PointerPort -where - Peripheral: Payload, - Memory: Payload, -{ - Peripheral(*mut Peripheral), - Memory(*mut Memory), -} From d7aa593b7fdea2514937ee157220515285dbd38a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ad=C3=A4?= Date: Sat, 25 Apr 2020 18:19:59 +0200 Subject: [PATCH 097/103] Added option to halt the stream --- src/dma/mod.rs | 2 ++ src/dma/stream/mod.rs | 80 +++++++++++++++++++++++++++++++++++++++-- src/dma/transfer/mod.rs | 55 +++++++++++++++++++++++++++- src/serial/mod.rs | 3 +- 4 files changed, 136 insertions(+), 4 deletions(-) diff --git a/src/dma/mod.rs b/src/dma/mod.rs index 3b9e8c08..bbfc1201 100644 --- a/src/dma/mod.rs +++ b/src/dma/mod.rs @@ -507,6 +507,8 @@ impl Dma { } } +unsafe impl Sync for Dma {} + pub trait DmaExt: DmaPeripheral { type Other: DmaPeripheral; diff --git a/src/dma/stream/mod.rs b/src/dma/stream/mod.rs index 9a0bd7c1..2d715867 100644 --- a/src/dma/stream/mod.rs +++ b/src/dma/stream/mod.rs @@ -18,6 +18,7 @@ use core::convert::{Infallible, TryInto}; use core::marker::PhantomData; pub use self::config::{CheckedConfig, Config}; +use crate::dma::stream::config::IntoNum; /// DMA Stream pub struct Stream @@ -29,6 +30,7 @@ where /// This field *must not* be mutated using shared references rb: &'static mut ST, config_ndt: Ndt, + config_ct: CurrentTarget, _phantom_data: PhantomData<(CXX, ED, IsrState)>, } @@ -43,6 +45,7 @@ where Stream { rb, config_ndt: Ndt::default(), + config_ct: CurrentTarget::default(), _phantom_data: PhantomData, } } @@ -64,7 +67,7 @@ where minc: self.minc(), priority_level: self.priority_level(), p_size: self.p_size(), - ndt: self.ndt(), + ndt: self.config_ndt, pa: self.pa(), m0a: self.m0a(), transfer_direction: self.transfer_direction_config(), @@ -132,7 +135,7 @@ where fn double_buffer_config(&self) -> DoubleBufferConf { DoubleBufferConf { - current_target: self.current_target(), + current_target: self.config_ct, m1a: self.m1a().unwrap(), } } @@ -289,6 +292,9 @@ where } /// Returns the Current Target + /// + /// Note: This performs a *volatile* read, so the value returned may differ from + /// the configured value pub fn current_target(&self) -> CurrentTarget { self.rb.cr.read().ct().bit().into() } @@ -304,6 +310,9 @@ where } /// Returns the content of the NDT register + /// + /// Note: This performs a *volatile* read, so the value returned may differ from + /// the configured value pub fn ndt(&self) -> Ndt { self.rb.ndtr.read().ndt().bits().into() } @@ -365,6 +374,7 @@ where Stream { rb: self.rb, config_ndt: self.config_ndt, + config_ct: self.config_ct, _phantom_data: PhantomData, } } @@ -478,6 +488,8 @@ where /// Sets the Current Target fn set_current_target(&mut self, current_target: CurrentTarget) { + self.config_ct = current_target; + self.rb.cr.modify(|_, w| w.ct().bit(current_target.into())); } @@ -605,7 +617,71 @@ where IsrState: IIsrState, { /// Disables the stream + /// + /// Original config will be reloaded, especially + /// * `NDT` (Number of Data Items to Transfer) + /// * `CT` (Current Target) pub fn disable(self) -> Stream { + let mut stream = self.impl_disable(); + + // Reload original config into stream + // Values that may have changed are: + // * NDT (reloads automatically, as documented in RM 433 Rev 7 - Chapter 15.5.6) + // * CT (automatic reload is not clearly documented) + + // TODO: Find out if necessary + stream.set_current_target(stream.config_ct); + + stream + } + + /// Halts the stream for later continuation. + /// + /// Current `NDT` and `CT` values will be written into the config, + /// and the address pointers will be adjusted, too. + /// + /// This returns the halted stream, and the original config. + pub fn halt(self) -> (Stream, CheckedConfig) { + let old_conf = self.config(); + + let current_ndt = self.ndt(); + let current_ct = self.current_target(); + + let mut stream = self.impl_disable(); + + stream.set_ndt(current_ndt); + stream.set_current_target(current_ct); + + let new_pa; + let new_m0a; + let new_m1a; + + { + let pa = stream.pa().0; + let m0a = stream.m0a().0; + let m1a = stream.m1a().map(|m1a| m1a.0); + + let p_size = stream.p_size().into_num() as u32; + let m_size = stream.m_size().into_num() as u32; + + let num_transferred_items = stream.config_ndt.0 as u32; + + new_pa = pa + num_transferred_items * p_size; + new_m0a = m0a + num_transferred_items * m_size; + new_m1a = m1a.map(|m1a| m1a + num_transferred_items * m_size); + } + + stream.set_pa(Pa(new_pa)); + stream.set_m0a(M0a(new_m0a)); + + if let Some(new_m1a) = new_m1a { + stream.set_m1a(M1a(new_m1a)); + } + + (stream, old_conf) + } + + fn impl_disable(self) -> Stream { self.rb.cr.modify(|_, w| w.en().clear_bit()); while self.rb.cr.read().en().bit_is_set() {} diff --git a/src/dma/transfer/mod.rs b/src/dma/transfer/mod.rs index 2763e14c..6324b21d 100644 --- a/src/dma/transfer/mod.rs +++ b/src/dma/transfer/mod.rs @@ -18,7 +18,6 @@ use core::fmt::Debug; use core::hint; use core::marker::PhantomData; use core::mem; -use enum_as_inner::EnumAsInner; use nb::block; @@ -274,6 +273,16 @@ where x.unwrap_or_else(|| unsafe { hint::unreachable_unchecked() }) } + pub fn halt(self) -> Transfer<'wo, Peripheral, Memory, Halted> { + let (stream, _) = self.state.stream.halt(); + + Transfer { + conf: self.conf, + state: Halted { stream }, + _phantom: PhantomData, + } + } + pub fn stop( self, ) -> ( @@ -319,6 +328,42 @@ where } } +impl<'wo, Peripheral, Memory, CXX> + Transfer<'wo, Peripheral, Memory, Halted> +where + Peripheral: Payload, + Memory: Payload, + CXX: ChannelId, +{ + pub fn resume( + self, + isr: &mut StreamIsr, + ) -> Transfer<'wo, Peripheral, Memory, Ongoing> { + let stream = unsafe { self.state.stream.clear_isr(isr).enable() }; + + Transfer { + conf: self.conf, + state: Ongoing { stream }, + _phantom: PhantomData, + } + } + + pub fn stop( + self, + ) -> ( + Transfer<'wo, Peripheral, Memory, Start>, + Stream, + ) { + let transfer = Transfer { + conf: self.conf, + state: Start, + _phantom: PhantomData, + }; + + (transfer, self.state.stream) + } +} + pub trait TransferState: Send + Sync + private::Sealed {} pub struct Start; @@ -335,6 +380,14 @@ impl private::Sealed for Ongoing {} impl TransferState for Ongoing {} +pub struct Halted { + stream: Stream, +} + +impl private::Sealed for Halted {} + +impl TransferState for Halted {} + /// # Safety /// /// * `Self` must be valid for any bit representation diff --git a/src/serial/mod.rs b/src/serial/mod.rs index 7a830794..688479df 100644 --- a/src/serial/mod.rs +++ b/src/serial/mod.rs @@ -1,7 +1,8 @@ //! Serial -#[cfg(all(test, feature = "dma"))] +/* pub mod dma; +*/ use core::fmt; use core::marker::PhantomData; From f39a4a1eac8fb8040c63efaf880ae50b96984c22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ad=C3=A4?= Date: Sun, 26 Apr 2020 01:52:56 +0200 Subject: [PATCH 098/103] update --- src/dma/macros.rs | 4 +- src/dma/mod.rs | 270 +++++++++++++++++++------------------ src/dma/mux/mod.rs | 9 +- src/dma/mux/request_gen.rs | 9 +- src/dma/stream/mod.rs | 13 +- src/dma/transfer/mod.rs | 22 ++- src/dma/utils.rs | 42 ++++++ 7 files changed, 213 insertions(+), 156 deletions(-) diff --git a/src/dma/macros.rs b/src/dma/macros.rs index a5476d43..f057215f 100644 --- a/src/dma/macros.rs +++ b/src/dma/macros.rs @@ -12,7 +12,9 @@ macro_rules! type_state { $( #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] - pub struct $type_state; + pub struct $type_state { + _private: (), + } impl crate::private::Sealed for $type_state {} diff --git a/src/dma/mod.rs b/src/dma/mod.rs index bbfc1201..e356eca9 100644 --- a/src/dma/mod.rs +++ b/src/dma/mod.rs @@ -22,13 +22,15 @@ use self::mux::{ use self::stream::{Disabled, IIsrState, IsrCleared, StreamIsr, IED}; use crate::private; use crate::rcc::Ccdr; -use crate::stm32::{dma1, dmamux1, DMA1, DMA2, RCC}; +use crate::stm32::{DMA1, DMA2, RCC}; use stm32h7::stm32h743::DMAMUX1; pub use self::mux::Mux; pub use self::stream::Stream; pub use self::transfer::Transfer; +use self::utils::UniqueRef; + /// Marker Trait for DMA peripherals pub trait DmaPeripheral: private::Sealed {} impl DmaPeripheral for DMA1 {} @@ -214,29 +216,29 @@ impl Dma { Dma::reset_mux(&mut dma_mux); - let dma1_rb: &mut dma1::RegisterBlock = - unsafe { &mut *(DMA1::ptr() as *mut _) }; - let dma2_rb: &mut dma1::RegisterBlock = - unsafe { &mut *(DMA2::ptr() as *mut _) }; - let dma_mux_rb: &mut dmamux1::RegisterBlock = - unsafe { &mut *(DMAMUX1::ptr() as *mut _) }; + let dma1_rb = unsafe { &*DMA1::ptr() }; + let dma2_rb = unsafe { &*DMA2::ptr() }; + let dma_mux_rb = unsafe { &*DMAMUX1::ptr() }; let stream_isr_dma_1 = StreamIsr::new( &dma1_rb.lisr, &dma1_rb.hisr, - &mut dma1_rb.lifcr, - &mut dma1_rb.hifcr, + unsafe { UniqueRef::new_unchecked(&dma1_rb.lifcr) }, + unsafe { UniqueRef::new_unchecked(&dma1_rb.hifcr) }, ); let stream_isr_dma_2 = StreamIsr::new( &dma2_rb.lisr, &dma2_rb.hisr, - &mut dma2_rb.lifcr, - &mut dma2_rb.hifcr, + unsafe { UniqueRef::new_unchecked(&dma2_rb.lifcr) }, + unsafe { UniqueRef::new_unchecked(&dma2_rb.hifcr) }, ); - let mux_isr = MuxIsr::new(&dma_mux_rb.csr, &mut dma_mux_rb.cfr); - let req_gen_isr = - RequestGenIsr::new(&dma_mux_rb.rgsr, &mut dma_mux_rb.rgcfr); + let mux_isr = MuxIsr::new(&dma_mux_rb.csr, unsafe { + UniqueRef::new_unchecked(&dma_mux_rb.cfr) + }); + let req_gen_isr = RequestGenIsr::new(&dma_mux_rb.rgsr, unsafe { + UniqueRef::new_unchecked(&dma_mux_rb.rgcfr) + }); let mux_shared = MuxShared::new(mux_isr, req_gen_isr); let dma_shared = DmaShared { @@ -248,68 +250,68 @@ impl Dma { let channels_dma_1 = unsafe { ( Channel { - stream: Stream::after_reset( - &mut *(&mut dma1_rb.st[0] as *mut _), - ), - mux: Mux::after_reset( - &mut *(&mut dma_mux_rb.ccr[0] as *mut _), - ), + stream: Stream::after_reset(UniqueRef::new_unchecked( + &dma1_rb.st[0], + )), + mux: Mux::after_reset(UniqueRef::new_unchecked( + &dma_mux_rb.ccr[0], + )), }, Channel { - stream: Stream::after_reset( - &mut *(&mut dma1_rb.st[1] as *mut _), - ), - mux: Mux::after_reset( - &mut *(&mut dma_mux_rb.ccr[1] as *mut _), - ), + stream: Stream::after_reset(UniqueRef::new_unchecked( + &dma1_rb.st[1], + )), + mux: Mux::after_reset(UniqueRef::new_unchecked( + &dma_mux_rb.ccr[1], + )), }, Channel { - stream: Stream::after_reset( - &mut *(&mut dma1_rb.st[2] as *mut _), - ), - mux: Mux::after_reset( - &mut *(&mut dma_mux_rb.ccr[2] as *mut _), - ), + stream: Stream::after_reset(UniqueRef::new_unchecked( + &dma1_rb.st[2], + )), + mux: Mux::after_reset(UniqueRef::new_unchecked( + &dma_mux_rb.ccr[2], + )), }, Channel { - stream: Stream::after_reset( - &mut *(&mut dma1_rb.st[3] as *mut _), - ), - mux: Mux::after_reset( - &mut *(&mut dma_mux_rb.ccr[3] as *mut _), - ), + stream: Stream::after_reset(UniqueRef::new_unchecked( + &dma1_rb.st[3], + )), + mux: Mux::after_reset(UniqueRef::new_unchecked( + &dma_mux_rb.ccr[3], + )), }, Channel { - stream: Stream::after_reset( - &mut *(&mut dma1_rb.st[4] as *mut _), - ), - mux: Mux::after_reset( - &mut *(&mut dma_mux_rb.ccr[4] as *mut _), - ), + stream: Stream::after_reset(UniqueRef::new_unchecked( + &dma1_rb.st[4], + )), + mux: Mux::after_reset(UniqueRef::new_unchecked( + &dma_mux_rb.ccr[4], + )), }, Channel { - stream: Stream::after_reset( - &mut *(&mut dma1_rb.st[5] as *mut _), - ), - mux: Mux::after_reset( - &mut *(&mut dma_mux_rb.ccr[5] as *mut _), - ), + stream: Stream::after_reset(UniqueRef::new_unchecked( + &dma1_rb.st[5], + )), + mux: Mux::after_reset(UniqueRef::new_unchecked( + &dma_mux_rb.ccr[5], + )), }, Channel { - stream: Stream::after_reset( - &mut *(&mut dma1_rb.st[6] as *mut _), - ), - mux: Mux::after_reset( - &mut *(&mut dma_mux_rb.ccr[6] as *mut _), - ), + stream: Stream::after_reset(UniqueRef::new_unchecked( + &dma1_rb.st[6], + )), + mux: Mux::after_reset(UniqueRef::new_unchecked( + &dma_mux_rb.ccr[6], + )), }, Channel { - stream: Stream::after_reset( - &mut *(&mut dma1_rb.st[7] as *mut _), - ), - mux: Mux::after_reset( - &mut *(&mut dma_mux_rb.ccr[7] as *mut _), - ), + stream: Stream::after_reset(UniqueRef::new_unchecked( + &dma1_rb.st[7], + )), + mux: Mux::after_reset(UniqueRef::new_unchecked( + &dma_mux_rb.ccr[7], + )), }, ) }; @@ -317,98 +319,98 @@ impl Dma { let channels_dma_2 = unsafe { ( Channel { - stream: Stream::after_reset( - &mut *(&mut dma2_rb.st[0] as *mut _), - ), - mux: Mux::after_reset( - &mut *(&mut dma_mux_rb.ccr[8] as *mut _), - ), + stream: Stream::after_reset(UniqueRef::new_unchecked( + &dma1_rb.st[0], + )), + mux: Mux::after_reset(UniqueRef::new_unchecked( + &dma_mux_rb.ccr[8], + )), }, Channel { - stream: Stream::after_reset( - &mut *(&mut dma2_rb.st[1] as *mut _), - ), - mux: Mux::after_reset( - &mut *(&mut dma_mux_rb.ccr[9] as *mut _), - ), + stream: Stream::after_reset(UniqueRef::new_unchecked( + &dma1_rb.st[1], + )), + mux: Mux::after_reset(UniqueRef::new_unchecked( + &dma_mux_rb.ccr[9], + )), }, Channel { - stream: Stream::after_reset( - &mut *(&mut dma2_rb.st[2] as *mut _), - ), - mux: Mux::after_reset( - &mut *(&mut dma_mux_rb.ccr[10] as *mut _), - ), + stream: Stream::after_reset(UniqueRef::new_unchecked( + &dma1_rb.st[2], + )), + mux: Mux::after_reset(UniqueRef::new_unchecked( + &dma_mux_rb.ccr[10], + )), }, Channel { - stream: Stream::after_reset( - &mut *(&mut dma2_rb.st[3] as *mut _), - ), - mux: Mux::after_reset( - &mut *(&mut dma_mux_rb.ccr[11] as *mut _), - ), + stream: Stream::after_reset(UniqueRef::new_unchecked( + &dma1_rb.st[3], + )), + mux: Mux::after_reset(UniqueRef::new_unchecked( + &dma_mux_rb.ccr[11], + )), }, Channel { - stream: Stream::after_reset( - &mut *(&mut dma2_rb.st[4] as *mut _), - ), - mux: Mux::after_reset( - &mut *(&mut dma_mux_rb.ccr[12] as *mut _), - ), + stream: Stream::after_reset(UniqueRef::new_unchecked( + &dma1_rb.st[4], + )), + mux: Mux::after_reset(UniqueRef::new_unchecked( + &dma_mux_rb.ccr[12], + )), }, Channel { - stream: Stream::after_reset( - &mut *(&mut dma2_rb.st[5] as *mut _), - ), - mux: Mux::after_reset( - &mut *(&mut dma_mux_rb.ccr[13] as *mut _), - ), + stream: Stream::after_reset(UniqueRef::new_unchecked( + &dma1_rb.st[5], + )), + mux: Mux::after_reset(UniqueRef::new_unchecked( + &dma_mux_rb.ccr[13], + )), }, Channel { - stream: Stream::after_reset( - &mut *(&mut dma2_rb.st[6] as *mut _), - ), - mux: Mux::after_reset( - &mut *(&mut dma_mux_rb.ccr[14] as *mut _), - ), + stream: Stream::after_reset(UniqueRef::new_unchecked( + &dma1_rb.st[6], + )), + mux: Mux::after_reset(UniqueRef::new_unchecked( + &dma_mux_rb.ccr[14], + )), }, Channel { - stream: Stream::after_reset( - &mut *(&mut dma2_rb.st[7] as *mut _), - ), - mux: Mux::after_reset( - &mut *(&mut dma_mux_rb.ccr[15] as *mut _), - ), + stream: Stream::after_reset(UniqueRef::new_unchecked( + &dma1_rb.st[7], + )), + mux: Mux::after_reset(UniqueRef::new_unchecked( + &dma_mux_rb.ccr[15], + )), }, ) }; let request_generators = unsafe { ( - RequestGenerator::after_reset( - &mut *(&mut dma_mux_rb.rgcr[0] as *mut _), - ), - RequestGenerator::after_reset( - &mut *(&mut dma_mux_rb.rgcr[1] as *mut _), - ), - RequestGenerator::after_reset( - &mut *(&mut dma_mux_rb.rgcr[2] as *mut _), - ), - RequestGenerator::after_reset( - &mut *(&mut dma_mux_rb.rgcr[3] as *mut _), - ), - RequestGenerator::after_reset( - &mut *(&mut dma_mux_rb.rgcr[4] as *mut _), - ), - RequestGenerator::after_reset( - &mut *(&mut dma_mux_rb.rgcr[5] as *mut _), - ), - RequestGenerator::after_reset( - &mut *(&mut dma_mux_rb.rgcr[6] as *mut _), - ), - RequestGenerator::after_reset( - &mut *(&mut dma_mux_rb.rgcr[7] as *mut _), - ), + RequestGenerator::after_reset(UniqueRef::new_unchecked( + &dma_mux_rb.rgcr[0], + )), + RequestGenerator::after_reset(UniqueRef::new_unchecked( + &dma_mux_rb.rgcr[1], + )), + RequestGenerator::after_reset(UniqueRef::new_unchecked( + &dma_mux_rb.rgcr[2], + )), + RequestGenerator::after_reset(UniqueRef::new_unchecked( + &dma_mux_rb.rgcr[3], + )), + RequestGenerator::after_reset(UniqueRef::new_unchecked( + &dma_mux_rb.rgcr[4], + )), + RequestGenerator::after_reset(UniqueRef::new_unchecked( + &dma_mux_rb.rgcr[5], + )), + RequestGenerator::after_reset(UniqueRef::new_unchecked( + &dma_mux_rb.rgcr[6], + )), + RequestGenerator::after_reset(UniqueRef::new_unchecked( + &dma_mux_rb.rgcr[7], + )), ) }; diff --git a/src/dma/mux/mod.rs b/src/dma/mux/mod.rs index 1b889ea0..2351a03e 100644 --- a/src/dma/mux/mod.rs +++ b/src/dma/mux/mod.rs @@ -4,6 +4,7 @@ pub mod request_gen; use self::request_gen::RequestGenIsr; use self::request_ids::{ReqNone, RequestId as IRequestId, RequestIdSome}; +use super::utils::UniqueRef; use super::ChannelId; use crate::stm32::dmamux1::{CCR, CFR, CSR}; use core::convert::{TryFrom, TryInto}; @@ -20,7 +21,7 @@ where EgED: IEgED, { /// This field *must not* be mutated using shared references - rb: &'static mut CCR, + rb: UniqueRef<'static, CCR>, req_id: ReqId, _phantom_data: PhantomData<(CXX, SyncED, EgED)>, } @@ -32,7 +33,7 @@ where /// Creates an instance of a DMA Mux in initial state. /// /// Should only be called after RCC-reset of the DMA. - pub(super) fn after_reset(rb: &'static mut CCR) -> Self { + pub(super) fn after_reset(rb: UniqueRef<'static, CCR>) -> Self { Mux { rb, req_id: ReqNone, @@ -578,11 +579,11 @@ impl MuxShared { pub struct MuxIsr { csr: &'static CSR, /// This field *must not* be mutated using shared references - cfr: &'static mut CFR, + cfr: UniqueRef<'static, CFR>, } impl MuxIsr { - pub(super) fn new(csr: &'static CSR, cfr: &'static mut CFR) -> Self { + pub(super) fn new(csr: &'static CSR, cfr: UniqueRef<'static, CFR>) -> Self { Self { csr, cfr } } } diff --git a/src/dma/mux/request_gen.rs b/src/dma/mux/request_gen.rs index 7f8d5366..aad6d00d 100644 --- a/src/dma/mux/request_gen.rs +++ b/src/dma/mux/request_gen.rs @@ -1,5 +1,6 @@ //! DMA Request Generator +use super::super::utils::UniqueRef; use crate::private; use crate::stm32::dmamux1::{RGCFR, RGCR, RGSR}; use core::convert::TryInto; @@ -11,7 +12,7 @@ where ED: IED, { /// This field *must not* be mutated using shared references - rb: &'static mut RGCR, + rb: UniqueRef<'static, RGCR>, _phantom_data: PhantomData<(GXX, ED)>, } @@ -19,7 +20,7 @@ impl RequestGenerator where GXX: GenId, { - pub(in super::super) fn after_reset(rb: &'static mut RGCR) -> Self { + pub(in super::super) fn after_reset(rb: UniqueRef<'static, RGCR>) -> Self { RequestGenerator { rb, _phantom_data: PhantomData, @@ -225,13 +226,13 @@ pub struct TriggerOverrunError; pub struct RequestGenIsr { rgsr: &'static RGSR, /// This field *must not* be mutated using shared references - rgcfr: &'static mut RGCFR, + rgcfr: UniqueRef<'static, RGCFR>, } impl RequestGenIsr { pub(in super::super) fn new( rgsr: &'static RGSR, - rgcfr: &'static mut RGCFR, + rgcfr: UniqueRef<'static, RGCFR>, ) -> Self { RequestGenIsr { rgsr, rgcfr } } diff --git a/src/dma/stream/mod.rs b/src/dma/stream/mod.rs index 2d715867..a34be772 100644 --- a/src/dma/stream/mod.rs +++ b/src/dma/stream/mod.rs @@ -11,6 +11,7 @@ use self::config::{ TransferCompleteInterrupt, TransferDirection, TransferDirectionConf, TransferErrorInterrupt, TransferMode, TransferModeConf, }; +use super::utils::UniqueRef; use super::{ChannelId, DmaPeripheral}; use crate::nb::Error as NbError; use crate::stm32::dma1::{HIFCR, HISR, LIFCR, LISR, ST}; @@ -28,7 +29,7 @@ where IsrState: IIsrState, { /// This field *must not* be mutated using shared references - rb: &'static mut ST, + rb: UniqueRef<'static, ST>, config_ndt: Ndt, config_ct: CurrentTarget, _phantom_data: PhantomData<(CXX, ED, IsrState)>, @@ -41,7 +42,7 @@ where /// Creates an instance of a Stream in initial state. /// /// Should only be called after RCC-Reset of the DMA. - pub(super) fn after_reset(rb: &'static mut ST) -> Self { + pub(super) fn after_reset(rb: UniqueRef<'static, ST>) -> Self { Stream { rb, config_ndt: Ndt::default(), @@ -1130,9 +1131,9 @@ where lisr: &'static LISR, hisr: &'static HISR, /// This field *must not* be mutated using shared references - lifcr: &'static mut LIFCR, + lifcr: UniqueRef<'static, LIFCR>, /// This field *must not* be mutated using shared references - hifcr: &'static mut HIFCR, + hifcr: UniqueRef<'static, HIFCR>, _phantom_data: PhantomData, } @@ -1143,8 +1144,8 @@ where pub(super) fn new( lisr: &'static LISR, hisr: &'static HISR, - lifcr: &'static mut LIFCR, - hifcr: &'static mut HIFCR, + lifcr: UniqueRef<'static, LIFCR>, + hifcr: UniqueRef<'static, HIFCR>, ) -> Self { StreamIsr { lisr, diff --git a/src/dma/transfer/mod.rs b/src/dma/transfer/mod.rs index 6324b21d..ec18ee74 100644 --- a/src/dma/transfer/mod.rs +++ b/src/dma/transfer/mod.rs @@ -43,7 +43,7 @@ where pub fn new(conf: Config<'wo, Peripheral, Memory>) -> Self { Self { conf, - state: Start, + state: Start { _private: () }, _phantom: PhantomData, } } @@ -293,7 +293,7 @@ where let transfer = Transfer { conf: self.conf, - state: Start, + state: Start { _private: () }, _phantom: PhantomData, }; @@ -356,7 +356,7 @@ where ) { let transfer = Transfer { conf: self.conf, - state: Start, + state: Start { _private: () }, _phantom: PhantomData, }; @@ -366,7 +366,9 @@ where pub trait TransferState: Send + Sync + private::Sealed {} -pub struct Start; +pub struct Start { + _private: (), +} impl private::Sealed for Start {} @@ -461,9 +463,15 @@ pub trait IPayloadSize { const SIZE: PayloadSize; } -pub struct Byte; -pub struct HalfWord; -pub struct Word; +pub struct Byte { + _private: (), +} +pub struct HalfWord { + _private: (), +} +pub struct Word { + _private: (), +} impl IPayloadSize for Byte { const SIZE: PayloadSize = PayloadSize::Byte; diff --git a/src/dma/utils.rs b/src/dma/utils.rs index de7ec6ea..aeebaff0 100644 --- a/src/dma/utils.rs +++ b/src/dma/utils.rs @@ -1,5 +1,47 @@ use core::fmt; +use core::ops::Deref; pub trait DefaultTraits: Copy + Clone + PartialEq + Eq + fmt::Debug {} impl DefaultTraits for T {} + +/// Guarantees that the stored reference is unique (i.e. not shared). +/// +/// # Example +/// +/// ```rust +/// # use core::cell::Cell; +/// +/// pub struct ShallBeSync<'a> { +/// cell: UniqueRef<'a, Cell>, +/// } +/// +/// impl<'a> ShallBeSync<'a> { +/// // Some sync-compliant methods +/// } +/// +/// // This wouldn't be safe if multiple references to `cell` would coexist +/// unsafe impl Sync for ShallBeSync<'_> {} +/// ``` +pub struct UniqueRef<'a, T> { + inner: &'a T, +} + +impl<'a, T> UniqueRef<'a, T> { + #[allow(dead_code)] + pub fn new(x: &'a mut T) -> Self { + Self { inner: x } + } + + pub unsafe fn new_unchecked(x: &'a T) -> Self { + Self { inner: x } + } +} + +impl Deref for UniqueRef<'_, T> { + type Target = T; + + fn deref(&self) -> &T { + &self.inner + } +} From 2df1b7a7e9e43b385a6f24b5bc2e1f6e8f1f270e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ad=C3=A4?= Date: Sun, 26 Apr 2020 01:59:38 +0200 Subject: [PATCH 099/103] minor change --- src/dma/mod.rs | 4 +++- src/dma/mux/request_gen.rs | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/dma/mod.rs b/src/dma/mod.rs index e356eca9..2b37dbd2 100644 --- a/src/dma/mod.rs +++ b/src/dma/mod.rs @@ -46,7 +46,9 @@ pub trait ChannelId: Send + private::Sealed { macro_rules! channels { ($($channel:ident => [$stream:tt, $mux:tt, $dma:ident]),*) => { $( - pub struct $channel; + pub struct $channel { + _private: (), + } impl crate::private::Sealed for $channel {} diff --git a/src/dma/mux/request_gen.rs b/src/dma/mux/request_gen.rs index aad6d00d..3bd695c0 100644 --- a/src/dma/mux/request_gen.rs +++ b/src/dma/mux/request_gen.rs @@ -169,7 +169,9 @@ pub trait GenId: Send + private::Sealed { macro_rules! gen_ids { ($($name:ident => $id:tt),*) => { $( - pub struct $name; + pub struct $name { + _private: (), + } impl private::Sealed for $name {} impl GenId for $name { From c2278b7a79b5a2e9e2b98059624a4b405398bab0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ad=C3=A4?= Date: Sun, 26 Apr 2020 18:02:41 +0200 Subject: [PATCH 100/103] Moved isr implementations into isr structs --- src/dma/mod.rs | 45 ++-- src/dma/mux/mod.rs | 122 ++++++++-- src/dma/mux/request_gen.rs | 113 ++++++--- src/dma/stream/mod.rs | 482 +++++++++++++++++++++---------------- src/dma/utils.rs | 30 ++- 5 files changed, 490 insertions(+), 302 deletions(-) diff --git a/src/dma/mod.rs b/src/dma/mod.rs index 2b37dbd2..459280e1 100644 --- a/src/dma/mod.rs +++ b/src/dma/mod.rs @@ -17,9 +17,10 @@ use self::mux::request_gen::{ use self::mux::request_ids::{ReqNone, RequestId as IRequestId}; use self::mux::MuxIsr; use self::mux::{ - EgDisabled, IEgED, ISyncED, MuxShared, RequestGenerator, SyncDisabled, + EgDisabled, IEgED, ISyncED, MuxId, MuxShared, RequestGenerator, + SyncDisabled, }; -use self::stream::{Disabled, IIsrState, IsrCleared, StreamIsr, IED}; +use self::stream::{Disabled, IIsrState, IsrCleared, StreamId, StreamIsr, IED}; use crate::private; use crate::rcc::Ccdr; use crate::stm32::{DMA1, DMA2, RCC}; @@ -37,8 +38,8 @@ impl DmaPeripheral for DMA1 {} impl DmaPeripheral for DMA2 {} pub trait ChannelId: Send + private::Sealed { - const STREAM_ID: usize; - const MUX_ID: usize; + const STREAM_ID: StreamId; + const MUX_ID: MuxId; type DMA: DmaPeripheral; } @@ -53,8 +54,8 @@ macro_rules! channels { impl crate::private::Sealed for $channel {} impl ChannelId for $channel { - const STREAM_ID: usize = $stream; - const MUX_ID: usize = $mux; + const STREAM_ID: StreamId = StreamId::$stream; + const MUX_ID: MuxId = MuxId::$mux; type DMA = $dma; } @@ -63,22 +64,22 @@ macro_rules! channels { } channels! { - C0 => [0, 0, DMA1], - C1 => [1, 1, DMA1], - C2 => [2, 2, DMA1], - C3 => [3, 3, DMA1], - C4 => [4, 4, DMA1], - C5 => [5, 5, DMA1], - C6 => [6, 6, DMA1], - C7 => [7, 7, DMA1], - C8 => [0, 8, DMA2], - C9 => [1, 9, DMA2], - C10 => [2, 10, DMA2], - C11 => [3, 11, DMA2], - C12 => [4, 12, DMA2], - C13 => [5, 13, DMA2], - C14 => [6, 14, DMA2], - C15 => [7, 15, DMA2] + C0 => [S_0, M_0, DMA1], + C1 => [S_1, M_1, DMA1], + C2 => [S_2, M_2, DMA1], + C3 => [S_3, M_3, DMA1], + C4 => [S_4, M_4, DMA1], + C5 => [S_5, M_5, DMA1], + C6 => [S_6, M_6, DMA1], + C7 => [S_7, M_7, DMA1], + C8 => [S_0, M_8, DMA2], + C9 => [S_1, M_9, DMA2], + C10 => [S_2, M_10, DMA2], + C11 => [S_3, M_11, DMA2], + C12 => [S_4, M_12, DMA2], + C13 => [S_5, M_13, DMA2], + C14 => [S_6, M_14, DMA2], + C15 => [S_7, M_15, DMA2] } /// DMA Channel diff --git a/src/dma/mux/mod.rs b/src/dma/mux/mod.rs index 2351a03e..be8d3d20 100644 --- a/src/dma/mux/mod.rs +++ b/src/dma/mux/mod.rs @@ -12,6 +12,49 @@ use core::marker::PhantomData; pub use self::request_gen::RequestGenerator; +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] +pub enum MuxId { + M_0, + M_1, + M_2, + M_3, + M_4, + M_5, + M_6, + M_7, + M_8, + M_9, + M_10, + M_11, + M_12, + M_13, + M_14, + M_15, +} + +impl From for usize { + fn from(x: MuxId) -> usize { + match x { + MuxId::M_0 => 0, + MuxId::M_1 => 1, + MuxId::M_2 => 2, + MuxId::M_3 => 3, + MuxId::M_4 => 4, + MuxId::M_5 => 5, + MuxId::M_6 => 6, + MuxId::M_7 => 7, + MuxId::M_8 => 8, + MuxId::M_9 => 9, + MuxId::M_10 => 10, + MuxId::M_11 => 11, + MuxId::M_12 => 12, + MuxId::M_13 => 13, + MuxId::M_14 => 14, + MuxId::M_15 => 15, + } + } +} + /// DMA Mux pub struct Mux where @@ -21,7 +64,7 @@ where EgED: IEgED, { /// This field *must not* be mutated using shared references - rb: UniqueRef<'static, CCR>, + rb: &'static CCR, req_id: ReqId, _phantom_data: PhantomData<(CXX, SyncED, EgED)>, } @@ -35,7 +78,7 @@ where /// Should only be called after RCC-reset of the DMA. pub(super) fn after_reset(rb: UniqueRef<'static, CCR>) -> Self { Mux { - rb, + rb: rb.into_inner(), req_id: ReqNone, _phantom_data: PhantomData, } @@ -50,7 +93,7 @@ where EgED: IEgED, { /// Returns the id of the DMA Mux - pub fn id(&self) -> usize { + pub fn id(&self) -> MuxId { CXX::MUX_ID } @@ -283,30 +326,12 @@ where /// Returns the Sync Overrun flag pub fn is_sync_overrun(&self, mux_isr: &MuxIsr) -> bool { - mux_isr.csr.read().sof0().bit_is_set() + mux_isr.is_sync_overrun(self.id()) } /// Clears the ISR pub fn clear_isr(&self, mux_isr: &mut MuxIsr) { - match self.id() { - 0 => mux_isr.cfr.write(|w| w.csof0().set_bit()), - 1 => mux_isr.cfr.write(|w| w.csof1().set_bit()), - 2 => mux_isr.cfr.write(|w| w.csof2().set_bit()), - 3 => mux_isr.cfr.write(|w| w.csof3().set_bit()), - 4 => mux_isr.cfr.write(|w| w.csof4().set_bit()), - 5 => mux_isr.cfr.write(|w| w.csof5().set_bit()), - 6 => mux_isr.cfr.write(|w| w.csof6().set_bit()), - 7 => mux_isr.cfr.write(|w| w.csof7().set_bit()), - 8 => mux_isr.cfr.write(|w| w.csof8().set_bit()), - 9 => mux_isr.cfr.write(|w| w.csof9().set_bit()), - 10 => mux_isr.cfr.write(|w| w.csof10().set_bit()), - 11 => mux_isr.cfr.write(|w| w.csof11().set_bit()), - 12 => mux_isr.cfr.write(|w| w.csof12().set_bit()), - 13 => mux_isr.cfr.write(|w| w.csof13().set_bit()), - 14 => mux_isr.cfr.write(|w| w.csof14().set_bit()), - 15 => mux_isr.cfr.write(|w| w.csof15().set_bit()), - _ => unreachable!(), - } + mux_isr.clear_isr(self.id()); } } @@ -579,12 +604,59 @@ impl MuxShared { pub struct MuxIsr { csr: &'static CSR, /// This field *must not* be mutated using shared references - cfr: UniqueRef<'static, CFR>, + cfr: &'static CFR, } impl MuxIsr { pub(super) fn new(csr: &'static CSR, cfr: UniqueRef<'static, CFR>) -> Self { - Self { csr, cfr } + Self { + csr, + cfr: cfr.into_inner(), + } + } + + /// Returns the Sync Overrun flag + pub fn is_sync_overrun(&self, id: MuxId) -> bool { + match id { + MuxId::M_0 => self.csr.read().sof0().bit_is_set(), + MuxId::M_1 => self.csr.read().sof1().bit_is_set(), + MuxId::M_2 => self.csr.read().sof2().bit_is_set(), + MuxId::M_3 => self.csr.read().sof3().bit_is_set(), + MuxId::M_4 => self.csr.read().sof4().bit_is_set(), + MuxId::M_5 => self.csr.read().sof5().bit_is_set(), + MuxId::M_6 => self.csr.read().sof6().bit_is_set(), + MuxId::M_7 => self.csr.read().sof7().bit_is_set(), + MuxId::M_8 => self.csr.read().sof8().bit_is_set(), + MuxId::M_9 => self.csr.read().sof9().bit_is_set(), + MuxId::M_10 => self.csr.read().sof10().bit_is_set(), + MuxId::M_11 => self.csr.read().sof11().bit_is_set(), + MuxId::M_12 => self.csr.read().sof12().bit_is_set(), + MuxId::M_13 => self.csr.read().sof13().bit_is_set(), + MuxId::M_14 => self.csr.read().sof14().bit_is_set(), + MuxId::M_15 => self.csr.read().sof15().bit_is_set(), + } + } + + /// Clears the ISR + pub fn clear_isr(&mut self, id: MuxId) { + match id { + MuxId::M_0 => self.cfr.write(|w| w.csof0().set_bit()), + MuxId::M_1 => self.cfr.write(|w| w.csof1().set_bit()), + MuxId::M_2 => self.cfr.write(|w| w.csof2().set_bit()), + MuxId::M_3 => self.cfr.write(|w| w.csof3().set_bit()), + MuxId::M_4 => self.cfr.write(|w| w.csof4().set_bit()), + MuxId::M_5 => self.cfr.write(|w| w.csof5().set_bit()), + MuxId::M_6 => self.cfr.write(|w| w.csof6().set_bit()), + MuxId::M_7 => self.cfr.write(|w| w.csof7().set_bit()), + MuxId::M_8 => self.cfr.write(|w| w.csof8().set_bit()), + MuxId::M_9 => self.cfr.write(|w| w.csof9().set_bit()), + MuxId::M_10 => self.cfr.write(|w| w.csof10().set_bit()), + MuxId::M_11 => self.cfr.write(|w| w.csof11().set_bit()), + MuxId::M_12 => self.cfr.write(|w| w.csof12().set_bit()), + MuxId::M_13 => self.cfr.write(|w| w.csof13().set_bit()), + MuxId::M_14 => self.cfr.write(|w| w.csof14().set_bit()), + MuxId::M_15 => self.cfr.write(|w| w.csof15().set_bit()), + } } } diff --git a/src/dma/mux/request_gen.rs b/src/dma/mux/request_gen.rs index 3bd695c0..694146b2 100644 --- a/src/dma/mux/request_gen.rs +++ b/src/dma/mux/request_gen.rs @@ -6,13 +6,40 @@ use crate::stm32::dmamux1::{RGCFR, RGCR, RGSR}; use core::convert::TryInto; use core::marker::PhantomData; +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] +pub enum RequestGenId { + G_0, + G_1, + G_2, + G_3, + G_4, + G_5, + G_6, + G_7, +} + +impl From for usize { + fn from(x: RequestGenId) -> usize { + match x { + RequestGenId::G_0 => 0, + RequestGenId::G_1 => 1, + RequestGenId::G_2 => 2, + RequestGenId::G_3 => 3, + RequestGenId::G_4 => 4, + RequestGenId::G_5 => 5, + RequestGenId::G_6 => 6, + RequestGenId::G_7 => 7, + } + } +} + pub struct RequestGenerator where GXX: GenId, ED: IED, { /// This field *must not* be mutated using shared references - rb: UniqueRef<'static, RGCR>, + rb: &'static RGCR, _phantom_data: PhantomData<(GXX, ED)>, } @@ -22,7 +49,7 @@ where { pub(in super::super) fn after_reset(rb: UniqueRef<'static, RGCR>) -> Self { RequestGenerator { - rb, + rb: rb.into_inner(), _phantom_data: PhantomData, } } @@ -33,7 +60,7 @@ where GXX: GenId, ED: IED, { - pub fn id(&self) -> usize { + pub fn id(&self) -> RequestGenId { GXX::ID } @@ -122,32 +149,13 @@ where Ok(()) } } + pub fn trigger_overrun_flag(&self, isr: &RequestGenIsr) -> bool { - match self.id() { - 0 => isr.rgsr.read().of0().bit_is_set(), - 1 => isr.rgsr.read().of1().bit_is_set(), - 2 => isr.rgsr.read().of2().bit_is_set(), - 3 => isr.rgsr.read().of3().bit_is_set(), - 4 => isr.rgsr.read().of4().bit_is_set(), - 5 => isr.rgsr.read().of5().bit_is_set(), - 6 => isr.rgsr.read().of6().bit_is_set(), - 7 => isr.rgsr.read().of7().bit_is_set(), - _ => unreachable!(), - } + isr.trigger_overrun_flag(self.id()) } pub fn clear_isr(&self, isr: &mut RequestGenIsr) { - match self.id() { - 0 => isr.rgcfr.write(|w| w.cof0().set_bit()), - 1 => isr.rgcfr.write(|w| w.cof1().set_bit()), - 2 => isr.rgcfr.write(|w| w.cof2().set_bit()), - 3 => isr.rgcfr.write(|w| w.cof3().set_bit()), - 4 => isr.rgcfr.write(|w| w.cof4().set_bit()), - 5 => isr.rgcfr.write(|w| w.cof5().set_bit()), - 6 => isr.rgcfr.write(|w| w.cof6().set_bit()), - 7 => isr.rgcfr.write(|w| w.cof7().set_bit()), - _ => unreachable!(), - } + isr.clear_isr(self.id()); } } @@ -163,7 +171,7 @@ type_state! { } pub trait GenId: Send + private::Sealed { - const ID: usize; + const ID: RequestGenId; } macro_rules! gen_ids { @@ -175,21 +183,21 @@ macro_rules! gen_ids { impl private::Sealed for $name {} impl GenId for $name { - const ID:usize = $id; + const ID: RequestGenId = RequestGenId::$id; } )* }; } gen_ids! { - G0 => 0, - G1 => 1, - G2 => 2, - G3 => 3, - G4 => 4, - G5 => 5, - G6 => 6, - G7 => 7 + G0 => G_0, + G1 => G_1, + G2 => G_2, + G3 => G_3, + G4 => G_4, + G5 => G_5, + G6 => G_6, + G7 => G_7 } int_enum! { @@ -222,13 +230,13 @@ int_struct! { GNbReq, u8, 5, "Number of DMA Requests to be generated (minus 1)", 0 } -#[derive(Debug, Clone, Copy)] +#[derive(Copy, Clone, Debug)] pub struct TriggerOverrunError; pub struct RequestGenIsr { rgsr: &'static RGSR, /// This field *must not* be mutated using shared references - rgcfr: UniqueRef<'static, RGCFR>, + rgcfr: &'static RGCFR, } impl RequestGenIsr { @@ -236,7 +244,36 @@ impl RequestGenIsr { rgsr: &'static RGSR, rgcfr: UniqueRef<'static, RGCFR>, ) -> Self { - RequestGenIsr { rgsr, rgcfr } + RequestGenIsr { + rgsr, + rgcfr: rgcfr.into_inner(), + } + } + + pub fn trigger_overrun_flag(&self, id: RequestGenId) -> bool { + match id { + RequestGenId::G_0 => self.rgsr.read().of0().bit_is_set(), + RequestGenId::G_1 => self.rgsr.read().of1().bit_is_set(), + RequestGenId::G_2 => self.rgsr.read().of2().bit_is_set(), + RequestGenId::G_3 => self.rgsr.read().of3().bit_is_set(), + RequestGenId::G_4 => self.rgsr.read().of4().bit_is_set(), + RequestGenId::G_5 => self.rgsr.read().of5().bit_is_set(), + RequestGenId::G_6 => self.rgsr.read().of6().bit_is_set(), + RequestGenId::G_7 => self.rgsr.read().of7().bit_is_set(), + } + } + + pub fn clear_isr(&mut self, id: RequestGenId) { + match id { + RequestGenId::G_0 => self.rgcfr.write(|w| w.cof0().set_bit()), + RequestGenId::G_1 => self.rgcfr.write(|w| w.cof1().set_bit()), + RequestGenId::G_2 => self.rgcfr.write(|w| w.cof2().set_bit()), + RequestGenId::G_3 => self.rgcfr.write(|w| w.cof3().set_bit()), + RequestGenId::G_4 => self.rgcfr.write(|w| w.cof4().set_bit()), + RequestGenId::G_5 => self.rgcfr.write(|w| w.cof5().set_bit()), + RequestGenId::G_6 => self.rgcfr.write(|w| w.cof6().set_bit()), + RequestGenId::G_7 => self.rgcfr.write(|w| w.cof7().set_bit()), + } } } diff --git a/src/dma/stream/mod.rs b/src/dma/stream/mod.rs index a34be772..4eb1cd45 100644 --- a/src/dma/stream/mod.rs +++ b/src/dma/stream/mod.rs @@ -21,6 +21,33 @@ use core::marker::PhantomData; pub use self::config::{CheckedConfig, Config}; use crate::dma::stream::config::IntoNum; +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] +pub enum StreamId { + S_0, + S_1, + S_2, + S_3, + S_4, + S_5, + S_6, + S_7, +} + +impl From for usize { + fn from(x: StreamId) -> usize { + match x { + StreamId::S_0 => 0, + StreamId::S_1 => 1, + StreamId::S_2 => 2, + StreamId::S_3 => 3, + StreamId::S_4 => 4, + StreamId::S_5 => 5, + StreamId::S_6 => 6, + StreamId::S_7 => 7, + } + } +} + /// DMA Stream pub struct Stream where @@ -29,7 +56,7 @@ where IsrState: IIsrState, { /// This field *must not* be mutated using shared references - rb: UniqueRef<'static, ST>, + rb: &'static ST, config_ndt: Ndt, config_ct: CurrentTarget, _phantom_data: PhantomData<(CXX, ED, IsrState)>, @@ -44,7 +71,7 @@ where /// Should only be called after RCC-Reset of the DMA. pub(super) fn after_reset(rb: UniqueRef<'static, ST>) -> Self { Stream { - rb, + rb: rb.into_inner(), config_ndt: Ndt::default(), config_ct: CurrentTarget::default(), _phantom_data: PhantomData, @@ -171,7 +198,7 @@ where } /// Returns the id of the Stream - pub fn id(&self) -> usize { + pub fn id(&self) -> StreamId { CXX::STREAM_ID } @@ -757,241 +784,56 @@ where /// Returns the Transfer Complete flag pub fn transfer_complete_flag(&self, isr: &StreamIsr) -> bool { - match self.id() { - 0 => isr.lisr.read().tcif0().bit_is_set(), - 1 => isr.lisr.read().tcif1().bit_is_set(), - 2 => isr.lisr.read().tcif2().bit_is_set(), - 3 => isr.lisr.read().tcif3().bit_is_set(), - 4 => isr.hisr.read().tcif4().bit_is_set(), - 5 => isr.hisr.read().tcif5().bit_is_set(), - 6 => isr.hisr.read().tcif6().bit_is_set(), - 7 => isr.hisr.read().tcif7().bit_is_set(), - _ => unreachable!(), - } + isr.transfer_complete_flag(self.id()) } /// Returns the Half Transfer flag pub fn half_transfer_flag(&self, isr: &StreamIsr) -> bool { - match self.id() { - 0 => isr.lisr.read().htif0().bit_is_set(), - 1 => isr.lisr.read().htif1().bit_is_set(), - 2 => isr.lisr.read().htif2().bit_is_set(), - 3 => isr.lisr.read().htif3().bit_is_set(), - 4 => isr.hisr.read().htif4().bit_is_set(), - 5 => isr.hisr.read().htif5().bit_is_set(), - 6 => isr.hisr.read().htif6().bit_is_set(), - 7 => isr.hisr.read().htif7().bit_is_set(), - _ => unreachable!(), - } + isr.half_transfer_flag(self.id()) } /// Returns the Transfer Error flag pub fn transfer_error_flag(&self, isr: &StreamIsr) -> bool { - match self.id() { - 0 => isr.lisr.read().teif0().bit_is_set(), - 1 => isr.lisr.read().teif1().bit_is_set(), - 2 => isr.lisr.read().teif2().bit_is_set(), - 3 => isr.lisr.read().teif3().bit_is_set(), - 4 => isr.hisr.read().teif4().bit_is_set(), - 5 => isr.hisr.read().teif5().bit_is_set(), - 6 => isr.hisr.read().teif6().bit_is_set(), - 7 => isr.hisr.read().teif7().bit_is_set(), - _ => unreachable!(), - } + isr.transfer_error_flag(self.id()) } /// Returns the Direct Mode Error flag pub fn direct_mode_error_flag(&self, isr: &StreamIsr) -> bool { - match self.id() { - 0 => isr.lisr.read().dmeif0().bit_is_set(), - 1 => isr.lisr.read().dmeif1().bit_is_set(), - 2 => isr.lisr.read().dmeif2().bit_is_set(), - 3 => isr.lisr.read().dmeif3().bit_is_set(), - 4 => isr.hisr.read().dmeif4().bit_is_set(), - 5 => isr.hisr.read().dmeif5().bit_is_set(), - 6 => isr.hisr.read().dmeif6().bit_is_set(), - 7 => isr.hisr.read().dmeif7().bit_is_set(), - _ => unreachable!(), - } + isr.direct_mode_error_flag(self.id()) } /// Returns the Fifo Error flag pub fn fifo_error_flag(&self, isr: &StreamIsr) -> bool { - match self.id() { - 0 => isr.lisr.read().feif0().bit_is_set(), - 1 => isr.lisr.read().feif1().bit_is_set(), - 2 => isr.lisr.read().feif2().bit_is_set(), - 3 => isr.lisr.read().feif3().bit_is_set(), - 4 => isr.hisr.read().feif4().bit_is_set(), - 5 => isr.hisr.read().feif5().bit_is_set(), - 6 => isr.hisr.read().feif6().bit_is_set(), - 7 => isr.hisr.read().feif7().bit_is_set(), - _ => unreachable!(), - } - } - - /// Performs the ISR clear - fn clear_isr_impl(&self, isr: &mut StreamIsr) { - self.clear_transfer_complete(isr); - self.clear_half_transfer(isr); - self.clear_transfer_error(isr); - self.clear_direct_mode_error(isr); - self.clear_fifo_error(isr); + isr.fifo_error_flag(self.id()) } /// Clears the Transfer Complete flag pub fn clear_transfer_complete(&self, isr: &mut StreamIsr) { - match self.id() { - 0 => { - isr.lifcr.write(|w| w.ctcif0().set_bit()); - } - 1 => { - isr.lifcr.write(|w| w.ctcif1().set_bit()); - } - 2 => { - isr.lifcr.write(|w| w.ctcif2().set_bit()); - } - 3 => { - isr.lifcr.write(|w| w.ctcif3().set_bit()); - } - 4 => { - isr.hifcr.write(|w| w.ctcif4().set_bit()); - } - 5 => { - isr.hifcr.write(|w| w.ctcif5().set_bit()); - } - 6 => { - isr.hifcr.write(|w| w.ctcif6().set_bit()); - } - 7 => { - isr.hifcr.write(|w| w.ctcif7().set_bit()); - } - _ => unreachable!(), - } + isr.clear_transfer_complete(self.id()); } /// Clears the Half Transfer flag pub fn clear_half_transfer(&self, isr: &mut StreamIsr) { - match self.id() { - 0 => { - isr.lifcr.write(|w| w.chtif0().set_bit()); - } - 1 => { - isr.lifcr.write(|w| w.chtif1().set_bit()); - } - 2 => { - isr.lifcr.write(|w| w.chtif2().set_bit()); - } - 3 => { - isr.lifcr.write(|w| w.chtif3().set_bit()); - } - 4 => { - isr.hifcr.write(|w| w.chtif4().set_bit()); - } - 5 => { - isr.hifcr.write(|w| w.chtif5().set_bit()); - } - 6 => { - isr.hifcr.write(|w| w.chtif6().set_bit()); - } - 7 => { - isr.hifcr.write(|w| w.chtif7().set_bit()); - } - _ => unreachable!(), - } + isr.clear_half_transfer(self.id()); } /// Clears the Transfer Error flag pub fn clear_transfer_error(&self, isr: &mut StreamIsr) { - match self.id() { - 0 => { - isr.lifcr.write(|w| w.cteif0().set_bit()); - } - 1 => { - isr.lifcr.write(|w| w.cteif1().set_bit()); - } - 2 => { - isr.lifcr.write(|w| w.cteif2().set_bit()); - } - 3 => { - isr.lifcr.write(|w| w.cteif3().set_bit()); - } - 4 => { - isr.hifcr.write(|w| w.cteif4().set_bit()); - } - 5 => { - isr.hifcr.write(|w| w.cteif5().set_bit()); - } - 6 => { - isr.hifcr.write(|w| w.cteif6().set_bit()); - } - 7 => { - isr.hifcr.write(|w| w.cteif7().set_bit()); - } - _ => unreachable!(), - } + isr.clear_transfer_error(self.id()); } /// Clears the Direct Mode Error flag pub fn clear_direct_mode_error(&self, isr: &mut StreamIsr) { - match self.id() { - 0 => { - isr.lifcr.write(|w| w.cdmeif0().set_bit()); - } - 1 => { - isr.lifcr.write(|w| w.cdmeif1().set_bit()); - } - 2 => { - isr.lifcr.write(|w| w.cdmeif2().set_bit()); - } - 3 => { - isr.lifcr.write(|w| w.cdmeif3().set_bit()); - } - 4 => { - isr.hifcr.write(|w| w.cdmeif4().set_bit()); - } - 5 => { - isr.hifcr.write(|w| w.cdmeif5().set_bit()); - } - 6 => { - isr.hifcr.write(|w| w.cdmeif6().set_bit()); - } - 7 => { - isr.hifcr.write(|w| w.cdmeif7().set_bit()); - } - _ => unreachable!(), - } + isr.clear_direct_mode_error(self.id()); } /// Clears the Fifo Error flag pub fn clear_fifo_error(&self, isr: &mut StreamIsr) { - match self.id() { - 0 => { - isr.lifcr.write(|w| w.cfeif0().set_bit()); - } - 1 => { - isr.lifcr.write(|w| w.cfeif1().set_bit()); - } - 2 => { - isr.lifcr.write(|w| w.cfeif2().set_bit()); - } - 3 => { - isr.lifcr.write(|w| w.cfeif3().set_bit()); - } - 4 => { - isr.hifcr.write(|w| w.cfeif4().set_bit()); - } - 5 => { - isr.hifcr.write(|w| w.cfeif5().set_bit()); - } - 6 => { - isr.hifcr.write(|w| w.cfeif6().set_bit()); - } - 7 => { - isr.hifcr.write(|w| w.cfeif7().set_bit()); - } - _ => unreachable!(), - } + isr.clear_fifo_error(self.id()); + } + + fn clear_isr_impl(&self, isr: &mut StreamIsr) { + isr.clear_isr(self.id()); } } @@ -1131,9 +973,9 @@ where lisr: &'static LISR, hisr: &'static HISR, /// This field *must not* be mutated using shared references - lifcr: UniqueRef<'static, LIFCR>, + lifcr: &'static LIFCR, /// This field *must not* be mutated using shared references - hifcr: UniqueRef<'static, HIFCR>, + hifcr: &'static HIFCR, _phantom_data: PhantomData, } @@ -1150,11 +992,239 @@ where StreamIsr { lisr, hisr, - lifcr, - hifcr, + lifcr: lifcr.into_inner(), + hifcr: hifcr.into_inner(), _phantom_data: PhantomData, } } + + /// Returns the Transfer Complete flag + pub fn transfer_complete_flag(&self, id: StreamId) -> bool { + match id { + StreamId::S_0 => self.lisr.read().tcif0().bit_is_set(), + StreamId::S_1 => self.lisr.read().tcif1().bit_is_set(), + StreamId::S_2 => self.lisr.read().tcif2().bit_is_set(), + StreamId::S_3 => self.lisr.read().tcif3().bit_is_set(), + StreamId::S_4 => self.hisr.read().tcif4().bit_is_set(), + StreamId::S_5 => self.hisr.read().tcif5().bit_is_set(), + StreamId::S_6 => self.hisr.read().tcif6().bit_is_set(), + StreamId::S_7 => self.hisr.read().tcif7().bit_is_set(), + } + } + + /// Returns the Half Transfer flag + pub fn half_transfer_flag(&self, id: StreamId) -> bool { + match id { + StreamId::S_0 => self.lisr.read().htif0().bit_is_set(), + StreamId::S_1 => self.lisr.read().htif1().bit_is_set(), + StreamId::S_2 => self.lisr.read().htif2().bit_is_set(), + StreamId::S_3 => self.lisr.read().htif3().bit_is_set(), + StreamId::S_4 => self.hisr.read().htif4().bit_is_set(), + StreamId::S_5 => self.hisr.read().htif5().bit_is_set(), + StreamId::S_6 => self.hisr.read().htif6().bit_is_set(), + StreamId::S_7 => self.hisr.read().htif7().bit_is_set(), + } + } + + /// Returns the Transfer Error flag + pub fn transfer_error_flag(&self, id: StreamId) -> bool { + match id { + StreamId::S_0 => self.lisr.read().teif0().bit_is_set(), + StreamId::S_1 => self.lisr.read().teif1().bit_is_set(), + StreamId::S_2 => self.lisr.read().teif2().bit_is_set(), + StreamId::S_3 => self.lisr.read().teif3().bit_is_set(), + StreamId::S_4 => self.hisr.read().teif4().bit_is_set(), + StreamId::S_5 => self.hisr.read().teif5().bit_is_set(), + StreamId::S_6 => self.hisr.read().teif6().bit_is_set(), + StreamId::S_7 => self.hisr.read().teif7().bit_is_set(), + } + } + + /// Returns the Direct Mode Error flag + pub fn direct_mode_error_flag(&self, id: StreamId) -> bool { + match id { + StreamId::S_0 => self.lisr.read().dmeif0().bit_is_set(), + StreamId::S_1 => self.lisr.read().dmeif1().bit_is_set(), + StreamId::S_2 => self.lisr.read().dmeif2().bit_is_set(), + StreamId::S_3 => self.lisr.read().dmeif3().bit_is_set(), + StreamId::S_4 => self.hisr.read().dmeif4().bit_is_set(), + StreamId::S_5 => self.hisr.read().dmeif5().bit_is_set(), + StreamId::S_6 => self.hisr.read().dmeif6().bit_is_set(), + StreamId::S_7 => self.hisr.read().dmeif7().bit_is_set(), + } + } + + /// Returns the Fifo Error flag + pub fn fifo_error_flag(&self, id: StreamId) -> bool { + match id { + StreamId::S_0 => self.lisr.read().feif0().bit_is_set(), + StreamId::S_1 => self.lisr.read().feif1().bit_is_set(), + StreamId::S_2 => self.lisr.read().feif2().bit_is_set(), + StreamId::S_3 => self.lisr.read().feif3().bit_is_set(), + StreamId::S_4 => self.hisr.read().feif4().bit_is_set(), + StreamId::S_5 => self.hisr.read().feif5().bit_is_set(), + StreamId::S_6 => self.hisr.read().feif6().bit_is_set(), + StreamId::S_7 => self.hisr.read().feif7().bit_is_set(), + } + } + + pub fn clear_isr(&mut self, id: StreamId) { + self.clear_transfer_complete(id); + self.clear_half_transfer(id); + self.clear_transfer_error(id); + self.clear_direct_mode_error(id); + self.clear_fifo_error(id); + } + + /// Clears the Transfer Complete flag + pub fn clear_transfer_complete(&mut self, id: StreamId) { + match id { + StreamId::S_0 => { + self.lifcr.write(|w| w.ctcif0().set_bit()); + } + StreamId::S_1 => { + self.lifcr.write(|w| w.ctcif1().set_bit()); + } + StreamId::S_2 => { + self.lifcr.write(|w| w.ctcif2().set_bit()); + } + StreamId::S_3 => { + self.lifcr.write(|w| w.ctcif3().set_bit()); + } + StreamId::S_4 => { + self.hifcr.write(|w| w.ctcif4().set_bit()); + } + StreamId::S_5 => { + self.hifcr.write(|w| w.ctcif5().set_bit()); + } + StreamId::S_6 => { + self.hifcr.write(|w| w.ctcif6().set_bit()); + } + StreamId::S_7 => { + self.hifcr.write(|w| w.ctcif7().set_bit()); + } + } + } + + /// Clears the Half Transfer flag + pub fn clear_half_transfer(&mut self, id: StreamId) { + match id { + StreamId::S_0 => { + self.lifcr.write(|w| w.chtif0().set_bit()); + } + StreamId::S_1 => { + self.lifcr.write(|w| w.chtif1().set_bit()); + } + StreamId::S_2 => { + self.lifcr.write(|w| w.chtif2().set_bit()); + } + StreamId::S_3 => { + self.lifcr.write(|w| w.chtif3().set_bit()); + } + StreamId::S_4 => { + self.hifcr.write(|w| w.chtif4().set_bit()); + } + StreamId::S_5 => { + self.hifcr.write(|w| w.chtif5().set_bit()); + } + StreamId::S_6 => { + self.hifcr.write(|w| w.chtif6().set_bit()); + } + StreamId::S_7 => { + self.hifcr.write(|w| w.chtif7().set_bit()); + } + } + } + + /// Clears the Transfer Error flag + pub fn clear_transfer_error(&mut self, id: StreamId) { + match id { + StreamId::S_0 => { + self.lifcr.write(|w| w.cteif0().set_bit()); + } + StreamId::S_1 => { + self.lifcr.write(|w| w.cteif1().set_bit()); + } + StreamId::S_2 => { + self.lifcr.write(|w| w.cteif2().set_bit()); + } + StreamId::S_3 => { + self.lifcr.write(|w| w.cteif3().set_bit()); + } + StreamId::S_4 => { + self.hifcr.write(|w| w.cteif4().set_bit()); + } + StreamId::S_5 => { + self.hifcr.write(|w| w.cteif5().set_bit()); + } + StreamId::S_6 => { + self.hifcr.write(|w| w.cteif6().set_bit()); + } + StreamId::S_7 => { + self.hifcr.write(|w| w.cteif7().set_bit()); + } + } + } + + /// Clears the Direct Mode Error flag + pub fn clear_direct_mode_error(&mut self, id: StreamId) { + match id { + StreamId::S_0 => { + self.lifcr.write(|w| w.cdmeif0().set_bit()); + } + StreamId::S_1 => { + self.lifcr.write(|w| w.cdmeif1().set_bit()); + } + StreamId::S_2 => { + self.lifcr.write(|w| w.cdmeif2().set_bit()); + } + StreamId::S_3 => { + self.lifcr.write(|w| w.cdmeif3().set_bit()); + } + StreamId::S_4 => { + self.hifcr.write(|w| w.cdmeif4().set_bit()); + } + StreamId::S_5 => { + self.hifcr.write(|w| w.cdmeif5().set_bit()); + } + StreamId::S_6 => { + self.hifcr.write(|w| w.cdmeif6().set_bit()); + } + StreamId::S_7 => { + self.hifcr.write(|w| w.cdmeif7().set_bit()); + } + } + } + + /// Clears the Fifo Error flag + pub fn clear_fifo_error(&mut self, id: StreamId) { + match id { + StreamId::S_0 => { + self.lifcr.write(|w| w.cfeif0().set_bit()); + } + StreamId::S_1 => { + self.lifcr.write(|w| w.cfeif1().set_bit()); + } + StreamId::S_2 => { + self.lifcr.write(|w| w.cfeif2().set_bit()); + } + StreamId::S_3 => { + self.lifcr.write(|w| w.cfeif3().set_bit()); + } + StreamId::S_4 => { + self.hifcr.write(|w| w.cfeif4().set_bit()); + } + StreamId::S_5 => { + self.hifcr.write(|w| w.cfeif5().set_bit()); + } + StreamId::S_6 => { + self.hifcr.write(|w| w.cfeif6().set_bit()); + } + StreamId::S_7 => { + self.hifcr.write(|w| w.cfeif7().set_bit()); + } + } + } } unsafe impl Send for StreamIsr where DMA: DmaPeripheral {} diff --git a/src/dma/utils.rs b/src/dma/utils.rs index aeebaff0..54c1e5bb 100644 --- a/src/dma/utils.rs +++ b/src/dma/utils.rs @@ -1,6 +1,4 @@ use core::fmt; -use core::ops::Deref; - pub trait DefaultTraits: Copy + Clone + PartialEq + Eq + fmt::Debug {} impl DefaultTraits for T {} @@ -13,22 +11,27 @@ impl DefaultTraits for T {} /// # use core::cell::Cell; /// /// pub struct ShallBeSync<'a> { -/// cell: UniqueRef<'a, Cell>, +/// cell: &'a Cell, /// } /// /// impl<'a> ShallBeSync<'a> { -/// // Some sync-compliant methods +/// pub fn new(cell: UniqueRef<'a, Cell>) -> Self { +/// Self { +/// cell: cell.into_inner(), +/// } +/// } /// } /// -/// // This wouldn't be safe if multiple references to `cell` would coexist +/// // This wouldn't be safe if multiple references to `cell` could coexist upon initialization /// unsafe impl Sync for ShallBeSync<'_> {} /// ``` +#[derive(Debug)] pub struct UniqueRef<'a, T> { inner: &'a T, } +#[allow(dead_code)] impl<'a, T> UniqueRef<'a, T> { - #[allow(dead_code)] pub fn new(x: &'a mut T) -> Self { Self { inner: x } } @@ -36,12 +39,17 @@ impl<'a, T> UniqueRef<'a, T> { pub unsafe fn new_unchecked(x: &'a T) -> Self { Self { inner: x } } -} -impl Deref for UniqueRef<'_, T> { - type Target = T; - - fn deref(&self) -> &T { + pub fn get(&mut self) -> &T { &self.inner } + + pub unsafe fn get_unchecked(&self) -> &T { + &*self.inner + } + + /// Releases the inner reference. After this call, the reference may be duplicated again. + pub fn into_inner(self) -> &'a T { + self.inner + } } From bf013dd89e49df7a419fd1c213d0b832cc34f24c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ad=C3=A4?= Date: Mon, 27 Apr 2020 11:31:48 +0200 Subject: [PATCH 101/103] Started implementation of serial dma --- src/serial/dma.rs | 327 +++++++++++++++------------------------------- src/serial/mod.rs | 5 +- 2 files changed, 108 insertions(+), 224 deletions(-) diff --git a/src/serial/dma.rs b/src/serial/dma.rs index 7490ce01..64abb2ad 100644 --- a/src/serial/dma.rs +++ b/src/serial/dma.rs @@ -4,19 +4,21 @@ use crate::dma::mux::request_ids::{ Uart7TxDma, Uart8RxDma, Uart8TxDma, Usart1RxDma, Usart1TxDma, Usart2RxDma, Usart2TxDma, Usart3RxDma, Usart3TxDma, Usart6RxDma, Usart6TxDma, }; -use crate::dma::mux::{EgED as IEgED, SyncED as ISyncED}; -use crate::dma::stream::{ - Disabled as StreamDisabled, IsrCleared as StreamIsrCleared, StreamIsr, +use crate::dma::transfer::buffer::{ + FixedBuffer, FixedBufferMut, FixedBufferRef, MemoryBufferType, }; -use crate::dma::transfer::{ - FixedBuffer, FixedBufferR, MemoryBufferStatic, Ongoing as TransferOngoing, - Payload, PeripheralBuffer, Start as TransferStart, +use crate::dma::transfer::config::{ + MemoryToPeripheral, PeripheralToMemory, TransferDirection, }; -use crate::dma::{Channel, ChannelId, Mux, SafeTransfer}; +use crate::dma::transfer::{Buffer, Buffers, Byte, Payload}; +use crate::private; +use crate::stm32::usart1::RegisterBlock; use crate::stm32::{UART4, UART5, UART7, UART8}; use crate::stm32::{USART1, USART2, USART3, USART6}; + +use core::cell::UnsafeCell; +use core::marker::PhantomData; use core::ops::Deref; -use stm32h7::stm32h743::usart1::RegisterBlock; pub trait SerialRequest: RequestIdSome {} @@ -38,9 +40,36 @@ impl SerialRequest for Uart7TxDma {} impl SerialRequest for Uart8RxDma {} impl SerialRequest for Uart8TxDma {} +pub trait RxRequest: SerialRequest {} +pub trait TxRequest: SerialRequest {} + +impl RxRequest for Usart1RxDma {} +impl TxRequest for Usart1TxDma {} + +impl RxRequest for Usart2RxDma {} +impl TxRequest for Usart2TxDma {} + +impl RxRequest for Usart3RxDma {} +impl TxRequest for Usart3TxDma {} + +impl RxRequest for Uart4RxDma {} +impl TxRequest for Uart4TxDma {} + +impl RxRequest for Uart5RxDma {} +impl TxRequest for Uart5TxDma {} + +impl RxRequest for Usart6RxDma {} +impl TxRequest for Usart6TxDma {} + +impl RxRequest for Uart7RxDma {} +impl TxRequest for Uart7TxDma {} + +impl RxRequest for Uart8RxDma {} +impl TxRequest for Uart8TxDma {} + pub trait SerialChannelDma { - type Rx: SerialRequest; - type Tx: SerialRequest; + type Rx: RxRequest; + type Tx: TxRequest; } impl SerialChannelDma for USART1 { @@ -83,246 +112,102 @@ impl SerialChannelDma for UART8 { type Tx = Uart8TxDma; } -pub trait IState {} - -pub struct Start -where - CXX: ChannelId, - ReqId: SerialRequest, - SyncED: ISyncED, - EgED: IEgED, -{ - channel: - Channel, -} - -pub struct Initialized +pub trait SerialDirection: private::Sealed where - CXX: ChannelId, - ReqId: SerialRequest, - SyncED: ISyncED, - EgED: IEgED, - Peripheral: Payload, + Peripheral: Payload, Memory: Payload, { - channel: - Channel, - transfer: SafeTransfer<'static, Peripheral, Memory, TransferStart>, -} - -pub struct Ongoing -where - CXX: ChannelId, - ReqId: SerialRequest, - SyncED: ISyncED, - EgED: IEgED, - Peripheral: Payload, - Memory: Payload, -{ - mux: Mux, - transfer: SafeTransfer<'static, Peripheral, Memory, TransferOngoing>, + #[doc(hidden)] + unsafe fn transfer_direction( + serial: &Serial, + memory_buffer: MemoryBufferType, + ) -> TransferDirection<'static, Peripheral, Memory> + where + USART: Deref; } -impl IState for Start -where - CXX: ChannelId, - ReqId: SerialRequest, - SyncED: ISyncED, - EgED: IEgED, -{ -} +pub struct Rx; +pub struct Tx; -impl IState - for Initialized -where - CXX: ChannelId, - ReqId: SerialRequest, - SyncED: ISyncED, - EgED: IEgED, - Peripheral: Payload, - Memory: Payload, -{ -} +impl private::Sealed for Rx {} +impl private::Sealed for Tx {} -impl IState - for Ongoing +impl SerialDirection for Rx where - CXX: ChannelId, - ReqId: SerialRequest, - SyncED: ISyncED, - EgED: IEgED, - Peripheral: Payload, + Peripheral: Payload, Memory: Payload, { -} + #[doc(hidden)] + unsafe fn transfer_direction( + serial: &Serial, + memory_buffer: MemoryBufferType, + ) -> TransferDirection<'static, Peripheral, Memory> + where + USART: Deref, + { + let ptr = &serial.usart.rdr as *const _ as *const Peripheral; + let peripheral_buffer = + Buffer::Fixed(FixedBuffer::Ref(FixedBufferRef::new(&*ptr))); + let buffers = Buffers { + peripheral_buffer, + memory_buffer, + }; -pub struct SerialDmaRx -where - USART: SerialChannelDma + Deref, - State: IState, -{ - serial: Serial, - state: State, + TransferDirection::P2M(PeripheralToMemory::new(buffers)) + } } -impl - SerialDmaRx> +impl SerialDirection for Tx where - USART: SerialChannelDma + Deref, - CXX: ChannelId, - SyncED: ISyncED, - EgED: IEgED, + Peripheral: Payload, + Memory: Payload, { - pub fn new( - serial: Serial, - channel: Channel< - CXX, - StreamDisabled, - StreamIsrCleared, - USART::Rx, - SyncED, - EgED, - >, - ) -> Self { - let mut s = Self { - serial, - state: Start { channel }, - }; - - s.enable_dma_mode(); - - s - } - - pub fn init( - self, - memory: MemoryBufferStatic, - ) -> SerialDmaRx< - USART, - PINS, - Initialized, - > + #[doc(hidden)] + unsafe fn transfer_direction( + serial: &Serial, + memory_buffer: MemoryBufferType, + ) -> TransferDirection<'static, Peripheral, Memory> where - Peripheral: Payload, - Memory: Payload, + USART: Deref, { - if !memory.is_write() { - panic!("The memory buffer must be a Write-Buffer."); - } - - let pa = &self.serial.usart.rdr as *const _ as *const Peripheral; - let peripheral = PeripheralBuffer::Fixed(FixedBuffer::Read( - FixedBufferR::new(unsafe { &*pa }), - )); - - let transfer = SafeTransfer::new(peripheral, memory); - - SerialDmaRx { - serial: self.serial, - state: Initialized { - transfer, - channel: self.state.channel, - }, - } - } - - pub fn free( - mut self, - ) -> ( - Serial, - Channel, - ) { - self.disable_dma_mode(); - - (self.serial, self.state.channel) - } - - fn enable_dma_mode(&mut self) { - self.serial.usart.cr3.modify(|_, w| w.dmar().set_bit()); - } + let reg_cell = + &*(&serial.usart.tdr as *const _ as *const UnsafeCell); + let ptr = reg_cell.get() as *mut Peripheral; + + let peripheral_buffer = + Buffer::Fixed(FixedBuffer::Mut(FixedBufferMut::new(&mut *ptr))); + let buffers = Buffers { + peripheral_buffer, + memory_buffer, + }; - fn disable_dma_mode(&mut self) { - self.serial.usart.cr3.modify(|_, w| w.dmar().clear_bit()); + TransferDirection::M2P(MemoryToPeripheral::new(buffers)) } } -impl - SerialDmaRx< - USART, - PINS, - Initialized, - > +pub struct Config where - USART: SerialChannelDma + Deref, - CXX: ChannelId, - SyncED: ISyncED, - EgED: IEgED, - Peripheral: Payload, + Direction: SerialDirection, + Peripheral: Payload, Memory: Payload, { - pub fn start( - self, - ) -> SerialDmaRx< - USART, - PINS, - Ongoing, - > { - let transfer = self.state.transfer.start(self.state.channel.stream); - - SerialDmaRx { - serial: self.serial, - state: Ongoing { - mux: self.state.channel.mux, - transfer, - }, - } - } + memory_buffer: MemoryBufferType, + _phantom: PhantomData<(Direction, Peripheral)>, } -impl - SerialDmaRx< - USART, - PINS, - Ongoing, - > +impl Config where - USART: SerialChannelDma + Deref, - CXX: ChannelId, - SyncED: ISyncED, - EgED: IEgED, - Peripheral: Payload, + Direction: SerialDirection, + Peripheral: Payload, Memory: Payload, { - pub fn transfer( - &self, - ) -> &SafeTransfer<'static, Peripheral, Memory, TransferOngoing> { - &self.state.transfer - } - - pub fn transfer_mut( - &mut self, - ) -> &mut SafeTransfer<'static, Peripheral, Memory, TransferOngoing> + unsafe fn build_transfer_direction( + serial: &Serial, + memory_buffer: MemoryBufferType, + ) -> TransferDirection<'static, Peripheral, Memory> + where + USART: Deref, { - &mut self.state.transfer - } - - pub fn mux(&self) -> &Mux { - &self.state.mux - } - - pub fn stop( - self, - isr: &mut StreamIsr, - ) -> SerialDmaRx> { - let stream = self.state.transfer.stop().clear_isr(isr); - let channel = Channel { - stream, - mux: self.state.mux, - }; - - SerialDmaRx { - serial: self.serial, - state: Start { channel }, - } + Direction::transfer_direction(serial, memory_buffer) } } diff --git a/src/serial/mod.rs b/src/serial/mod.rs index 688479df..2134deb7 100644 --- a/src/serial/mod.rs +++ b/src/serial/mod.rs @@ -1,8 +1,7 @@ //! Serial -/* +#[cfg(feature = "dma")] pub mod dma; -*/ use core::fmt; use core::marker::PhantomData; @@ -385,7 +384,7 @@ macro_rules! usart { ccdr.$apb.rstr().modify(|_, w| w.$usartXrst().clear_bit()); // Get kernel clock - let usart_ker_ck = match Self::kernel_clk(ccdr) { + let usart_ker_ck = match Self::kernel_clk(ccdr) { Some(ker_hz) => ker_hz.0, _ => panic!("$USARTX kernel clock not running!") }; From be1ea6cb12bc32efa169d7bb138c27763a317bfc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ad=C3=A4?= Date: Mon, 27 Apr 2020 22:00:23 +0200 Subject: [PATCH 102/103] update --- src/dma/mod.rs | 2 +- src/dma/mux/mod.rs | 2 +- src/dma/mux/request_gen.rs | 2 +- src/dma/stream/mod.rs | 2 +- src/dma/transfer/buffer.rs | 21 ++++++++++++++ src/dma/utils.rs | 51 ---------------------------------- src/lib.rs | 1 + src/serial/dma.rs | 21 ++++++++++---- src/utils.rs | 56 ++++++++++++++++++++++++++++++++++++++ 9 files changed, 97 insertions(+), 61 deletions(-) create mode 100644 src/utils.rs diff --git a/src/dma/mod.rs b/src/dma/mod.rs index 459280e1..4174a669 100644 --- a/src/dma/mod.rs +++ b/src/dma/mod.rs @@ -30,7 +30,7 @@ pub use self::mux::Mux; pub use self::stream::Stream; pub use self::transfer::Transfer; -use self::utils::UniqueRef; +use crate::utils::UniqueRef; /// Marker Trait for DMA peripherals pub trait DmaPeripheral: private::Sealed {} diff --git a/src/dma/mux/mod.rs b/src/dma/mux/mod.rs index be8d3d20..610c0ed1 100644 --- a/src/dma/mux/mod.rs +++ b/src/dma/mux/mod.rs @@ -4,7 +4,7 @@ pub mod request_gen; use self::request_gen::RequestGenIsr; use self::request_ids::{ReqNone, RequestId as IRequestId, RequestIdSome}; -use super::utils::UniqueRef; +use crate::utils::UniqueRef; use super::ChannelId; use crate::stm32::dmamux1::{CCR, CFR, CSR}; use core::convert::{TryFrom, TryInto}; diff --git a/src/dma/mux/request_gen.rs b/src/dma/mux/request_gen.rs index 694146b2..cce90cbb 100644 --- a/src/dma/mux/request_gen.rs +++ b/src/dma/mux/request_gen.rs @@ -1,6 +1,6 @@ //! DMA Request Generator -use super::super::utils::UniqueRef; +use crate::utils::UniqueRef; use crate::private; use crate::stm32::dmamux1::{RGCFR, RGCR, RGSR}; use core::convert::TryInto; diff --git a/src/dma/stream/mod.rs b/src/dma/stream/mod.rs index 4eb1cd45..46636f02 100644 --- a/src/dma/stream/mod.rs +++ b/src/dma/stream/mod.rs @@ -11,7 +11,7 @@ use self::config::{ TransferCompleteInterrupt, TransferDirection, TransferDirectionConf, TransferErrorInterrupt, TransferMode, TransferModeConf, }; -use super::utils::UniqueRef; +use crate::utils::UniqueRef; use super::{ChannelId, DmaPeripheral}; use crate::nb::Error as NbError; use crate::stm32::dma1::{HIFCR, HISR, LIFCR, LISR, ST}; diff --git a/src/dma/transfer/buffer.rs b/src/dma/transfer/buffer.rs index 498a3f69..0bcdb2a5 100644 --- a/src/dma/transfer/buffer.rs +++ b/src/dma/transfer/buffer.rs @@ -1,6 +1,7 @@ use super::Payload; use core::ptr; use enum_as_inner::EnumAsInner; +use crate::utils::UniqueRef; #[derive(Debug, EnumAsInner)] pub enum Buffer<'wo, P> @@ -207,6 +208,13 @@ where FixedBufferMut(buffer) } + pub fn with_ref(buffer: UniqueRef<'static, P>) -> Self { + let p = buffer.into_inner(); + let mut_ptr = p as *const _ as *mut P; + + Self::new(unsafe { &mut *mut_ptr }) + } + /// # Safety /// /// - The caller must ensure, that the DMA is currently not writing this address. @@ -345,6 +353,13 @@ where RegularOffsetBufferMut(buffer) } + pub fn with_ref(buffer: UniqueRef<'static, [P]>) -> Self { + let p = buffer.into_inner(); + let mut_ptr = p as *const _ as *mut [P]; + + Self::new(unsafe { &mut *mut_ptr }) + } + /// # Safety /// /// - The caller must ensure, that the DMA is currently not modifying this address. @@ -512,6 +527,12 @@ where } } + pub fn with_ref(buffer: &'wo mut [UniqueRef<'static, P>]) -> Self { + let mut_ptr = buffer as *mut _ as *mut [&'static mut P]; + + Self::new(unsafe { &mut *mut_ptr }) + } + /// # Safety /// /// The caller must ensure, that the DMA is currently not modifying this address. diff --git a/src/dma/utils.rs b/src/dma/utils.rs index 54c1e5bb..d5cd5135 100644 --- a/src/dma/utils.rs +++ b/src/dma/utils.rs @@ -2,54 +2,3 @@ use core::fmt; pub trait DefaultTraits: Copy + Clone + PartialEq + Eq + fmt::Debug {} impl DefaultTraits for T {} - -/// Guarantees that the stored reference is unique (i.e. not shared). -/// -/// # Example -/// -/// ```rust -/// # use core::cell::Cell; -/// -/// pub struct ShallBeSync<'a> { -/// cell: &'a Cell, -/// } -/// -/// impl<'a> ShallBeSync<'a> { -/// pub fn new(cell: UniqueRef<'a, Cell>) -> Self { -/// Self { -/// cell: cell.into_inner(), -/// } -/// } -/// } -/// -/// // This wouldn't be safe if multiple references to `cell` could coexist upon initialization -/// unsafe impl Sync for ShallBeSync<'_> {} -/// ``` -#[derive(Debug)] -pub struct UniqueRef<'a, T> { - inner: &'a T, -} - -#[allow(dead_code)] -impl<'a, T> UniqueRef<'a, T> { - pub fn new(x: &'a mut T) -> Self { - Self { inner: x } - } - - pub unsafe fn new_unchecked(x: &'a T) -> Self { - Self { inner: x } - } - - pub fn get(&mut self) -> &T { - &self.inner - } - - pub unsafe fn get_unchecked(&self) -> &T { - &*self.inner - } - - /// Releases the inner reference. After this call, the reference may be duplicated again. - pub fn into_inner(self) -> &'a T { - self.inner - } -} diff --git a/src/lib.rs b/src/lib.rs index 5ae49fb2..fa700035 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -82,6 +82,7 @@ pub use crate::stm32 as device; pub use crate::stm32::interrupt; mod private; +mod utils; #[cfg(feature = "device-selected")] pub mod adc; diff --git a/src/serial/dma.rs b/src/serial/dma.rs index 64abb2ad..44b04b81 100644 --- a/src/serial/dma.rs +++ b/src/serial/dma.rs @@ -15,8 +15,8 @@ use crate::private; use crate::stm32::usart1::RegisterBlock; use crate::stm32::{UART4, UART5, UART7, UART8}; use crate::stm32::{USART1, USART2, USART3, USART6}; +use crate::utils::UniqueRef; -use core::cell::UnsafeCell; use core::marker::PhantomData; use core::ops::Deref; @@ -137,6 +137,10 @@ where Peripheral: Payload, Memory: Payload, { + /// # Safety + /// + /// The peripheral buffer is aliasing the `RDR` register, + /// without the borrowchecker knowing. #[doc(hidden)] unsafe fn transfer_direction( serial: &Serial, @@ -162,6 +166,14 @@ where Peripheral: Payload, Memory: Payload, { + /// # Safety + /// + /// The peripheral buffer is mutably aliasing the `TDR` register, + /// without the borrowchecker knowing, so the caller must ensure + /// + /// * that `TDR` is not aliased when calling this method, and + /// * after calling this method, either `TDR` or peripheral buffer + /// are mutably aliased OR not mutably aliased at the same time #[doc(hidden)] unsafe fn transfer_direction( serial: &Serial, @@ -170,12 +182,9 @@ where where USART: Deref, { - let reg_cell = - &*(&serial.usart.tdr as *const _ as *const UnsafeCell); - let ptr = reg_cell.get() as *mut Peripheral; - + let ptr = &serial.usart.tdr as *const _ as *const Peripheral; let peripheral_buffer = - Buffer::Fixed(FixedBuffer::Mut(FixedBufferMut::new(&mut *ptr))); + Buffer::Fixed(FixedBuffer::Mut(FixedBufferMut::with_ref(UniqueRef::new_unchecked(&*ptr)))); let buffers = Buffers { peripheral_buffer, memory_buffer, diff --git a/src/utils.rs b/src/utils.rs new file mode 100644 index 00000000..37232ec4 --- /dev/null +++ b/src/utils.rs @@ -0,0 +1,56 @@ +/// Guarantees that the stored reference is unique (i.e. not shared). +/// +/// # Example +/// +/// ```rust +/// # use core::cell::Cell; +/// +/// pub struct ShallBeSync<'a> { +/// cell: &'a Cell, +/// } +/// +/// impl<'a> ShallBeSync<'a> { +/// pub fn new(cell: UniqueRef<'a, Cell>) -> Self { +/// Self { +/// cell: cell.into_inner(), +/// } +/// } +/// } +/// +/// // This wouldn't be safe if multiple references to `cell` could coexist upon initialization +/// unsafe impl Sync for ShallBeSync<'_> {} +/// ``` +#[derive(Debug)] +pub struct UniqueRef<'a, T> +where + T: ?Sized, +{ + inner: &'a T, +} + +#[allow(dead_code)] +impl<'a, T> UniqueRef<'a, T> +where + T: ?Sized, +{ + pub fn new(x: &'a mut T) -> Self { + Self { inner: x } + } + + pub unsafe fn new_unchecked(x: &'a T) -> Self { + Self { inner: x } + } + + pub fn get(&mut self) -> &T { + &self.inner + } + + pub unsafe fn get_unchecked(&self) -> &T { + &*self.inner + } + + /// Releases the inner reference. After this call, the reference may be duplicated again. + pub fn into_inner(self) -> &'a T { + self.inner + } +} From e1c4455273796837bba587c062335ccf0dc15cfb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ad=C3=A4?= Date: Mon, 27 Apr 2020 23:43:56 +0200 Subject: [PATCH 103/103] fmt --- src/dma/mux/mod.rs | 2 +- src/dma/mux/request_gen.rs | 2 +- src/dma/stream/mod.rs | 2 +- src/dma/transfer/buffer.rs | 2 +- src/serial/dma.rs | 5 +++-- 5 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/dma/mux/mod.rs b/src/dma/mux/mod.rs index 610c0ed1..add04df6 100644 --- a/src/dma/mux/mod.rs +++ b/src/dma/mux/mod.rs @@ -4,9 +4,9 @@ pub mod request_gen; use self::request_gen::RequestGenIsr; use self::request_ids::{ReqNone, RequestId as IRequestId, RequestIdSome}; -use crate::utils::UniqueRef; use super::ChannelId; use crate::stm32::dmamux1::{CCR, CFR, CSR}; +use crate::utils::UniqueRef; use core::convert::{TryFrom, TryInto}; use core::marker::PhantomData; diff --git a/src/dma/mux/request_gen.rs b/src/dma/mux/request_gen.rs index cce90cbb..0093ae8d 100644 --- a/src/dma/mux/request_gen.rs +++ b/src/dma/mux/request_gen.rs @@ -1,8 +1,8 @@ //! DMA Request Generator -use crate::utils::UniqueRef; use crate::private; use crate::stm32::dmamux1::{RGCFR, RGCR, RGSR}; +use crate::utils::UniqueRef; use core::convert::TryInto; use core::marker::PhantomData; diff --git a/src/dma/stream/mod.rs b/src/dma/stream/mod.rs index 46636f02..911fe1b0 100644 --- a/src/dma/stream/mod.rs +++ b/src/dma/stream/mod.rs @@ -11,10 +11,10 @@ use self::config::{ TransferCompleteInterrupt, TransferDirection, TransferDirectionConf, TransferErrorInterrupt, TransferMode, TransferModeConf, }; -use crate::utils::UniqueRef; use super::{ChannelId, DmaPeripheral}; use crate::nb::Error as NbError; use crate::stm32::dma1::{HIFCR, HISR, LIFCR, LISR, ST}; +use crate::utils::UniqueRef; use core::convert::{Infallible, TryInto}; use core::marker::PhantomData; diff --git a/src/dma/transfer/buffer.rs b/src/dma/transfer/buffer.rs index 0bcdb2a5..6eea667a 100644 --- a/src/dma/transfer/buffer.rs +++ b/src/dma/transfer/buffer.rs @@ -1,7 +1,7 @@ use super::Payload; +use crate::utils::UniqueRef; use core::ptr; use enum_as_inner::EnumAsInner; -use crate::utils::UniqueRef; #[derive(Debug, EnumAsInner)] pub enum Buffer<'wo, P> diff --git a/src/serial/dma.rs b/src/serial/dma.rs index 44b04b81..ef4099ec 100644 --- a/src/serial/dma.rs +++ b/src/serial/dma.rs @@ -183,8 +183,9 @@ where USART: Deref, { let ptr = &serial.usart.tdr as *const _ as *const Peripheral; - let peripheral_buffer = - Buffer::Fixed(FixedBuffer::Mut(FixedBufferMut::with_ref(UniqueRef::new_unchecked(&*ptr)))); + let peripheral_buffer = Buffer::Fixed(FixedBuffer::Mut( + FixedBufferMut::with_ref(UniqueRef::new_unchecked(&*ptr)), + )); let buffers = Buffers { peripheral_buffer, memory_buffer,