diff --git a/embassy-nrf/src/gpio.rs b/embassy-nrf/src/gpio.rs index 85977a80..a47fb835 100644 --- a/embassy-nrf/src/gpio.rs +++ b/embassy-nrf/src/gpio.rs @@ -50,19 +50,19 @@ impl<'d, T: Pin> Input<'d, T> { Self { pin } } - /// Test if current pin level is high. + /// Get whether the pin input level is high. #[inline] pub fn is_high(&mut self) -> bool { self.pin.is_high() } - /// Test if current pin level is low. + /// Get whether the pin input level is low. #[inline] pub fn is_low(&mut self) -> bool { self.pin.is_low() } - /// Returns current pin level + /// Get the pin input level. #[inline] pub fn get_level(&mut self) -> Level { self.pin.get_level() @@ -158,19 +158,19 @@ impl<'d, T: Pin> Output<'d, T> { self.pin.set_level(level) } - /// Is the output pin set as high? + /// Get whether the output level is set to high. #[inline] pub fn is_set_high(&mut self) -> bool { self.pin.is_set_high() } - /// Is the output pin set as low? + /// Get whether the output level is set to low. #[inline] pub fn is_set_low(&mut self) -> bool { self.pin.is_set_low() } - /// What level output is set to + /// Get the current output level. #[inline] pub fn get_output_level(&mut self) -> Level { self.pin.get_output_level() @@ -275,13 +275,13 @@ impl<'d, T: Pin> Flex<'d, T> { self.pin.conf().reset(); } - /// Test if current pin level is high. + /// Get whether the pin input level is high. #[inline] pub fn is_high(&mut self) -> bool { !self.is_low() } - /// Test if current pin level is low. + /// Get whether the pin input level is low. #[inline] pub fn is_low(&mut self) -> bool { self.ref_is_low() @@ -292,7 +292,7 @@ impl<'d, T: Pin> Flex<'d, T> { self.pin.block().in_.read().bits() & (1 << self.pin.pin()) == 0 } - /// Returns current pin level + /// Get the pin input level. #[inline] pub fn get_level(&mut self) -> Level { self.is_high().into() @@ -319,25 +319,24 @@ impl<'d, T: Pin> Flex<'d, T> { } } - /// Is the output pin set as high? + /// Get whether the output level is set to high. #[inline] pub fn is_set_high(&mut self) -> bool { !self.is_set_low() } - /// Is the output pin set as low? + /// Get whether the output level is set to low. #[inline] pub fn is_set_low(&mut self) -> bool { self.ref_is_set_low() } - /// Is the output pin set as low? #[inline] pub(crate) fn ref_is_set_low(&self) -> bool { self.pin.block().out.read().bits() & (1 << self.pin.pin()) == 0 } - /// What level output is set to + /// Get the current output level. #[inline] pub fn get_output_level(&mut self) -> Level { self.is_set_high().into() diff --git a/embassy-stm32/src/adc/mod.rs b/embassy-stm32/src/adc/mod.rs index dbe53c80..2e470662 100644 --- a/embassy-stm32/src/adc/mod.rs +++ b/embassy-stm32/src/adc/mod.rs @@ -1,3 +1,4 @@ +//! Analog to Digital (ADC) converter driver. #![macro_use] #[cfg(not(adc_f3_v2))] @@ -24,6 +25,7 @@ pub use sample_time::SampleTime; use crate::peripherals; +/// Analog to Digital driver. pub struct Adc<'d, T: Instance> { #[allow(unused)] adc: crate::PeripheralRef<'d, T>, @@ -75,12 +77,16 @@ pub(crate) mod sealed { } } +/// ADC instance. #[cfg(not(any(adc_f1, adc_v1, adc_v2, adc_v3, adc_v4, adc_f3, adc_f3_v1_1, adc_g0)))] pub trait Instance: sealed::Instance + crate::Peripheral
{} +/// ADC instance. #[cfg(any(adc_f1, adc_v1, adc_v2, adc_v3, adc_v4, adc_f3, adc_f3_v1_1, adc_g0))] pub trait Instance: sealed::Instance + crate::Peripheral
+ crate::rcc::RccPeripheral {}
+/// ADC pin.
pub trait AdcPin + 'd, delay: &mut impl DelayUs (&mut self, pin: &mut P) -> u16
where
P: AdcPin + 'd,
dma: impl Peripheral + 'd,
@@ -139,6 +152,7 @@ where
Self::new_inner(peri, dma, config, false, 0b00)
}
+ /// Create a new DCMI driver with 10 data bits.
pub fn new_10bit(
peri: impl Peripheral + 'd,
dma: impl Peripheral + 'd,
@@ -165,6 +179,7 @@ where
Self::new_inner(peri, dma, config, false, 0b01)
}
+ /// Create a new DCMI driver with 12 data bits.
pub fn new_12bit(
peri: impl Peripheral + 'd,
dma: impl Peripheral + 'd,
@@ -193,6 +208,7 @@ where
Self::new_inner(peri, dma, config, false, 0b10)
}
+ /// Create a new DCMI driver with 14 data bits.
pub fn new_14bit(
peri: impl Peripheral + 'd,
dma: impl Peripheral + 'd,
@@ -223,6 +239,7 @@ where
Self::new_inner(peri, dma, config, false, 0b11)
}
+ /// Create a new DCMI driver with 8 data bits, with embedded synchronization.
pub fn new_es_8bit(
peri: impl Peripheral + 'd,
dma: impl Peripheral + 'd,
@@ -245,6 +262,7 @@ where
Self::new_inner(peri, dma, config, true, 0b00)
}
+ /// Create a new DCMI driver with 10 data bits, with embedded synchronization.
pub fn new_es_10bit(
peri: impl Peripheral + 'd,
dma: impl Peripheral + 'd,
@@ -269,6 +287,7 @@ where
Self::new_inner(peri, dma, config, true, 0b01)
}
+ /// Create a new DCMI driver with 12 data bits, with embedded synchronization.
pub fn new_es_12bit(
peri: impl Peripheral + 'd,
dma: impl Peripheral + 'd,
@@ -295,6 +314,7 @@ where
Self::new_inner(peri, dma, config, true, 0b10)
}
+ /// Create a new DCMI driver with 14 data bits, with embedded synchronization.
pub fn new_es_14bit(
peri: impl Peripheral + 'd,
dma: impl Peripheral + 'd,
@@ -538,7 +558,9 @@ mod sealed {
}
}
+/// DCMI instance.
pub trait Instance: sealed::Instance + 'static {
+ /// Interrupt for this instance.
type Interrupt: interrupt::typelevel::Interrupt;
}
diff --git a/embassy-stm32/src/dma/bdma.rs b/embassy-stm32/src/dma/bdma.rs
index a7422f66..5102330c 100644
--- a/embassy-stm32/src/dma/bdma.rs
+++ b/embassy-stm32/src/dma/bdma.rs
@@ -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 + 'static + super::dmamux::MuxChannel {}
+/// DMA channel.
#[cfg(not(dmamux))]
pub trait Channel: sealed::Channel + Peripheral + '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 + '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 + '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 + '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 + '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 + '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 + '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 + '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()
diff --git a/embassy-stm32/src/dma/dma.rs b/embassy-stm32/src/dma/dma.rs
index cce0407c..64e492c1 100644
--- a/embassy-stm32/src/dma/dma.rs
+++ b/embassy-stm32/src/dma/dma.rs
@@ -16,6 +16,7 @@ use crate::interrupt::Priority;
use crate::pac::dma::{regs, vals};
use crate::{interrupt, pac};
+/// DMA transfer options.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[non_exhaustive]
@@ -69,6 +70,7 @@ impl From + 'static + super::dmamux::MuxChannel {}
+/// DMA channel.
#[cfg(not(dmamux))]
pub trait Channel: sealed::Channel + Peripheral + 'static {}
@@ -229,12 +237,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 + 'a,
request: Request,
@@ -245,6 +255,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 + 'a,
request: Request,
@@ -270,6 +281,7 @@ impl<'a, C: Channel> Transfer<'a, C> {
)
}
+ /// Create a new write DMA transfer (memory to peripheral).
pub unsafe fn new_write + 'a,
request: Request,
@@ -280,6 +292,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 + 'a,
request: Request,
@@ -305,6 +318,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 + 'a,
request: Request,
@@ -407,6 +421,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().st(self.channel.num());
@@ -417,6 +434,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().st(self.channel.num());
ch.cr().read().en()
@@ -429,6 +450,7 @@ impl<'a, C: Channel> Transfer<'a, C> {
ch.ndtr().read().ndt()
}
+ /// Blocking wait until the transfer finishes.
pub fn blocking_wait(mut self) {
while self.is_running() {}
@@ -465,12 +487,14 @@ impl<'a, C: Channel> Future for Transfer<'a, C> {
// ==================================
+/// Double-buffered DMA transfer.
pub struct DoubleBuffered<'a, C: Channel, W: Word> {
channel: PeripheralRef<'a, C>,
_phantom: PhantomData + 'a,
_request: Request,
@@ -554,25 +578,36 @@ impl<'a, C: Channel, W: Word> DoubleBuffered<'a, C, W> {
});
}
+ /// Set the first buffer address.
+ ///
+ /// You may call this while DMA is transferring the other buffer.
pub unsafe fn set_buffer0(&mut self, buffer: *mut W) {
let ch = self.channel.regs().st(self.channel.num());
ch.m0ar().write_value(buffer as _);
}
+ /// Set the second buffer address.
+ ///
+ /// You may call this while DMA is transferring the other buffer.
pub unsafe fn set_buffer1(&mut self, buffer: *mut W) {
let ch = self.channel.regs().st(self.channel.num());
ch.m1ar().write_value(buffer as _);
}
+ /// Returh whether buffer0 is accessible (i.e. whether DMA is transferring buffer1 now)
pub fn is_buffer0_accessible(&mut self) -> bool {
let ch = self.channel.regs().st(self.channel.num());
ch.cr().read().ct() == vals::Ct::MEMORY1
}
+ /// Set a waker to be woken when one of the buffers is being transferred.
pub fn set_waker(&mut self, waker: &Waker) {
STATE.ch_wakers[self.channel.index()].register(waker);
}
+ /// 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().st(self.channel.num());
@@ -583,6 +618,10 @@ impl<'a, C: Channel, W: Word> DoubleBuffered<'a, C, W> {
});
}
+ /// 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().st(self.channel.num());
ch.cr().read().en()
@@ -629,6 +668,7 @@ impl<'a, C: Channel> DmaCtrl for DmaCtrlImpl<'a, C> {
}
}
+/// Ringbuffer for receiving data using DMA circular mode.
pub struct ReadableRingBuffer<'a, C: Channel, W: Word> {
cr: regs::Cr,
channel: PeripheralRef<'a, C>,
@@ -636,7 +676,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 + 'a,
_request: Request,
peri_addr: *mut W,
@@ -706,11 +747,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().st(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()));
}
@@ -741,11 +786,12 @@ impl<'a, C: Channel, W: Word> ReadableRingBuffer<'a, C, W> {
.await
}
- // The capacity of the ringbuffer
- pub const fn cap(&self) -> usize {
+ /// The capacity of the ringbuffer
+ 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);
}
@@ -763,6 +809,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().st(self.channel.num());
@@ -774,6 +823,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().st(self.channel.num());
ch.cr().read().en()
@@ -790,6 +843,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>,
@@ -797,7 +851,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 + 'a,
_request: Request,
peri_addr: *mut W,
@@ -867,11 +922,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().st(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()));
}
@@ -889,11 +948,12 @@ impl<'a, C: Channel, W: Word> WritableRingBuffer<'a, C, W> {
.await
}
- // The capacity of the ringbuffer
- pub const fn cap(&self) -> usize {
+ /// The capacity of the ringbuffer
+ 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);
}
@@ -911,6 +971,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().st(self.channel.num());
@@ -922,6 +985,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().st(self.channel.num());
ch.cr().read().en()
diff --git a/embassy-stm32/src/dma/dmamux.rs b/embassy-stm32/src/dma/dmamux.rs
index 20601dc8..9cd49472 100644
--- a/embassy-stm32/src/dma/dmamux.rs
+++ b/embassy-stm32/src/dma/dmamux.rs
@@ -22,11 +22,15 @@ pub(crate) mod dmamux_sealed {
}
}
+/// DMAMUX1 instance.
pub struct DMAMUX1;
+/// DMAMUX2 instance.
#[cfg(stm32h7)]
pub struct DMAMUX2;
+/// DMAMUX channel trait.
pub trait MuxChannel: dmamux_sealed::MuxChannel {
+ /// DMAMUX instance this channel is on.
type Mux;
}
diff --git a/embassy-stm32/src/dma/mod.rs b/embassy-stm32/src/dma/mod.rs
index 29fced8f..fb40a4b5 100644
--- a/embassy-stm32/src/dma/mod.rs
+++ b/embassy-stm32/src/dma/mod.rs
@@ -39,6 +39,13 @@ enum Dir {
PeripheralToMemory,
}
+/// "No DMA" placeholder.
+///
+/// You may pass this in place of a real DMA channel when creating a driver
+/// to indicate it should not use DMA.
+///
+/// This often causes async functionality to not be available on the instance,
+/// leaving only blocking functionality.
pub struct NoDma;
impl_peripheral!(NoDma);
diff --git a/embassy-stm32/src/dma/word.rs b/embassy-stm32/src/dma/word.rs
index aef6e970..a72c4b7d 100644
--- a/embassy-stm32/src/dma/word.rs
+++ b/embassy-stm32/src/dma/word.rs
@@ -1,3 +1,6 @@
+//! DMA word sizes.
+
+#[allow(missing_docs)]
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum WordSize {
@@ -7,6 +10,7 @@ pub enum WordSize {
}
impl WordSize {
+ /// Amount of bytes of this word size.
pub fn bytes(&self) -> usize {
match self {
Self::OneByte => 1,
@@ -20,8 +24,13 @@ mod sealed {
pub trait Word {}
}
+/// DMA word trait.
+///
+/// This is implemented for u8, u16, u32, etc.
pub trait Word: sealed::Word + Default + Copy + 'static {
+ /// Word size
fn size() -> WordSize;
+ /// Amount of bits of this word size.
fn bits() -> usize;
}
@@ -40,6 +49,7 @@ macro_rules! impl_word {
($T:ident, $uX:ident, $bits:literal, $size:ident) => {
#[repr(transparent)]
#[derive(Copy, Clone, Default)]
+ #[doc = concat!(stringify!($T), " word size")]
pub struct $T(pub $uX);
impl_word!(_, $T, $bits, $size);
};
diff --git a/embassy-stm32/src/eth/generic_smi.rs b/embassy-stm32/src/eth/generic_smi.rs
index 1e1094a1..9c26e90f 100644
--- a/embassy-stm32/src/eth/generic_smi.rs
+++ b/embassy-stm32/src/eth/generic_smi.rs
@@ -102,6 +102,7 @@ unsafe impl PHY for GenericSMI {
/// Public functions for the PHY
impl GenericSMI {
+ /// Set the SMI polling interval.
#[cfg(feature = "time")]
pub fn set_poll_interval(&mut self, poll_interval: Duration) {
self.poll_interval = poll_interval
diff --git a/embassy-stm32/src/eth/mod.rs b/embassy-stm32/src/eth/mod.rs
index 556aadd7..dbf91eed 100644
--- a/embassy-stm32/src/eth/mod.rs
+++ b/embassy-stm32/src/eth/mod.rs
@@ -22,6 +22,14 @@ const RX_BUFFER_SIZE: usize = 1536;
#[derive(Copy, Clone)]
pub(crate) struct Packet + 'd,
@@ -237,6 +239,7 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> {
}
}
+/// Ethernet SMI driver.
pub struct EthernetStationManagement + 'd) -> Self {
Self { pin }
}
+ /// Get whether the pin is high.
pub fn is_high(&mut self) -> bool {
self.pin.is_high()
}
+ /// Get whether the pin is low.
pub fn is_low(&mut self) -> bool {
self.pin.is_low()
}
+ /// Get the pin level.
pub fn get_level(&mut self) -> Level {
self.pin.get_level()
}
- pub async fn wait_for_high<'a>(&'a mut self) {
+ /// Asynchronously wait until the pin is high.
+ ///
+ /// This returns immediately if the pin is already high.
+ pub async fn wait_for_high(&mut self) {
let fut = ExtiInputFuture::new(self.pin.pin.pin.pin(), self.pin.pin.pin.port(), true, false);
if self.is_high() {
return;
@@ -117,7 +130,10 @@ impl<'d, T: GpioPin> ExtiInput<'d, T> {
fut.await
}
- pub async fn wait_for_low<'a>(&'a mut self) {
+ /// Asynchronously wait until the pin is low.
+ ///
+ /// This returns immediately if the pin is already low.
+ pub async fn wait_for_low(&mut self) {
let fut = ExtiInputFuture::new(self.pin.pin.pin.pin(), self.pin.pin.pin.port(), false, true);
if self.is_low() {
return;
@@ -125,15 +141,22 @@ impl<'d, T: GpioPin> ExtiInput<'d, T> {
fut.await
}
- pub async fn wait_for_rising_edge<'a>(&'a mut self) {
+ /// Asynchronously wait until the pin sees a rising edge.
+ ///
+ /// If the pin is already high, it will wait for it to go low then back high.
+ pub async fn wait_for_rising_edge(&mut self) {
ExtiInputFuture::new(self.pin.pin.pin.pin(), self.pin.pin.pin.port(), true, false).await
}
- pub async fn wait_for_falling_edge<'a>(&'a mut self) {
+ /// Asynchronously wait until the pin sees a falling edge.
+ ///
+ /// If the pin is already low, it will wait for it to go high then back low.
+ pub async fn wait_for_falling_edge(&mut self) {
ExtiInputFuture::new(self.pin.pin.pin.pin(), self.pin.pin.pin.port(), false, true).await
}
- pub async fn wait_for_any_edge<'a>(&'a mut self) {
+ /// Asynchronously wait until the pin sees any edge (either rising or falling).
+ pub async fn wait_for_any_edge(&mut self) {
ExtiInputFuture::new(self.pin.pin.pin.pin(), self.pin.pin.pin.port(), true, true).await
}
}
@@ -284,6 +307,7 @@ macro_rules! foreach_exti_irq {
macro_rules! impl_irq {
($e:ident) => {
+ #[allow(non_snake_case)]
#[cfg(feature = "rt")]
#[interrupt]
unsafe fn $e() {
@@ -298,8 +322,16 @@ pub(crate) mod sealed {
pub trait Channel {}
}
+/// EXTI channel trait.
pub trait Channel: sealed::Channel + Sized {
+ /// Get the EXTI channel number.
fn number(&self) -> usize;
+
+ /// Type-erase (degrade) this channel into an `AnyChannel`.
+ ///
+ /// This converts EXTI channel singletons (`EXTI0`, `EXTI1`, ...), which
+ /// are all different types, into the same type. It is useful for
+ /// creating arrays of channels, or avoiding generics.
fn degrade(self) -> AnyChannel {
AnyChannel {
number: self.number() as u8,
@@ -307,9 +339,13 @@ pub trait Channel: sealed::Channel + Sized {
}
}
+/// Type-erased (degraded) EXTI channel.
+///
+/// This represents ownership over any EXTI channel, known at runtime.
pub struct AnyChannel {
number: u8,
}
+
impl_peripheral!(AnyChannel);
impl sealed::Channel for AnyChannel {}
impl Channel for AnyChannel {
diff --git a/embassy-stm32/src/flash/asynch.rs b/embassy-stm32/src/flash/asynch.rs
index eae40c7e..e3c6d4d6 100644
--- a/embassy-stm32/src/flash/asynch.rs
+++ b/embassy-stm32/src/flash/asynch.rs
@@ -59,7 +59,7 @@ impl embedded_storage_async::nor_flash::ReadNorFlash for Flash<'_, Async> {
const READ_SIZE: usize = super::READ_SIZE;
async fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> {
- self.read(offset, bytes)
+ self.blocking_read(offset, bytes)
}
fn capacity(&self) -> usize {
diff --git a/embassy-stm32/src/flash/common.rs b/embassy-stm32/src/flash/common.rs
index 8acad1c7..f8561edb 100644
--- a/embassy-stm32/src/flash/common.rs
+++ b/embassy-stm32/src/flash/common.rs
@@ -12,12 +12,14 @@ use super::{
use crate::peripherals::FLASH;
use crate::Peripheral;
+/// Internal flash memory driver.
pub struct Flash<'d, MODE = Async> {
pub(crate) inner: PeripheralRef<'d, FLASH>,
pub(crate) _mode: PhantomData + 'd) -> Self {
into_ref!(p);
@@ -29,15 +31,26 @@ impl<'d> Flash<'d, Blocking> {
}
impl<'d, MODE> Flash<'d, MODE> {
+ /// Split this flash driver into one instance per flash memory region.
+ ///
+ /// See module-level documentation for details on how memory regions work.
pub fn into_blocking_regions(self) -> FlashLayout<'d, Blocking> {
assert!(family::is_default_layout());
FlashLayout::new(self.inner)
}
- pub fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Error> {
+ /// Blocking read.
+ ///
+ /// NOTE: `offset` is an offset from the flash start, NOT an absolute address.
+ /// For example, to read address `0x0800_1234` you have to use offset `0x1234`.
+ pub fn blocking_read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Error> {
blocking_read(FLASH_BASE as u32, FLASH_SIZE as u32, offset, bytes)
}
+ /// Blocking write.
+ ///
+ /// NOTE: `offset` is an offset from the flash start, NOT an absolute address.
+ /// For example, to write address `0x0800_1234` you have to use offset `0x1234`.
pub fn blocking_write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Error> {
unsafe {
blocking_write(
@@ -50,6 +63,10 @@ impl<'d, MODE> Flash<'d, MODE> {
}
}
+ /// Blocking erase.
+ ///
+ /// NOTE: `from` and `to` are offsets from the flash start, NOT an absolute address.
+ /// For example, to erase address `0x0801_0000` you have to use offset `0x1_0000`.
pub fn blocking_erase(&mut self, from: u32, to: u32) -> Result<(), Error> {
unsafe { blocking_erase(FLASH_BASE as u32, from, to, erase_sector_unlocked) }
}
@@ -206,7 +223,7 @@ impl + 'd, pull: Pull) -> Self {
let mut pin = Flex::new(pin);
@@ -312,6 +330,11 @@ impl<'d, T: Pin> Input<'d, T> {
Self { pin }
}
+ /// Type-erase (degrade) this pin into an `AnyPin`.
+ ///
+ /// This converts pin singletons (`PA5`, `PB6`, ...), which
+ /// are all different types, into the same type. It is useful for
+ /// creating arrays of pins, or avoiding generics.
#[inline]
pub fn degrade(self) -> Input<'d, AnyPin> {
Input {
@@ -319,16 +342,19 @@ impl<'d, T: Pin> Input<'d, T> {
}
}
+ /// Get whether the pin input level is high.
#[inline]
pub fn is_high(&mut self) -> bool {
self.pin.is_high()
}
+ /// Get whether the pin input level is low.
#[inline]
pub fn is_low(&mut self) -> bool {
self.pin.is_low()
}
+ /// Get the current pin input level.
#[inline]
pub fn get_level(&mut self) -> Level {
self.pin.get_level()
@@ -339,7 +365,9 @@ impl<'d, T: Pin> Input<'d, T> {
#[derive(Debug, Eq, PartialEq, Copy, Clone)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum Level {
+ /// Low
Low,
+ /// High
High,
}
@@ -371,6 +399,7 @@ pub struct Output<'d, T: Pin> {
}
impl<'d, T: Pin> Output<'d, T> {
+ /// Create GPIO output driver for a [Pin] with the provided [Level] and [Speed] configuration.
#[inline]
pub fn new(pin: impl Peripheral + 'd, initial_output: Level, speed: Speed) -> Self {
let mut pin = Flex::new(pin);
@@ -382,6 +411,11 @@ impl<'d, T: Pin> Output<'d, T> {
Self { pin }
}
+ /// Type-erase (degrade) this pin into an `AnyPin`.
+ ///
+ /// This converts pin singletons (`PA5`, `PB6`, ...), which
+ /// are all different types, into the same type. It is useful for
+ /// creating arrays of pins, or avoiding generics.
#[inline]
pub fn degrade(self) -> Output<'d, AnyPin> {
Output {
@@ -442,6 +476,7 @@ pub struct OutputOpenDrain<'d, T: Pin> {
}
impl<'d, T: Pin> OutputOpenDrain<'d, T> {
+ /// Create a new GPIO open drain output driver for a [Pin] with the provided [Level] and [Speed], [Pull] configuration.
#[inline]
pub fn new(pin: impl Peripheral + 'd, initial_output: Level, speed: Speed, pull: Pull) -> Self {
let mut pin = Flex::new(pin);
@@ -455,6 +490,11 @@ impl<'d, T: Pin> OutputOpenDrain<'d, T> {
Self { pin }
}
+ /// Type-erase (degrade) this pin into an `AnyPin`.
+ ///
+ /// This converts pin singletons (`PA5`, `PB6`, ...), which
+ /// are all different types, into the same type. It is useful for
+ /// creating arrays of pins, or avoiding generics.
#[inline]
pub fn degrade(self) -> Output<'d, AnyPin> {
Output {
@@ -462,17 +502,19 @@ impl<'d, T: Pin> OutputOpenDrain<'d, T> {
}
}
+ /// Get whether the pin input level is high.
#[inline]
pub fn is_high(&mut self) -> bool {
!self.pin.is_low()
}
+ /// Get whether the pin input level is low.
#[inline]
pub fn is_low(&mut self) -> bool {
self.pin.is_low()
}
- /// Returns current pin level
+ /// Get the current pin input level.
#[inline]
pub fn get_level(&mut self) -> Level {
self.pin.get_level()
@@ -496,19 +538,19 @@ impl<'d, T: Pin> OutputOpenDrain<'d, T> {
self.pin.set_level(level);
}
- /// Is the output pin set as high?
+ /// Get whether the output level is set to high.
#[inline]
pub fn is_set_high(&mut self) -> bool {
self.pin.is_set_high()
}
- /// Is the output pin set as low?
+ /// Get whether the output level is set to low.
#[inline]
pub fn is_set_low(&mut self) -> bool {
self.pin.is_set_low()
}
- /// What level output is set to
+ /// Get the current output level.
#[inline]
pub fn get_output_level(&mut self) -> Level {
self.pin.get_output_level()
@@ -521,8 +563,11 @@ impl<'d, T: Pin> OutputOpenDrain<'d, T> {
}
}
+/// GPIO output type
pub enum OutputType {
+ /// Drive the pin both high or low.
PushPull,
+ /// Drive the pin low, or don't drive it at all if the output level is high.
OpenDrain,
}
@@ -535,6 +580,7 @@ impl From + Into + Into + Into