stm32/dma: improve trait docs, seal Word.

This commit is contained in:
Dario Nieuwenhuis 2021-12-08 03:18:15 +01:00
parent 6179da6b9c
commit b316d2620c
6 changed files with 50 additions and 24 deletions

View file

@ -89,7 +89,7 @@ pac::dma_channels! {
($channel_peri:ident, $dma_peri:ident, bdma, $channel_num:expr, $dmamux:tt) => { ($channel_peri:ident, $dma_peri:ident, bdma, $channel_num:expr, $dmamux:tt) => {
impl crate::dma::sealed::Channel for crate::peripherals::$channel_peri { impl crate::dma::sealed::Channel for crate::peripherals::$channel_peri {
unsafe fn start_write<W: Word>(&mut self, request: Request, buf: &[W], reg_addr: *mut u32) { unsafe fn start_write<W: Word>(&mut self, request: Request, buf: &[W], reg_addr: *mut W) {
low_level_api::reset_status(crate::pac::$dma_peri, $channel_num); low_level_api::reset_status(crate::pac::$dma_peri, $channel_num);
low_level_api::start_transfer( low_level_api::start_transfer(
crate::pac::$dma_peri, crate::pac::$dma_peri,
@ -110,7 +110,7 @@ pac::dma_channels! {
} }
unsafe fn start_write_repeated<W: Word>(&mut self, request: Request, repeated: W, count: usize, reg_addr: *mut u32) { unsafe fn start_write_repeated<W: Word>(&mut self, request: Request, repeated: W, count: usize, reg_addr: *mut W) {
let buf = [repeated]; let buf = [repeated];
low_level_api::reset_status(crate::pac::$dma_peri, $channel_num); low_level_api::reset_status(crate::pac::$dma_peri, $channel_num);
low_level_api::start_transfer( low_level_api::start_transfer(
@ -131,7 +131,7 @@ pac::dma_channels! {
) )
} }
unsafe fn start_read<W: Word>(&mut self, request: Request, reg_addr: *mut u32, buf: &mut [W]) { unsafe fn start_read<W: Word>(&mut self, request: Request, reg_addr: *mut W, buf: &mut [W]) {
low_level_api::reset_status(crate::pac::$dma_peri, $channel_num); low_level_api::reset_status(crate::pac::$dma_peri, $channel_num);
low_level_api::start_transfer( low_level_api::start_transfer(
crate::pac::$dma_peri, crate::pac::$dma_peri,

View file

@ -84,7 +84,7 @@ pub(crate) unsafe fn init() {
pac::dma_channels! { pac::dma_channels! {
($channel_peri:ident, $dma_peri:ident, dma, $channel_num:expr, $dmamux:tt) => { ($channel_peri:ident, $dma_peri:ident, dma, $channel_num:expr, $dmamux:tt) => {
impl crate::dma::sealed::Channel for crate::peripherals::$channel_peri { impl crate::dma::sealed::Channel for crate::peripherals::$channel_peri {
unsafe fn start_write<W: Word>(&mut self, request: Request, buf: &[W], reg_addr: *mut u32) { unsafe fn start_write<W: Word>(&mut self, request: Request, buf: &[W], reg_addr: *mut W) {
let isrn = $channel_num as usize / 4; let isrn = $channel_num as usize / 4;
let isrbit = $channel_num as usize % 4; let isrbit = $channel_num as usize % 4;
low_level_api::reset_status(&crate::pac::$dma_peri, isrn, isrbit); low_level_api::reset_status(&crate::pac::$dma_peri, isrn, isrbit);
@ -104,7 +104,7 @@ pac::dma_channels! {
) )
} }
unsafe fn start_write_repeated<W: Word>(&mut self, request: Request, repeated: W, count: usize, reg_addr: *mut u32) { unsafe fn start_write_repeated<W: Word>(&mut self, request: Request, repeated: W, count: usize, reg_addr: *mut W) {
let buf = [repeated]; let buf = [repeated];
let isrn = $channel_num as usize / 4; let isrn = $channel_num as usize / 4;
let isrbit = $channel_num as usize % 4; let isrbit = $channel_num as usize % 4;
@ -125,7 +125,7 @@ pac::dma_channels! {
) )
} }
unsafe fn start_read<W: Word>(&mut self, request: Request, reg_addr: *mut u32, buf: &mut [W]) { unsafe fn start_read<W: Word>(&mut self, request: Request, reg_addr: *mut W, buf: &mut [W]) {
let isrn = $channel_num as usize / 4; let isrn = $channel_num as usize / 4;
let isrbit = $channel_num as usize % 4; let isrbit = $channel_num as usize % 4;
low_level_api::reset_status(&crate::pac::$dma_peri, isrn, isrbit); low_level_api::reset_status(&crate::pac::$dma_peri, isrn, isrbit);

View file

@ -30,37 +30,59 @@ pub type Request = ();
pub(crate) mod sealed { pub(crate) mod sealed {
use super::*; use super::*;
pub trait Word {}
pub trait Channel { pub trait Channel {
/// Starts this channel for writing a stream of words. /// Starts this channel for writing a stream of words.
unsafe fn start_write<W: Word>(&mut self, request: Request, buf: &[W], reg_addr: *mut u32); ///
/// Safety:
/// - `buf` must be alive for the entire duration of the DMA transfer.
/// - `reg_addr` must be a valid peripheral register address to write to.
unsafe fn start_write<W: super::Word>(
&mut self,
request: Request,
buf: &[W],
reg_addr: *mut W,
);
/// Starts this channel for writing a word repeatedly. /// Starts this channel for writing a word repeatedly.
unsafe fn start_write_repeated<W: Word>( ///
/// Safety:
/// - `reg_addr` must be a valid peripheral register address to write to.
unsafe fn start_write_repeated<W: super::Word>(
&mut self, &mut self,
request: Request, request: Request,
repeated: W, repeated: W,
count: usize, count: usize,
reg_addr: *mut u32, reg_addr: *mut W,
); );
/// Starts this channel for reading a stream of words. /// Starts this channel for reading a stream of words.
unsafe fn start_read<W: Word>( ///
/// Safety:
/// - `buf` must be alive for the entire duration of the DMA transfer.
/// - `reg_addr` must be a valid peripheral register address to write to.
unsafe fn start_read<W: super::Word>(
&mut self, &mut self,
request: Request, request: Request,
reg_addr: *mut u32, reg_addr: *mut W,
buf: &mut [W], buf: &mut [W],
); );
/// Stops this channel. /// Requests the channel to stop.
/// NOTE: The channel does not immediately stop, you have to wait
/// for `is_running() = false`.
fn request_stop(&mut self); fn request_stop(&mut self);
/// Returns whether this channel is active or stopped. /// Returns whether this channel is running or stopped.
///
/// The channel stops running when it either completes or is manually stopped.
fn is_running(&self) -> bool; fn is_running(&self) -> bool;
/// Returns the total number of remaining transfers. /// Returns the total number of remaining transfers.
fn remaining_transfers(&mut self) -> u16; fn remaining_transfers(&mut self) -> u16;
/// Sets the waker that is called when this channel completes. /// Sets the waker that is called when this channel stops (either completed or manually stopped)
fn set_waker(&mut self, waker: &Waker); fn set_waker(&mut self, waker: &Waker);
} }
} }
@ -70,21 +92,25 @@ pub enum WordSize {
TwoBytes, TwoBytes,
FourBytes, FourBytes,
} }
pub trait Word { pub trait Word: sealed::Word {
fn bits() -> WordSize; fn bits() -> WordSize;
} }
impl sealed::Word for u8 {}
impl Word for u8 { impl Word for u8 {
fn bits() -> WordSize { fn bits() -> WordSize {
WordSize::OneByte WordSize::OneByte
} }
} }
impl sealed::Word for u16 {}
impl Word for u16 { impl Word for u16 {
fn bits() -> WordSize { fn bits() -> WordSize {
WordSize::TwoBytes WordSize::TwoBytes
} }
} }
impl sealed::Word for u32 {}
impl Word for u32 { impl Word for u32 {
fn bits() -> WordSize { fn bits() -> WordSize {
WordSize::FourBytes WordSize::FourBytes
@ -98,7 +124,7 @@ mod transfers {
pub fn read<'a, W: Word>( pub fn read<'a, W: Word>(
channel: impl Unborrow<Target = impl Channel> + 'a, channel: impl Unborrow<Target = impl Channel> + 'a,
request: Request, request: Request,
reg_addr: *mut u32, reg_addr: *mut W,
buf: &'a mut [W], buf: &'a mut [W],
) -> impl Future<Output = ()> + 'a { ) -> impl Future<Output = ()> + 'a {
assert!(buf.len() <= 0xFFFF); assert!(buf.len() <= 0xFFFF);
@ -117,7 +143,7 @@ mod transfers {
channel: impl Unborrow<Target = impl Channel> + 'a, channel: impl Unborrow<Target = impl Channel> + 'a,
request: Request, request: Request,
buf: &'a [W], buf: &'a [W],
reg_addr: *mut u32, reg_addr: *mut W,
) -> impl Future<Output = ()> + 'a { ) -> impl Future<Output = ()> + 'a {
assert!(buf.len() <= 0xFFFF); assert!(buf.len() <= 0xFFFF);
unborrow!(channel); unborrow!(channel);
@ -136,7 +162,7 @@ mod transfers {
request: Request, request: Request,
repeated: W, repeated: W,
count: usize, count: usize,
reg_addr: *mut u32, reg_addr: *mut W,
) -> impl Future<Output = ()> + 'a { ) -> impl Future<Output = ()> + 'a {
unborrow!(channel); unborrow!(channel);

View file

@ -415,7 +415,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
w.set_tcie(true); w.set_tcie(true);
} }
}); });
let dst = regs.txdr().ptr() as *mut u32; let dst = regs.txdr().ptr() as *mut u8;
let ch = &mut self.tx_dma; let ch = &mut self.tx_dma;
let request = ch.request(); let request = ch.request();
@ -508,7 +508,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
w.set_rxdmaen(true); w.set_rxdmaen(true);
w.set_tcie(true); w.set_tcie(true);
}); });
let src = regs.rxdr().ptr() as *mut u32; let src = regs.rxdr().ptr() as *mut u8;
let ch = &mut self.rx_dma; let ch = &mut self.rx_dma;
let request = ch.request(); let request = ch.request();

View file

@ -77,7 +77,7 @@ impl<'d, T: Instance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
}); });
} }
let r = self.inner.regs(); let r = self.inner.regs();
let dst = r.dr().ptr() as *mut u32; let dst = r.dr().ptr() as *mut u8;
crate::dma::write(ch, request, buffer, dst).await; crate::dma::write(ch, request, buffer, dst).await;
Ok(()) Ok(())
} }
@ -94,7 +94,7 @@ impl<'d, T: Instance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
}); });
} }
let r = self.inner.regs(); let r = self.inner.regs();
let src = r.dr().ptr() as *mut u32; let src = r.dr().ptr() as *mut u8;
crate::dma::read(ch, request, src, buffer).await; crate::dma::read(ch, request, src, buffer).await;
Ok(()) Ok(())
} }

View file

@ -87,7 +87,7 @@ impl<'d, T: Instance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
}); });
} }
let r = self.inner.regs(); let r = self.inner.regs();
let dst = r.tdr().ptr() as *mut u32; let dst = r.tdr().ptr() as *mut u8;
crate::dma::write(ch, request, buffer, dst).await; crate::dma::write(ch, request, buffer, dst).await;
Ok(()) Ok(())
} }
@ -104,7 +104,7 @@ impl<'d, T: Instance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
}); });
} }
let r = self.inner.regs(); let r = self.inner.regs();
let src = r.rdr().ptr() as *mut u32; let src = r.rdr().ptr() as *mut u8;
crate::dma::read(ch, request, src, buffer).await; crate::dma::read(ch, request, src, buffer).await;
Ok(()) Ok(())