stm32: add some docs.
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
#![macro_use]
|
||||
//! Basic Direct Memory Acccess (BDMA)
|
||||
|
||||
use core::future::Future;
|
||||
use core::pin::Pin;
|
||||
@@ -17,6 +17,7 @@ use crate::interrupt::Priority;
|
||||
use crate::pac;
|
||||
use crate::pac::bdma::{regs, vals};
|
||||
|
||||
/// BDMA transfer options.
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
#[non_exhaustive]
|
||||
@@ -140,13 +141,17 @@ pub(crate) unsafe fn on_irq_inner(dma: pac::bdma::Dma, channel_num: usize, index
|
||||
STATE.ch_wakers[index].wake();
|
||||
}
|
||||
|
||||
/// DMA request type alias.
|
||||
#[cfg(any(bdma_v2, dmamux))]
|
||||
pub type Request = u8;
|
||||
/// DMA request type alias.
|
||||
#[cfg(not(any(bdma_v2, dmamux)))]
|
||||
pub type Request = ();
|
||||
|
||||
/// DMA channel.
|
||||
#[cfg(dmamux)]
|
||||
pub trait Channel: sealed::Channel + Peripheral<P = Self> + 'static + super::dmamux::MuxChannel {}
|
||||
/// DMA channel.
|
||||
#[cfg(not(dmamux))]
|
||||
pub trait Channel: sealed::Channel + Peripheral<P = Self> + 'static {}
|
||||
|
||||
@@ -161,12 +166,14 @@ pub(crate) mod sealed {
|
||||
}
|
||||
}
|
||||
|
||||
/// DMA transfer.
|
||||
#[must_use = "futures do nothing unless you `.await` or poll them"]
|
||||
pub struct Transfer<'a, C: Channel> {
|
||||
channel: PeripheralRef<'a, C>,
|
||||
}
|
||||
|
||||
impl<'a, C: Channel> Transfer<'a, C> {
|
||||
/// Create a new read DMA transfer (peripheral to memory).
|
||||
pub unsafe fn new_read<W: Word>(
|
||||
channel: impl Peripheral<P = C> + 'a,
|
||||
request: Request,
|
||||
@@ -177,6 +184,7 @@ impl<'a, C: Channel> Transfer<'a, C> {
|
||||
Self::new_read_raw(channel, request, peri_addr, buf, options)
|
||||
}
|
||||
|
||||
/// Create a new read DMA transfer (peripheral to memory), using raw pointers.
|
||||
pub unsafe fn new_read_raw<W: Word>(
|
||||
channel: impl Peripheral<P = C> + 'a,
|
||||
request: Request,
|
||||
@@ -202,6 +210,7 @@ impl<'a, C: Channel> Transfer<'a, C> {
|
||||
)
|
||||
}
|
||||
|
||||
/// Create a new write DMA transfer (memory to peripheral).
|
||||
pub unsafe fn new_write<W: Word>(
|
||||
channel: impl Peripheral<P = C> + 'a,
|
||||
request: Request,
|
||||
@@ -212,6 +221,7 @@ impl<'a, C: Channel> Transfer<'a, C> {
|
||||
Self::new_write_raw(channel, request, buf, peri_addr, options)
|
||||
}
|
||||
|
||||
/// Create a new write DMA transfer (memory to peripheral), using raw pointers.
|
||||
pub unsafe fn new_write_raw<W: Word>(
|
||||
channel: impl Peripheral<P = C> + 'a,
|
||||
request: Request,
|
||||
@@ -237,6 +247,7 @@ impl<'a, C: Channel> Transfer<'a, C> {
|
||||
)
|
||||
}
|
||||
|
||||
/// Create a new write DMA transfer (memory to peripheral), writing the same value repeatedly.
|
||||
pub unsafe fn new_write_repeated<W: Word>(
|
||||
channel: impl Peripheral<P = C> + 'a,
|
||||
request: Request,
|
||||
@@ -321,6 +332,9 @@ impl<'a, C: Channel> Transfer<'a, C> {
|
||||
});
|
||||
}
|
||||
|
||||
/// Request the transfer to stop.
|
||||
///
|
||||
/// This doesn't immediately stop the transfer, you have to wait until [`is_running`](Self::is_running) returns false.
|
||||
pub fn request_stop(&mut self) {
|
||||
let ch = self.channel.regs().ch(self.channel.num());
|
||||
|
||||
@@ -331,6 +345,10 @@ impl<'a, C: Channel> Transfer<'a, C> {
|
||||
});
|
||||
}
|
||||
|
||||
/// Return whether this transfer is still running.
|
||||
///
|
||||
/// If this returns `false`, it can be because either the transfer finished, or
|
||||
/// it was requested to stop early with [`request_stop`](Self::request_stop).
|
||||
pub fn is_running(&mut self) -> bool {
|
||||
let ch = self.channel.regs().ch(self.channel.num());
|
||||
let en = ch.cr().read().en();
|
||||
@@ -339,13 +357,15 @@ impl<'a, C: Channel> Transfer<'a, C> {
|
||||
en && (circular || !tcif)
|
||||
}
|
||||
|
||||
/// Gets the total remaining transfers for the channel
|
||||
/// Note: this will be zero for transfers that completed without cancellation.
|
||||
/// Get the total remaining transfers for the channel.
|
||||
///
|
||||
/// This will be zero for transfers that completed instead of being canceled with [`request_stop`](Self::request_stop).
|
||||
pub fn get_remaining_transfers(&self) -> u16 {
|
||||
let ch = self.channel.regs().ch(self.channel.num());
|
||||
ch.ndtr().read().ndt()
|
||||
}
|
||||
|
||||
/// Blocking wait until the transfer finishes.
|
||||
pub fn blocking_wait(mut self) {
|
||||
while self.is_running() {}
|
||||
self.request_stop();
|
||||
@@ -411,6 +431,7 @@ impl<'a, C: Channel> DmaCtrl for DmaCtrlImpl<'a, C> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Ringbuffer for reading data using DMA circular mode.
|
||||
pub struct ReadableRingBuffer<'a, C: Channel, W: Word> {
|
||||
cr: regs::Cr,
|
||||
channel: PeripheralRef<'a, C>,
|
||||
@@ -418,7 +439,8 @@ pub struct ReadableRingBuffer<'a, C: Channel, W: Word> {
|
||||
}
|
||||
|
||||
impl<'a, C: Channel, W: Word> ReadableRingBuffer<'a, C, W> {
|
||||
pub unsafe fn new_read(
|
||||
/// Create a new ring buffer.
|
||||
pub unsafe fn new(
|
||||
channel: impl Peripheral<P = C> + 'a,
|
||||
_request: Request,
|
||||
peri_addr: *mut W,
|
||||
@@ -473,11 +495,15 @@ impl<'a, C: Channel, W: Word> ReadableRingBuffer<'a, C, W> {
|
||||
this
|
||||
}
|
||||
|
||||
/// Start the ring buffer operation.
|
||||
///
|
||||
/// You must call this after creating it for it to work.
|
||||
pub fn start(&mut self) {
|
||||
let ch = self.channel.regs().ch(self.channel.num());
|
||||
ch.cr().write_value(self.cr)
|
||||
}
|
||||
|
||||
/// Clear all data in the ring buffer.
|
||||
pub fn clear(&mut self) {
|
||||
self.ringbuf.clear(&mut DmaCtrlImpl(self.channel.reborrow()));
|
||||
}
|
||||
@@ -509,10 +535,11 @@ impl<'a, C: Channel, W: Word> ReadableRingBuffer<'a, C, W> {
|
||||
}
|
||||
|
||||
/// The capacity of the ringbuffer.
|
||||
pub const fn cap(&self) -> usize {
|
||||
pub const fn capacity(&self) -> usize {
|
||||
self.ringbuf.cap()
|
||||
}
|
||||
|
||||
/// Set a waker to be woken when at least one byte is received.
|
||||
pub fn set_waker(&mut self, waker: &Waker) {
|
||||
DmaCtrlImpl(self.channel.reborrow()).set_waker(waker);
|
||||
}
|
||||
@@ -526,6 +553,9 @@ impl<'a, C: Channel, W: Word> ReadableRingBuffer<'a, C, W> {
|
||||
});
|
||||
}
|
||||
|
||||
/// Request DMA to stop.
|
||||
///
|
||||
/// This doesn't immediately stop the transfer, you have to wait until [`is_running`](Self::is_running) returns false.
|
||||
pub fn request_stop(&mut self) {
|
||||
let ch = self.channel.regs().ch(self.channel.num());
|
||||
|
||||
@@ -539,6 +569,10 @@ impl<'a, C: Channel, W: Word> ReadableRingBuffer<'a, C, W> {
|
||||
});
|
||||
}
|
||||
|
||||
/// Return whether DMA is still running.
|
||||
///
|
||||
/// If this returns `false`, it can be because either the transfer finished, or
|
||||
/// it was requested to stop early with [`request_stop`](Self::request_stop).
|
||||
pub fn is_running(&mut self) -> bool {
|
||||
let ch = self.channel.regs().ch(self.channel.num());
|
||||
ch.cr().read().en()
|
||||
@@ -555,6 +589,7 @@ impl<'a, C: Channel, W: Word> Drop for ReadableRingBuffer<'a, C, W> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Ringbuffer for writing data using DMA circular mode.
|
||||
pub struct WritableRingBuffer<'a, C: Channel, W: Word> {
|
||||
cr: regs::Cr,
|
||||
channel: PeripheralRef<'a, C>,
|
||||
@@ -562,7 +597,8 @@ pub struct WritableRingBuffer<'a, C: Channel, W: Word> {
|
||||
}
|
||||
|
||||
impl<'a, C: Channel, W: Word> WritableRingBuffer<'a, C, W> {
|
||||
pub unsafe fn new_write(
|
||||
/// Create a new ring buffer.
|
||||
pub unsafe fn new(
|
||||
channel: impl Peripheral<P = C> + 'a,
|
||||
_request: Request,
|
||||
peri_addr: *mut W,
|
||||
@@ -617,11 +653,15 @@ impl<'a, C: Channel, W: Word> WritableRingBuffer<'a, C, W> {
|
||||
this
|
||||
}
|
||||
|
||||
/// Start the ring buffer operation.
|
||||
///
|
||||
/// You must call this after creating it for it to work.
|
||||
pub fn start(&mut self) {
|
||||
let ch = self.channel.regs().ch(self.channel.num());
|
||||
ch.cr().write_value(self.cr)
|
||||
}
|
||||
|
||||
/// Clear all data in the ring buffer.
|
||||
pub fn clear(&mut self) {
|
||||
self.ringbuf.clear(&mut DmaCtrlImpl(self.channel.reborrow()));
|
||||
}
|
||||
@@ -640,10 +680,11 @@ impl<'a, C: Channel, W: Word> WritableRingBuffer<'a, C, W> {
|
||||
}
|
||||
|
||||
/// The capacity of the ringbuffer.
|
||||
pub const fn cap(&self) -> usize {
|
||||
pub const fn capacity(&self) -> usize {
|
||||
self.ringbuf.cap()
|
||||
}
|
||||
|
||||
/// Set a waker to be woken when at least one byte is sent.
|
||||
pub fn set_waker(&mut self, waker: &Waker) {
|
||||
DmaCtrlImpl(self.channel.reborrow()).set_waker(waker);
|
||||
}
|
||||
@@ -657,6 +698,9 @@ impl<'a, C: Channel, W: Word> WritableRingBuffer<'a, C, W> {
|
||||
});
|
||||
}
|
||||
|
||||
/// Request DMA to stop.
|
||||
///
|
||||
/// This doesn't immediately stop the transfer, you have to wait until [`is_running`](Self::is_running) returns false.
|
||||
pub fn request_stop(&mut self) {
|
||||
let ch = self.channel.regs().ch(self.channel.num());
|
||||
|
||||
@@ -670,6 +714,10 @@ impl<'a, C: Channel, W: Word> WritableRingBuffer<'a, C, W> {
|
||||
});
|
||||
}
|
||||
|
||||
/// Return whether DMA is still running.
|
||||
///
|
||||
/// If this returns `false`, it can be because either the transfer finished, or
|
||||
/// it was requested to stop early with [`request_stop`](Self::request_stop).
|
||||
pub fn is_running(&mut self) -> bool {
|
||||
let ch = self.channel.regs().ch(self.channel.num());
|
||||
ch.cr().read().en()
|
||||
|
||||
Reference in New Issue
Block a user