123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426 |
- #![allow(dead_code)]
- use core::marker::PhantomData;
- use core::ops;
- use rcc::AHB;
- #[derive(Debug)]
- pub enum Error {
- Overrun,
- #[doc(hidden)]
- _Extensible,
- }
- pub enum Event {
- HalfTransfer,
- TransferComplete,
- }
- #[derive(Clone, Copy, PartialEq)]
- pub enum Half {
- First,
- Second,
- }
- pub struct CircBuffer<BUFFER, CHANNEL>
- where
- BUFFER: 'static,
- {
- buffer: &'static mut [BUFFER; 2],
- channel: CHANNEL,
- readable_half: Half,
- }
- impl<BUFFER, CHANNEL> CircBuffer<BUFFER, CHANNEL> {
- pub(crate) fn new(buf: &'static mut [BUFFER; 2], chan: CHANNEL) -> Self {
- CircBuffer {
- buffer: buf,
- channel: chan,
- readable_half: Half::Second,
- }
- }
- }
- pub trait Static<B> {
- fn borrow(&self) -> &B;
- }
- impl<B> Static<B> for &'static B {
- fn borrow(&self) -> &B {
- *self
- }
- }
- impl<B> Static<B> for &'static mut B {
- fn borrow(&self) -> &B {
- *self
- }
- }
- pub trait DmaExt {
- type Channels;
- fn split(self, ahb: &mut AHB) -> Self::Channels;
- }
- pub struct Transfer<MODE, BUFFER, CHANNEL, PAYLOAD> {
- _mode: PhantomData<MODE>,
- buffer: BUFFER,
- channel: CHANNEL,
- payload: PAYLOAD,
- }
- impl<BUFFER, CHANNEL, PAYLOAD> Transfer<R, BUFFER, CHANNEL, PAYLOAD> {
- pub(crate) fn r(buffer: BUFFER, channel: CHANNEL, payload: PAYLOAD) -> Self {
- Transfer {
- _mode: PhantomData,
- buffer,
- channel,
- payload,
- }
- }
- }
- impl<BUFFER, CHANNEL, PAYLOAD> Transfer<W, BUFFER, CHANNEL, PAYLOAD> {
- pub(crate) fn w(buffer: BUFFER, channel: CHANNEL, payload: PAYLOAD) -> Self {
- Transfer {
- _mode: PhantomData,
- buffer,
- channel,
- payload,
- }
- }
- }
- impl<BUFFER, CHANNEL, PAYLOAD> ops::Deref for Transfer<R, BUFFER, CHANNEL, PAYLOAD> {
- type Target = BUFFER;
- fn deref(&self) -> &BUFFER {
- &self.buffer
- }
- }
- /// Read transfer
- pub struct R;
- /// Write transfer
- pub struct W;
- macro_rules! dma {
- ($($DMAX:ident: ($dmaX:ident, $dmaXen:ident, $dmaXrst:ident, {
- $($CX:ident: (
- $ccrX:ident,
- $CCRX:ident,
- $cndtrX:ident,
- $CNDTRX:ident,
- $cparX:ident,
- $CPARX:ident,
- $cmarX:ident,
- $CMARX:ident,
- $htifX:ident,
- $tcifX:ident,
- $chtifX:ident,
- $ctcifX:ident,
- $cgifX:ident
- ),)+
- }),)+) => {
- $(
- pub mod $dmaX {
- use core::sync::atomic::{self, Ordering};
- use stm32::{$DMAX, dma1};
- use dma::{CircBuffer, DmaExt, Error, Event, Half, Transfer, W};
- use rcc::AHB;
- pub struct Channels((), $(pub $CX),+);
- $(
- pub struct $CX { _0: () }
- impl $CX {
- pub fn listen(&mut self, event: Event) {
- match event {
- Event::HalfTransfer => self.ccr().modify(|_, w| w.htie().set_bit()),
- Event::TransferComplete => {
- self.ccr().modify(|_, w| w.tcie().set_bit())
- }
- }
- }
- pub fn unlisten(&mut self, event: Event) {
- match event {
- Event::HalfTransfer => {
- self.ccr().modify(|_, w| w.htie().clear_bit())
- },
- Event::TransferComplete => {
- self.ccr().modify(|_, w| w.tcie().clear_bit())
- }
- }
- }
- pub(crate) fn isr(&self) -> dma1::isr::R {
- // NOTE(unsafe) atomic read with no side effects
- unsafe { (*$DMAX::ptr()).isr.read() }
- }
- pub(crate) fn ifcr(&self) -> &dma1::IFCR {
- unsafe { &(*$DMAX::ptr()).ifcr }
- }
- pub(crate) fn ccr(&mut self) -> &dma1::$CCRX {
- unsafe { &(*$DMAX::ptr()).$ccrX }
- }
- pub(crate) fn cndtr(&mut self) -> &dma1::$CNDTRX {
- unsafe { &(*$DMAX::ptr()).$cndtrX }
- }
- pub(crate) fn cpar(&mut self) -> &dma1::$CPARX {
- unsafe { &(*$DMAX::ptr()).$cparX }
- }
- pub(crate) fn cmar(&mut self) -> &dma1::$CMARX {
- unsafe { &(*$DMAX::ptr()).$cmarX }
- }
- pub(crate) fn get_cndtr(&self) -> u32 {
- // NOTE(unsafe) atomic read with no side effects
- unsafe { (*$DMAX::ptr()).$cndtrX.read().bits() }
- }
- }
- impl<B> CircBuffer<B, $CX> {
- /// Peeks into the readable half of the buffer
- pub fn peek<R, F>(&mut self, f: F) -> Result<R, Error>
- where
- F: FnOnce(&B, Half) -> R,
- {
- let half_being_read = self.readable_half()?;
- let buf = match half_being_read {
- Half::First => &self.buffer[0],
- Half::Second => &self.buffer[1],
- };
- // XXX does this need a compiler barrier?
- let ret = f(buf, half_being_read);
- let isr = self.channel.isr();
- let first_half_is_done = isr.$htifX().bit_is_set();
- let second_half_is_done = isr.$tcifX().bit_is_set();
- if (half_being_read == Half::First && second_half_is_done) ||
- (half_being_read == Half::Second && first_half_is_done) {
- Err(Error::Overrun)
- } else {
- Ok(ret)
- }
- }
- /// Returns the `Half` of the buffer that can be read
- pub fn readable_half(&mut self) -> Result<Half, Error> {
- let isr = self.channel.isr();
- let first_half_is_done = isr.$htifX().bit_is_set();
- let second_half_is_done = isr.$tcifX().bit_is_set();
- if first_half_is_done && second_half_is_done {
- return Err(Error::Overrun);
- }
- let last_read_half = self.readable_half;
- Ok(match last_read_half {
- Half::First => {
- if second_half_is_done {
- self.channel.ifcr().write(|w| w.$ctcifX().set_bit());
- self.readable_half = Half::Second;
- Half::Second
- } else {
- last_read_half
- }
- }
- Half::Second => {
- if first_half_is_done {
- self.channel.ifcr().write(|w| w.$chtifX().set_bit());
- self.readable_half = Half::First;
- Half::First
- } else {
- last_read_half
- }
- }
- })
- }
- }
- impl<BUFFER, PAYLOAD, MODE> Transfer<MODE, BUFFER, $CX, PAYLOAD> {
- pub fn is_done(&self) -> bool {
- self.channel.isr().$tcifX().bit_is_set()
- }
- pub fn wait(mut self) -> (BUFFER, $CX, PAYLOAD) {
- // XXX should we check for transfer errors here?
- // The manual says "A DMA transfer error can be generated by reading
- // from or writing to a reserved address space". I think it's impossible
- // to get to that state with our type safe API and *safe* Rust.
- while !self.is_done() {}
- self.channel.ifcr().write(|w| w.$cgifX().set_bit());
- self.channel.ccr().modify(|_, w| w.en().clear_bit());
- // TODO can we weaken this compiler barrier?
- // NOTE(compiler_fence) operations on `buffer` should not be reordered
- // before the previous statement, which marks the DMA transfer as done
- atomic::compiler_fence(Ordering::SeqCst);
- (self.buffer, self.channel, self.payload)
- }
- }
- impl<BUFFER, PAYLOAD> Transfer<W, &'static mut BUFFER, $CX, PAYLOAD> {
- pub fn peek<T>(&self) -> &[T]
- where
- BUFFER: AsRef<[T]>,
- {
- let pending = self.channel.get_cndtr() as usize;
- let slice = self.buffer.as_ref();
- let capacity = slice.len();
- &slice[..(capacity - pending)]
- }
- }
- )+
- impl DmaExt for $DMAX {
- type Channels = Channels;
- fn split(self, ahb: &mut AHB) -> Channels {
- ahb.enr().modify(|_, w| w.$dmaXen().set_bit());
- // reset the DMA control registers (stops all on-going transfers)
- $(
- self.$ccrX.reset();
- )+
- Channels((), $($CX { _0: () }),+)
- }
- }
- }
- )+
- }
- }
- dma! {
- DMA1: (dma1, dma1en, dma1rst, {
- C1: (
- ccr1, CCR1,
- cndtr1, CNDTR1,
- cpar1, CPAR1,
- cmar1, CMAR1,
- htif1, tcif1,
- chtif1, ctcif1, cgif1
- ),
- C2: (
- ccr2, CCR2,
- cndtr2, CNDTR2,
- cpar2, CPAR2,
- cmar2, CMAR2,
- htif2, tcif2,
- chtif2, ctcif2, cgif2
- ),
- C3: (
- ccr3, CCR3,
- cndtr3, CNDTR3,
- cpar3, CPAR3,
- cmar3, CMAR3,
- htif3, tcif3,
- chtif3, ctcif3, cgif3
- ),
- C4: (
- ccr4, CCR4,
- cndtr4, CNDTR4,
- cpar4, CPAR4,
- cmar4, CMAR4,
- htif4, tcif4,
- chtif4, ctcif4, cgif4
- ),
- C5: (
- ccr5, CCR5,
- cndtr5, CNDTR5,
- cpar5, CPAR5,
- cmar5, CMAR5,
- htif5, tcif5,
- chtif5, ctcif5, cgif5
- ),
- C6: (
- ccr6, CCR6,
- cndtr6, CNDTR6,
- cpar6, CPAR6,
- cmar6, CMAR6,
- htif6, tcif6,
- chtif6, ctcif6, cgif6
- ),
- C7: (
- ccr7, CCR7,
- cndtr7, CNDTR7,
- cpar7, CPAR7,
- cmar7, CMAR7,
- htif7, tcif7,
- chtif7, ctcif7, cgif7
- ),
- }),
- DMA2: (dma2, dma2en, dma2rst, {
- C1: (
- ccr1, CCR1,
- cndtr1, CNDTR1,
- cpar1, CPAR1,
- cmar1, CMAR1,
- htif1, tcif1,
- chtif1, ctcif1, cgif1
- ),
- C2: (
- ccr2, CCR2,
- cndtr2, CNDTR2,
- cpar2, CPAR2,
- cmar2, CMAR2,
- htif2, tcif2,
- chtif2, ctcif2, cgif2
- ),
- C3: (
- ccr3, CCR3,
- cndtr3, CNDTR3,
- cpar3, CPAR3,
- cmar3, CMAR3,
- htif3, tcif3,
- chtif3, ctcif3, cgif3
- ),
- C4: (
- ccr4, CCR4,
- cndtr4, CNDTR4,
- cpar4, CPAR4,
- cmar4, CMAR4,
- htif4, tcif4,
- chtif4, ctcif4, cgif4
- ),
- C5: (
- ccr5, CCR5,
- cndtr5, CNDTR5,
- cpar5, CPAR5,
- cmar5, CMAR5,
- htif5, tcif5,
- chtif5, ctcif5, cgif5
- ),
- }),
- }
- pub trait DmaChannel {
- type Dma;
- }
|