diff --git a/embassy-stm32/src/dma/gpdma.rs b/embassy-stm32/src/dma/gpdma.rs
index b061415eb..34b2426b9 100644
--- a/embassy-stm32/src/dma/gpdma.rs
+++ b/embassy-stm32/src/dma/gpdma.rs
@@ -16,6 +16,7 @@ use crate::interrupt::Priority;
use crate::pac;
use crate::pac::gpdma::vals;
+/// GPDMA transfer options.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[non_exhaustive]
@@ -113,10 +114,13 @@ pub(crate) unsafe fn on_irq_inner(dma: pac::gpdma::Gpdma, channel_num: usize, in
}
}
+/// DMA request type alias. (also known as DMA channel number in some chips)
pub type Request = u8;
+/// 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 {}
@@ -131,12 +135,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(
channel: impl Peripheral + 'a,
request: Request,
@@ -147,6 +153,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(
channel: impl Peripheral + 'a,
request: Request,
@@ -172,6 +179,7 @@ impl<'a, C: Channel> Transfer<'a, C> {
)
}
+ /// Create a new write DMA transfer (memory to peripheral).
pub unsafe fn new_write(
channel: impl Peripheral + 'a,
request: Request,
@@ -182,6 +190,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(
channel: impl Peripheral + 'a,
request: Request,
@@ -207,6 +216,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(
channel: impl Peripheral + 'a,
request: Request,
@@ -297,6 +307,9 @@ impl<'a, C: Channel> Transfer<'a, C> {
this
}
+ /// 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());
ch.cr().modify(|w| {
@@ -304,6 +317,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 sr = ch.sr().read();
@@ -317,6 +334,7 @@ impl<'a, C: Channel> Transfer<'a, C> {
ch.br1().read().bndt()
}
+ /// Blocking wait until the transfer finishes.
pub fn blocking_wait(mut self) {
while self.is_running() {}
diff --git a/embassy-stm32/src/hrtim/mod.rs b/embassy-stm32/src/hrtim/mod.rs
index 1e6626a58..faefaabbc 100644
--- a/embassy-stm32/src/hrtim/mod.rs
+++ b/embassy-stm32/src/hrtim/mod.rs
@@ -68,22 +68,22 @@ mod sealed {
pub trait AdvancedChannel: sealed::AdvancedChannel {}
/// HRTIM PWM pin.
-pub struct PwmPin<'d, Perip, Channel> {
+pub struct PwmPin<'d, T, C> {
_pin: PeripheralRef<'d, AnyPin>,
- phantom: PhantomData<(Perip, Channel)>,
+ phantom: PhantomData<(T, C)>,
}
/// HRTIM complementary PWM pin.
-pub struct ComplementaryPwmPin<'d, Perip, Channel> {
+pub struct ComplementaryPwmPin<'d, T, C> {
_pin: PeripheralRef<'d, AnyPin>,
- phantom: PhantomData<(Perip, Channel)>,
+ phantom: PhantomData<(T, C)>,
}
macro_rules! advanced_channel_impl {
($new_chx:ident, $channel:tt, $ch_num:expr, $pin_trait:ident, $complementary_pin_trait:ident) => {
- impl<'d, Perip: Instance> PwmPin<'d, Perip, $channel> {
+ impl<'d, T: Instance> PwmPin<'d, T, $channel> {
#[doc = concat!("Create a new ", stringify!($channel), " PWM pin instance.")]
- pub fn $new_chx(pin: impl Peripheral> + 'd) -> Self {
+ pub fn $new_chx(pin: impl Peripheral
> + 'd) -> Self {
into_ref!(pin);
critical_section::with(|_| {
pin.set_low();
@@ -98,9 +98,9 @@ macro_rules! advanced_channel_impl {
}
}
- impl<'d, Perip: Instance> ComplementaryPwmPin<'d, Perip, $channel> {
+ impl<'d, T: Instance> ComplementaryPwmPin<'d, T, $channel> {
#[doc = concat!("Create a new ", stringify!($channel), " complementary PWM pin instance.")]
- pub fn $new_chx(pin: impl Peripheral> + 'd) -> Self {
+ pub fn $new_chx(pin: impl Peripheral
> + 'd) -> Self {
into_ref!(pin);
critical_section::with(|_| {
pin.set_low();
diff --git a/embassy-stm32/src/ipcc.rs b/embassy-stm32/src/ipcc.rs
index 4006dee19..663a7f59d 100644
--- a/embassy-stm32/src/ipcc.rs
+++ b/embassy-stm32/src/ipcc.rs
@@ -1,3 +1,5 @@
+//! Inter-Process Communication Controller (IPCC)
+
use core::future::poll_fn;
use core::sync::atomic::{compiler_fence, Ordering};
use core::task::Poll;
@@ -41,6 +43,7 @@ impl interrupt::typelevel::Handler for Receive
}
}
+/// TX interrupt handler.
pub struct TransmitInterruptHandler {}
impl interrupt::typelevel::Handler for TransmitInterruptHandler {
@@ -72,6 +75,7 @@ impl interrupt::typelevel::Handler for Transmi
}
}
+/// IPCC config.
#[non_exhaustive]
#[derive(Clone, Copy, Default)]
pub struct Config {
@@ -79,6 +83,8 @@ pub struct Config {
// reserved for future use
}
+/// Channel.
+#[allow(missing_docs)]
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub enum IpccChannel {
@@ -90,9 +96,11 @@ pub enum IpccChannel {
Channel6 = 5,
}
+/// IPCC driver.
pub struct Ipcc;
impl Ipcc {
+ /// Enable IPCC.
pub fn enable(_config: Config) {
IPCC::enable_and_reset();
IPCC::set_cpu2(true);
diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs
index 5d9b4e6a0..207f7ed8f 100644
--- a/embassy-stm32/src/lib.rs
+++ b/embassy-stm32/src/lib.rs
@@ -1,5 +1,6 @@
#![cfg_attr(not(test), no_std)]
#![allow(async_fn_in_trait)]
+#![warn(missing_docs)]
//! ## Feature flags
#![doc = document_features::document_features!(feature_label = r#"{feature}
"#)]
@@ -79,6 +80,7 @@ pub(crate) mod _generated {
#![allow(dead_code)]
#![allow(unused_imports)]
#![allow(non_snake_case)]
+ #![allow(missing_docs)]
include!(concat!(env!("OUT_DIR"), "/_generated.rs"));
}
@@ -149,15 +151,33 @@ use crate::interrupt::Priority;
pub use crate::pac::NVIC_PRIO_BITS;
use crate::rcc::sealed::RccPeripheral;
+/// `embassy-stm32` global configuration.
#[non_exhaustive]
pub struct Config {
+ /// RCC config.
pub rcc: rcc::Config,
+
+ /// Enable debug during sleep.
+ ///
+ /// May incrase power consumption. Defaults to true.
#[cfg(dbgmcu)]
pub enable_debug_during_sleep: bool,
+
+ /// BDMA interrupt priority.
+ ///
+ /// Defaults to P0 (highest).
#[cfg(bdma)]
pub bdma_interrupt_priority: Priority,
+
+ /// DMA interrupt priority.
+ ///
+ /// Defaults to P0 (highest).
#[cfg(dma)]
pub dma_interrupt_priority: Priority,
+
+ /// GPDMA interrupt priority.
+ ///
+ /// Defaults to P0 (highest).
#[cfg(gpdma)]
pub gpdma_interrupt_priority: Priority,
}
@@ -178,7 +198,11 @@ impl Default for Config {
}
}
-/// Initialize embassy.
+/// Initialize the `embassy-stm32` HAL with the provided configuration.
+///
+/// This returns the peripheral singletons that can be used for creating drivers.
+///
+/// This should only be called once at startup, otherwise it panics.
pub fn init(config: Config) -> Peripherals {
critical_section::with(|cs| {
let p = Peripherals::take_with_cs(cs);
diff --git a/embassy-stm32/src/low_power.rs b/embassy-stm32/src/low_power.rs
index 20d8f9045..a41c40eba 100644
--- a/embassy-stm32/src/low_power.rs
+++ b/embassy-stm32/src/low_power.rs
@@ -1,50 +1,53 @@
-/// The STM32 line of microcontrollers support various deep-sleep modes which exploit clock-gating
-/// to reduce power consumption. `embassy-stm32` provides a low-power executor, [`Executor`] which
-/// can use knowledge of which peripherals are currently blocked upon to transparently and safely
-/// enter such low-power modes (currently, only `STOP2`) when idle.
-///
-/// The executor determines which peripherals are active by their RCC state; consequently,
-/// low-power states can only be entered if all peripherals have been `drop`'d. There are a few
-/// exceptions to this rule:
-///
-/// * `GPIO`
-/// * `RCC`
-///
-/// Since entering and leaving low-power modes typically incurs a significant latency, the
-/// low-power executor will only attempt to enter when the next timer event is at least
-/// [`time_driver::MIN_STOP_PAUSE`] in the future.
-///
-/// Currently there is no macro analogous to `embassy_executor::main` for this executor;
-/// consequently one must define their entrypoint manually. Moveover, you must relinquish control
-/// of the `RTC` peripheral to the executor. This will typically look like
-///
-/// ```rust,no_run
-/// use embassy_executor::Spawner;
-/// use embassy_stm32::low_power::Executor;
-/// use embassy_stm32::rtc::{Rtc, RtcConfig};
-/// use static_cell::make_static;
-///
-/// #[cortex_m_rt::entry]
-/// fn main() -> ! {
-/// Executor::take().run(|spawner| {
-/// unwrap!(spawner.spawn(async_main(spawner)));
-/// });
-/// }
-///
-/// #[embassy_executor::task]
-/// async fn async_main(spawner: Spawner) {
-/// // initialize the platform...
-/// let mut config = embassy_stm32::Config::default();
-/// let p = embassy_stm32::init(config);
-///
-/// // give the RTC to the executor...
-/// let mut rtc = Rtc::new(p.RTC, RtcConfig::default());
-/// let rtc = make_static!(rtc);
-/// embassy_stm32::low_power::stop_with_rtc(rtc);
-///
-/// // your application here...
-/// }
-/// ```
+//! Low-power support.
+//!
+//! The STM32 line of microcontrollers support various deep-sleep modes which exploit clock-gating
+//! to reduce power consumption. `embassy-stm32` provides a low-power executor, [`Executor`] which
+//! can use knowledge of which peripherals are currently blocked upon to transparently and safely
+//! enter such low-power modes (currently, only `STOP2`) when idle.
+//!
+//! The executor determines which peripherals are active by their RCC state; consequently,
+//! low-power states can only be entered if all peripherals have been `drop`'d. There are a few
+//! exceptions to this rule:
+//!
+//! * `GPIO`
+//! * `RCC`
+//!
+//! Since entering and leaving low-power modes typically incurs a significant latency, the
+//! low-power executor will only attempt to enter when the next timer event is at least
+//! [`time_driver::MIN_STOP_PAUSE`] in the future.
+//!
+//! Currently there is no macro analogous to `embassy_executor::main` for this executor;
+//! consequently one must define their entrypoint manually. Moveover, you must relinquish control
+//! of the `RTC` peripheral to the executor. This will typically look like
+//!
+//! ```rust,no_run
+//! use embassy_executor::Spawner;
+//! use embassy_stm32::low_power::Executor;
+//! use embassy_stm32::rtc::{Rtc, RtcConfig};
+//! use static_cell::make_static;
+//!
+//! #[cortex_m_rt::entry]
+//! fn main() -> ! {
+//! Executor::take().run(|spawner| {
+//! unwrap!(spawner.spawn(async_main(spawner)));
+//! });
+//! }
+//!
+//! #[embassy_executor::task]
+//! async fn async_main(spawner: Spawner) {
+//! // initialize the platform...
+//! let mut config = embassy_stm32::Config::default();
+//! let p = embassy_stm32::init(config);
+//!
+//! // give the RTC to the executor...
+//! let mut rtc = Rtc::new(p.RTC, RtcConfig::default());
+//! let rtc = make_static!(rtc);
+//! embassy_stm32::low_power::stop_with_rtc(rtc);
+//!
+//! // your application here...
+//! }
+//! ```
+
use core::arch::asm;
use core::marker::PhantomData;
use core::sync::atomic::{compiler_fence, Ordering};
@@ -64,6 +67,7 @@ static mut EXECUTOR: Option = None;
foreach_interrupt! {
(RTC, rtc, $block:ident, WKUP, $irq:ident) => {
#[interrupt]
+ #[allow(non_snake_case)]
unsafe fn $irq() {
EXECUTOR.as_mut().unwrap().on_wakeup_irq();
}
@@ -75,10 +79,15 @@ pub(crate) unsafe fn on_wakeup_irq() {
EXECUTOR.as_mut().unwrap().on_wakeup_irq();
}
+/// Configure STOP mode with RTC.
pub fn stop_with_rtc(rtc: &'static Rtc) {
unsafe { EXECUTOR.as_mut().unwrap() }.stop_with_rtc(rtc)
}
+/// Get whether the core is ready to enter the given stop mode.
+///
+/// This will return false if some peripheral driver is in use that
+/// prevents entering the given stop mode.
pub fn stop_ready(stop_mode: StopMode) -> bool {
match unsafe { EXECUTOR.as_mut().unwrap() }.stop_mode() {
Some(StopMode::Stop2) => true,
@@ -87,10 +96,13 @@ pub fn stop_ready(stop_mode: StopMode) -> bool {
}
}
+/// Available stop modes.
#[non_exhaustive]
#[derive(PartialEq)]
pub enum StopMode {
+ /// STOP 1
Stop1,
+ /// STOP 2
Stop2,
}
diff --git a/embassy-stm32/src/opamp.rs b/embassy-stm32/src/opamp.rs
index e1eb031d1..df8a78bcc 100644
--- a/embassy-stm32/src/opamp.rs
+++ b/embassy-stm32/src/opamp.rs
@@ -1,9 +1,12 @@
+//! Operational Amplifier (OPAMP)
#![macro_use]
use embassy_hal_internal::{into_ref, PeripheralRef};
use crate::Peripheral;
+/// Gain
+#[allow(missing_docs)]
#[derive(Clone, Copy)]
pub enum OpAmpGain {
Mul1,
@@ -13,6 +16,8 @@ pub enum OpAmpGain {
Mul16,
}
+/// Speed
+#[allow(missing_docs)]
#[derive(Clone, Copy)]
pub enum OpAmpSpeed {
Normal,
@@ -180,6 +185,7 @@ impl<'d, T: Instance> Drop for OpAmpInternalOutput<'d, T> {
}
}
+/// Opamp instance trait.
pub trait Instance: sealed::Instance + 'static {}
pub(crate) mod sealed {
@@ -198,8 +204,11 @@ pub(crate) mod sealed {
pub trait OutputPin {}
}
+/// Non-inverting pin trait.
pub trait NonInvertingPin: sealed::NonInvertingPin {}
+/// Inverting pin trait.
pub trait InvertingPin: sealed::InvertingPin {}
+/// Output pin trait.
pub trait OutputPin: sealed::OutputPin {}
macro_rules! impl_opamp_external_output {
diff --git a/embassy-stm32/src/rng.rs b/embassy-stm32/src/rng.rs
index 6ee89a922..ca641f352 100644
--- a/embassy-stm32/src/rng.rs
+++ b/embassy-stm32/src/rng.rs
@@ -80,6 +80,7 @@ impl<'d, T: Instance> Rng<'d, T> {
let _ = self.next_u32();
}
+ /// Reset the RNG.
#[cfg(not(rng_v1))]
pub fn reset(&mut self) {
T::regs().cr().write(|reg| {
diff --git a/embassy-stm32/src/sdmmc/mod.rs b/embassy-stm32/src/sdmmc/mod.rs
index ab142053a..10006baff 100644
--- a/embassy-stm32/src/sdmmc/mod.rs
+++ b/embassy-stm32/src/sdmmc/mod.rs
@@ -293,6 +293,7 @@ pub struct Sdmmc<'d, T: Instance, Dma: SdmmcDma = NoDma> {
#[cfg(sdmmc_v1)]
impl<'d, T: Instance, Dma: SdmmcDma> Sdmmc<'d, T, Dma> {
+ /// Create a new SDMMC driver, with 1 data lane.
pub fn new_1bit(
sdmmc: impl Peripheral + 'd,
_irq: impl interrupt::typelevel::Binding> + 'd,
@@ -327,6 +328,7 @@ impl<'d, T: Instance, Dma: SdmmcDma> Sdmmc<'d, T, Dma> {
)
}
+ /// Create a new SDMMC driver, with 4 data lanes.
pub fn new_4bit(
sdmmc: impl Peripheral + 'd,
_irq: impl interrupt::typelevel::Binding> + 'd,
diff --git a/embassy-stm32/src/timer/complementary_pwm.rs b/embassy-stm32/src/timer/complementary_pwm.rs
index e543a5b43..71d7110b5 100644
--- a/embassy-stm32/src/timer/complementary_pwm.rs
+++ b/embassy-stm32/src/timer/complementary_pwm.rs
@@ -13,15 +13,19 @@ use crate::gpio::{AnyPin, OutputType};
use crate::time::Hertz;
use crate::Peripheral;
-pub struct ComplementaryPwmPin<'d, Perip, Channel> {
+/// Complementary PWM pin wrapper.
+///
+/// This wraps a pin to make it usable with PWM.
+pub struct ComplementaryPwmPin<'d, T, C> {
_pin: PeripheralRef<'d, AnyPin>,
- phantom: PhantomData<(Perip, Channel)>,
+ phantom: PhantomData<(T, C)>,
}
macro_rules! complementary_channel_impl {
($new_chx:ident, $channel:ident, $pin_trait:ident) => {
- impl<'d, Perip: CaptureCompare16bitInstance> ComplementaryPwmPin<'d, Perip, $channel> {
- pub fn $new_chx(pin: impl Peripheral> + 'd, output_type: OutputType) -> Self {
+ impl<'d, T: CaptureCompare16bitInstance> ComplementaryPwmPin<'d, T, $channel> {
+ #[doc = concat!("Create a new ", stringify!($channel), " complementary PWM pin instance.")]
+ pub fn $new_chx(pin: impl Peripheral
> + 'd, output_type: OutputType) -> Self {
into_ref!(pin);
critical_section::with(|_| {
pin.set_low();
@@ -43,11 +47,13 @@ complementary_channel_impl!(new_ch2, Ch2, Channel2ComplementaryPin);
complementary_channel_impl!(new_ch3, Ch3, Channel3ComplementaryPin);
complementary_channel_impl!(new_ch4, Ch4, Channel4ComplementaryPin);
+/// PWM driver with support for standard and complementary outputs.
pub struct ComplementaryPwm<'d, T> {
inner: PeripheralRef<'d, T>,
}
impl<'d, T: ComplementaryCaptureCompare16bitInstance> ComplementaryPwm<'d, T> {
+ /// Create a new complementary PWM driver.
pub fn new(
tim: impl Peripheral
+ 'd,
_ch1: Option>,
@@ -72,7 +78,7 @@ impl<'d, T: ComplementaryCaptureCompare16bitInstance> ComplementaryPwm<'d, T> {
let mut this = Self { inner: tim };
this.inner.set_counting_mode(counting_mode);
- this.set_freq(freq);
+ this.set_frequency(freq);
this.inner.start();
this.inner.enable_outputs();
@@ -88,17 +94,23 @@ impl<'d, T: ComplementaryCaptureCompare16bitInstance> ComplementaryPwm<'d, T> {
this
}
+ /// Enable the given channel.
pub fn enable(&mut self, channel: Channel) {
self.inner.enable_channel(channel, true);
self.inner.enable_complementary_channel(channel, true);
}
+ /// Disable the given channel.
pub fn disable(&mut self, channel: Channel) {
self.inner.enable_complementary_channel(channel, false);
self.inner.enable_channel(channel, false);
}
- pub fn set_freq(&mut self, freq: Hertz) {
+ /// Set PWM frequency.
+ ///
+ /// Note: when you call this, the max duty value changes, so you will have to
+ /// call `set_duty` on all channels with the duty calculated based on the new max duty.
+ pub fn set_frequency(&mut self, freq: Hertz) {
let multiplier = if self.inner.get_counting_mode().is_center_aligned() {
2u8
} else {
@@ -107,15 +119,22 @@ impl<'d, T: ComplementaryCaptureCompare16bitInstance> ComplementaryPwm<'d, T> {
self.inner.set_frequency(freq * multiplier);
}
+ /// Get max duty value.
+ ///
+ /// This value depends on the configured frequency and the timer's clock rate from RCC.
pub fn get_max_duty(&self) -> u16 {
self.inner.get_max_compare_value() + 1
}
+ /// Set the duty for a given channel.
+ ///
+ /// The value ranges from 0 for 0% duty, to [`get_max_duty`](Self::get_max_duty) for 100% duty, both included.
pub fn set_duty(&mut self, channel: Channel, duty: u16) {
assert!(duty <= self.get_max_duty());
self.inner.set_compare_value(channel, duty)
}
+ /// Set the output polarity for a given channel.
pub fn set_polarity(&mut self, channel: Channel, polarity: OutputPolarity) {
self.inner.set_output_polarity(channel, polarity);
self.inner.set_complementary_output_polarity(channel, polarity);
diff --git a/embassy-stm32/src/timer/mod.rs b/embassy-stm32/src/timer/mod.rs
index 42ef878f7..74120adad 100644
--- a/embassy-stm32/src/timer/mod.rs
+++ b/embassy-stm32/src/timer/mod.rs
@@ -17,17 +17,27 @@ pub mod low_level {
}
pub(crate) mod sealed {
-
use super::*;
+
+ /// Basic 16-bit timer instance.
pub trait Basic16bitInstance: RccPeripheral {
+ /// Interrupt for this timer.
type Interrupt: interrupt::typelevel::Interrupt;
+ /// Get access to the basic 16bit timer registers.
+ ///
+ /// Note: This works even if the timer is more capable, because registers
+ /// for the less capable timers are a subset. This allows writing a driver
+ /// for a given set of capabilities, and having it transparently work with
+ /// more capable timers.
fn regs() -> crate::pac::timer::TimBasic;
+ /// Start the timer.
fn start(&mut self) {
Self::regs().cr1().modify(|r| r.set_cen(true));
}
+ /// Stop the timer.
fn stop(&mut self) {
Self::regs().cr1().modify(|r| r.set_cen(false));
}
@@ -63,6 +73,9 @@ pub(crate) mod sealed {
regs.cr1().modify(|r| r.set_urs(vals::Urs::ANYEVENT));
}
+ /// Clear update interrupt.
+ ///
+ /// Returns whether the update interrupt flag was set.
fn clear_update_interrupt(&mut self) -> bool {
let regs = Self::regs();
let sr = regs.sr().read();
@@ -76,14 +89,17 @@ pub(crate) mod sealed {
}
}
+ /// Enable/disable the update interrupt.
fn enable_update_interrupt(&mut self, enable: bool) {
Self::regs().dier().write(|r| r.set_uie(enable));
}
+ /// Enable/disable autoreload preload.
fn set_autoreload_preload(&mut self, enable: bool) {
Self::regs().cr1().modify(|r| r.set_arpe(enable));
}
+ /// Get the timer frequency.
fn get_frequency(&self) -> Hertz {
let timer_f = Self::frequency();
@@ -95,9 +111,17 @@ pub(crate) mod sealed {
}
}
+ /// Gneral-purpose 16-bit timer instance.
pub trait GeneralPurpose16bitInstance: Basic16bitInstance {
+ /// Get access to the general purpose 16bit timer registers.
+ ///
+ /// Note: This works even if the timer is more capable, because registers
+ /// for the less capable timers are a subset. This allows writing a driver
+ /// for a given set of capabilities, and having it transparently work with
+ /// more capable timers.
fn regs_gp16() -> crate::pac::timer::TimGp16;
+ /// Set counting mode.
fn set_counting_mode(&mut self, mode: CountingMode) {
let (cms, dir) = mode.into();
@@ -110,19 +134,29 @@ pub(crate) mod sealed {
Self::regs_gp16().cr1().modify(|r| r.set_cms(cms))
}
+ /// Get counting mode.
fn get_counting_mode(&self) -> CountingMode {
let cr1 = Self::regs_gp16().cr1().read();
(cr1.cms(), cr1.dir()).into()
}
+ /// Set clock divider.
fn set_clock_division(&mut self, ckd: vals::Ckd) {
Self::regs_gp16().cr1().modify(|r| r.set_ckd(ckd));
}
}
+ /// Gneral-purpose 32-bit timer instance.
pub trait GeneralPurpose32bitInstance: GeneralPurpose16bitInstance {
+ /// Get access to the general purpose 32bit timer registers.
+ ///
+ /// Note: This works even if the timer is more capable, because registers
+ /// for the less capable timers are a subset. This allows writing a driver
+ /// for a given set of capabilities, and having it transparently work with
+ /// more capable timers.
fn regs_gp32() -> crate::pac::timer::TimGp32;
+ /// Set timer frequency.
fn set_frequency(&mut self, frequency: Hertz) {
let f = frequency.0;
assert!(f > 0);
@@ -140,6 +174,7 @@ pub(crate) mod sealed {
regs.cr1().modify(|r| r.set_urs(vals::Urs::ANYEVENT));
}
+ /// Get timer frequency.
fn get_frequency(&self) -> Hertz {
let timer_f = Self::frequency();
@@ -151,141 +186,177 @@ pub(crate) mod sealed {
}
}
+ /// Advanced control timer instance.
pub trait AdvancedControlInstance: GeneralPurpose16bitInstance {
+ /// Get access to the advanced timer registers.
fn regs_advanced() -> crate::pac::timer::TimAdv;
}
+ /// Capture/Compare 16-bit timer instance.
pub trait CaptureCompare16bitInstance: GeneralPurpose16bitInstance {
+ /// Set input capture filter.
fn set_input_capture_filter(&mut self, channel: Channel, icf: vals::Icf) {
- let raw_channel = channel.raw();
+ let raw_channel = channel.index();
Self::regs_gp16()
.ccmr_input(raw_channel / 2)
.modify(|r| r.set_icf(raw_channel % 2, icf));
}
+ /// Clear input interrupt.
fn clear_input_interrupt(&mut self, channel: Channel) {
- Self::regs_gp16().sr().modify(|r| r.set_ccif(channel.raw(), false));
+ Self::regs_gp16().sr().modify(|r| r.set_ccif(channel.index(), false));
}
+ /// Enable input interrupt.
fn enable_input_interrupt(&mut self, channel: Channel, enable: bool) {
- Self::regs_gp16().dier().modify(|r| r.set_ccie(channel.raw(), enable));
+ Self::regs_gp16().dier().modify(|r| r.set_ccie(channel.index(), enable));
}
+
+ /// Set input capture prescaler.
fn set_input_capture_prescaler(&mut self, channel: Channel, factor: u8) {
- let raw_channel = channel.raw();
+ let raw_channel = channel.index();
Self::regs_gp16()
.ccmr_input(raw_channel / 2)
.modify(|r| r.set_icpsc(raw_channel % 2, factor));
}
+ /// Set input TI selection.
fn set_input_ti_selection(&mut self, channel: Channel, tisel: InputTISelection) {
- let raw_channel = channel.raw();
+ let raw_channel = channel.index();
Self::regs_gp16()
.ccmr_input(raw_channel / 2)
.modify(|r| r.set_ccs(raw_channel % 2, tisel.into()));
}
+
+ /// Set input capture mode.
fn set_input_capture_mode(&mut self, channel: Channel, mode: InputCaptureMode) {
Self::regs_gp16().ccer().modify(|r| match mode {
InputCaptureMode::Rising => {
- r.set_ccnp(channel.raw(), false);
- r.set_ccp(channel.raw(), false);
+ r.set_ccnp(channel.index(), false);
+ r.set_ccp(channel.index(), false);
}
InputCaptureMode::Falling => {
- r.set_ccnp(channel.raw(), false);
- r.set_ccp(channel.raw(), true);
+ r.set_ccnp(channel.index(), false);
+ r.set_ccp(channel.index(), true);
}
InputCaptureMode::BothEdges => {
- r.set_ccnp(channel.raw(), true);
- r.set_ccp(channel.raw(), true);
+ r.set_ccnp(channel.index(), true);
+ r.set_ccp(channel.index(), true);
}
});
}
+
+ /// Enable timer outputs.
fn enable_outputs(&mut self);
+ /// Set output compare mode.
fn set_output_compare_mode(&mut self, channel: Channel, mode: OutputCompareMode) {
let r = Self::regs_gp16();
- let raw_channel: usize = channel.raw();
+ let raw_channel: usize = channel.index();
r.ccmr_output(raw_channel / 2)
.modify(|w| w.set_ocm(raw_channel % 2, mode.into()));
}
+ /// Set output polarity.
fn set_output_polarity(&mut self, channel: Channel, polarity: OutputPolarity) {
Self::regs_gp16()
.ccer()
- .modify(|w| w.set_ccp(channel.raw(), polarity.into()));
+ .modify(|w| w.set_ccp(channel.index(), polarity.into()));
}
+ /// Enable/disable a channel.
fn enable_channel(&mut self, channel: Channel, enable: bool) {
- Self::regs_gp16().ccer().modify(|w| w.set_cce(channel.raw(), enable));
+ Self::regs_gp16().ccer().modify(|w| w.set_cce(channel.index(), enable));
}
+ /// Set compare value for a channel.
fn set_compare_value(&mut self, channel: Channel, value: u16) {
- Self::regs_gp16().ccr(channel.raw()).modify(|w| w.set_ccr(value));
+ Self::regs_gp16().ccr(channel.index()).modify(|w| w.set_ccr(value));
}
+ /// Get capture value for a channel.
fn get_capture_value(&mut self, channel: Channel) -> u16 {
- Self::regs_gp16().ccr(channel.raw()).read().ccr()
+ Self::regs_gp16().ccr(channel.index()).read().ccr()
}
+ /// Get max compare value. This depends on the timer frequency and the clock frequency from RCC.
fn get_max_compare_value(&self) -> u16 {
Self::regs_gp16().arr().read().arr()
}
+ /// Get compare value for a channel.
fn get_compare_value(&self, channel: Channel) -> u16 {
- Self::regs_gp16().ccr(channel.raw()).read().ccr()
+ Self::regs_gp16().ccr(channel.index()).read().ccr()
}
}
+ /// Capture/Compare 16-bit timer instance with complementary pin support.
pub trait ComplementaryCaptureCompare16bitInstance: CaptureCompare16bitInstance + AdvancedControlInstance {
+ /// Set complementary output polarity.
fn set_complementary_output_polarity(&mut self, channel: Channel, polarity: OutputPolarity) {
Self::regs_advanced()
.ccer()
- .modify(|w| w.set_ccnp(channel.raw(), polarity.into()));
+ .modify(|w| w.set_ccnp(channel.index(), polarity.into()));
}
+ /// Set clock divider for the dead time.
fn set_dead_time_clock_division(&mut self, value: vals::Ckd) {
Self::regs_advanced().cr1().modify(|w| w.set_ckd(value));
}
+ /// Set dead time, as a fraction of the max duty value.
fn set_dead_time_value(&mut self, value: u8) {
Self::regs_advanced().bdtr().modify(|w| w.set_dtg(value));
}
+ /// Enable/disable a complementary channel.
fn enable_complementary_channel(&mut self, channel: Channel, enable: bool) {
Self::regs_advanced()
.ccer()
- .modify(|w| w.set_ccne(channel.raw(), enable));
+ .modify(|w| w.set_ccne(channel.index(), enable));
}
}
+ /// Capture/Compare 32-bit timer instance.
pub trait CaptureCompare32bitInstance: GeneralPurpose32bitInstance + CaptureCompare16bitInstance {
+ /// Set comapre value for a channel.
fn set_compare_value(&mut self, channel: Channel, value: u32) {
- Self::regs_gp32().ccr(channel.raw()).modify(|w| w.set_ccr(value));
+ Self::regs_gp32().ccr(channel.index()).modify(|w| w.set_ccr(value));
}
+ /// Get capture value for a channel.
fn get_capture_value(&mut self, channel: Channel) -> u32 {
- Self::regs_gp32().ccr(channel.raw()).read().ccr()
+ Self::regs_gp32().ccr(channel.index()).read().ccr()
}
+ /// Get max compare value. This depends on the timer frequency and the clock frequency from RCC.
fn get_max_compare_value(&self) -> u32 {
Self::regs_gp32().arr().read().arr()
}
+ /// Get compare value for a channel.
fn get_compare_value(&self, channel: Channel) -> u32 {
- Self::regs_gp32().ccr(channel.raw()).read().ccr()
+ Self::regs_gp32().ccr(channel.index()).read().ccr()
}
}
}
+/// Timer channel.
#[derive(Clone, Copy)]
pub enum Channel {
+ /// Channel 1.
Ch1,
+ /// Channel 2.
Ch2,
+ /// Channel 3.
Ch3,
+ /// Channel 4.
Ch4,
}
impl Channel {
- pub fn raw(&self) -> usize {
+ /// Get the channel index (0..3)
+ pub fn index(&self) -> usize {
match self {
Channel::Ch1 => 0,
Channel::Ch2 => 1,
@@ -295,17 +366,25 @@ impl Channel {
}
}
+/// Input capture mode.
#[derive(Clone, Copy)]
pub enum InputCaptureMode {
+ /// Rising edge only.
Rising,
+ /// Falling edge only.
Falling,
+ /// Both rising or falling edges.
BothEdges,
}
+/// Input TI selection.
#[derive(Clone, Copy)]
pub enum InputTISelection {
+ /// Normal
Normal,
+ /// Alternate
Alternate,
+ /// TRC
TRC,
}
@@ -319,6 +398,7 @@ impl From for stm32_metapac::timer::vals::CcmrInputCcs {
}
}
+/// Timer counting mode.
#[repr(u8)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum CountingMode {
@@ -345,6 +425,7 @@ pub enum CountingMode {
}
impl CountingMode {
+ /// Return whether this mode is edge-aligned (up or down).
pub fn is_edge_aligned(&self) -> bool {
match self {
CountingMode::EdgeAlignedUp | CountingMode::EdgeAlignedDown => true,
@@ -352,6 +433,7 @@ impl CountingMode {
}
}
+ /// Return whether this mode is center-aligned.
pub fn is_center_aligned(&self) -> bool {
match self {
CountingMode::CenterAlignedDownInterrupts
@@ -386,16 +468,34 @@ impl From<(vals::Cms, vals::Dir)> for CountingMode {
}
}
+/// Output compare mode.
#[derive(Clone, Copy)]
pub enum OutputCompareMode {
+ /// The comparison between the output compare register TIMx_CCRx and
+ /// the counter TIMx_CNT has no effect on the outputs.
+ /// (this mode is used to generate a timing base).
Frozen,
+ /// Set channel to active level on match. OCxREF signal is forced high when the
+ /// counter TIMx_CNT matches the capture/compare register x (TIMx_CCRx).
ActiveOnMatch,
+ /// Set channel to inactive level on match. OCxREF signal is forced low when the
+ /// counter TIMx_CNT matches the capture/compare register x (TIMx_CCRx).
InactiveOnMatch,
+ /// Toggle - OCxREF toggles when TIMx_CNT=TIMx_CCRx.
Toggle,
+ /// Force inactive level - OCxREF is forced low.
ForceInactive,
+ /// Force active level - OCxREF is forced high.
ForceActive,
+ /// PWM mode 1 - In upcounting, channel is active as long as TIMx_CNTTIMx_CCRx else active (OCxREF=1).
PwmMode1,
+ /// PWM mode 2 - In upcounting, channel is inactive as long as
+ /// TIMx_CNTTIMx_CCRx else inactive.
PwmMode2,
+ // TODO: there's more modes here depending on the chip family.
}
impl From for stm32_metapac::timer::vals::Ocm {
@@ -413,9 +513,12 @@ impl From for stm32_metapac::timer::vals::Ocm {
}
}
+/// Timer output pin polarity.
#[derive(Clone, Copy)]
pub enum OutputPolarity {
+ /// Active high (higher duty value makes the pin spend more time high).
ActiveHigh,
+ /// Active low (higher duty value makes the pin spend more time low).
ActiveLow,
}
@@ -428,24 +531,31 @@ impl From for bool {
}
}
+/// Basic 16-bit timer instance.
pub trait Basic16bitInstance: sealed::Basic16bitInstance + 'static {}
+/// Gneral-purpose 16-bit timer instance.
pub trait GeneralPurpose16bitInstance: sealed::GeneralPurpose16bitInstance + 'static {}
+/// Gneral-purpose 32-bit timer instance.
pub trait GeneralPurpose32bitInstance: sealed::GeneralPurpose32bitInstance + 'static {}
+/// Advanced control timer instance.
pub trait AdvancedControlInstance: sealed::AdvancedControlInstance + 'static {}
+/// Capture/Compare 16-bit timer instance.
pub trait CaptureCompare16bitInstance:
sealed::CaptureCompare16bitInstance + GeneralPurpose16bitInstance + 'static
{
}
+/// Capture/Compare 16-bit timer instance with complementary pin support.
pub trait ComplementaryCaptureCompare16bitInstance:
sealed::ComplementaryCaptureCompare16bitInstance + AdvancedControlInstance + 'static
{
}
+/// Capture/Compare 32-bit timer instance.
pub trait CaptureCompare32bitInstance:
sealed::CaptureCompare32bitInstance + CaptureCompare16bitInstance + GeneralPurpose32bitInstance + 'static
{
diff --git a/embassy-stm32/src/timer/qei.rs b/embassy-stm32/src/timer/qei.rs
index 9f9379c20..59efb72ba 100644
--- a/embassy-stm32/src/timer/qei.rs
+++ b/embassy-stm32/src/timer/qei.rs
@@ -9,23 +9,30 @@ use crate::gpio::sealed::AFType;
use crate::gpio::AnyPin;
use crate::Peripheral;
+/// Counting direction
pub enum Direction {
+ /// Counting up.
Upcounting,
+ /// Counting down.
Downcounting,
}
-pub struct Ch1;
-pub struct Ch2;
+/// Channel 1 marker type.
+pub enum Ch1 {}
+/// Channel 2 marker type.
+pub enum Ch2 {}
-pub struct QeiPin<'d, Perip, Channel> {
+/// Wrapper for using a pin with QEI.
+pub struct QeiPin<'d, T, Channel> {
_pin: PeripheralRef<'d, AnyPin>,
- phantom: PhantomData<(Perip, Channel)>,
+ phantom: PhantomData<(T, Channel)>,
}
macro_rules! channel_impl {
($new_chx:ident, $channel:ident, $pin_trait:ident) => {
- impl<'d, Perip: CaptureCompare16bitInstance> QeiPin<'d, Perip, $channel> {
- pub fn $new_chx(pin: impl Peripheral> + 'd) -> Self {
+ impl<'d, T: CaptureCompare16bitInstance> QeiPin<'d, T, $channel> {
+ #[doc = concat!("Create a new ", stringify!($channel), " QEI pin instance.")]
+ pub fn $new_chx(pin: impl Peripheral
> + 'd) -> Self {
into_ref!(pin);
critical_section::with(|_| {
pin.set_low();
@@ -45,11 +52,13 @@ macro_rules! channel_impl {
channel_impl!(new_ch1, Ch1, Channel1Pin);
channel_impl!(new_ch2, Ch2, Channel2Pin);
+/// Quadrature decoder driver.
pub struct Qei<'d, T> {
_inner: PeripheralRef<'d, T>,
}
impl<'d, T: CaptureCompare16bitInstance> Qei<'d, T> {
+ /// Create a new quadrature decoder driver.
pub fn new(tim: impl Peripheral
+ 'd, _ch1: QeiPin<'d, T, Ch1>, _ch2: QeiPin<'d, T, Ch2>) -> Self {
Self::new_inner(tim)
}
@@ -84,6 +93,7 @@ impl<'d, T: CaptureCompare16bitInstance> Qei<'d, T> {
Self { _inner: tim }
}
+ /// Get direction.
pub fn read_direction(&self) -> Direction {
match T::regs_gp16().cr1().read().dir() {
vals::Dir::DOWN => Direction::Downcounting,
@@ -91,6 +101,7 @@ impl<'d, T: CaptureCompare16bitInstance> Qei<'d, T> {
}
}
+ /// Get count.
pub fn count(&self) -> u16 {
T::regs_gp16().cnt().read().cnt()
}
diff --git a/embassy-stm32/src/timer/simple_pwm.rs b/embassy-stm32/src/timer/simple_pwm.rs
index 234bbaff0..e6072aa15 100644
--- a/embassy-stm32/src/timer/simple_pwm.rs
+++ b/embassy-stm32/src/timer/simple_pwm.rs
@@ -11,20 +11,28 @@ use crate::gpio::{AnyPin, OutputType};
use crate::time::Hertz;
use crate::Peripheral;
-pub struct Ch1;
-pub struct Ch2;
-pub struct Ch3;
-pub struct Ch4;
+/// Channel 1 marker type.
+pub enum Ch1 {}
+/// Channel 2 marker type.
+pub enum Ch2 {}
+/// Channel 3 marker type.
+pub enum Ch3 {}
+/// Channel 4 marker type.
+pub enum Ch4 {}
-pub struct PwmPin<'d, Perip, Channel> {
+/// PWM pin wrapper.
+///
+/// This wraps a pin to make it usable with PWM.
+pub struct PwmPin<'d, T, C> {
_pin: PeripheralRef<'d, AnyPin>,
- phantom: PhantomData<(Perip, Channel)>,
+ phantom: PhantomData<(T, C)>,
}
macro_rules! channel_impl {
($new_chx:ident, $channel:ident, $pin_trait:ident) => {
- impl<'d, Perip: CaptureCompare16bitInstance> PwmPin<'d, Perip, $channel> {
- pub fn $new_chx(pin: impl Peripheral
> + 'd, output_type: OutputType) -> Self {
+ impl<'d, T: CaptureCompare16bitInstance> PwmPin<'d, T, $channel> {
+ #[doc = concat!("Create a new ", stringify!($channel), " PWM pin instance.")]
+ pub fn $new_chx(pin: impl Peripheral
> + 'd, output_type: OutputType) -> Self {
into_ref!(pin);
critical_section::with(|_| {
pin.set_low();
@@ -46,11 +54,13 @@ channel_impl!(new_ch2, Ch2, Channel2Pin);
channel_impl!(new_ch3, Ch3, Channel3Pin);
channel_impl!(new_ch4, Ch4, Channel4Pin);
+/// Simple PWM driver.
pub struct SimplePwm<'d, T> {
inner: PeripheralRef<'d, T>,
}
impl<'d, T: CaptureCompare16bitInstance> SimplePwm<'d, T> {
+ /// Create a new simple PWM driver.
pub fn new(
tim: impl Peripheral
+ 'd,
_ch1: Option>,
@@ -71,7 +81,7 @@ impl<'d, T: CaptureCompare16bitInstance> SimplePwm<'d, T> {
let mut this = Self { inner: tim };
this.inner.set_counting_mode(counting_mode);
- this.set_freq(freq);
+ this.set_frequency(freq);
this.inner.start();
this.inner.enable_outputs();
@@ -87,15 +97,21 @@ impl<'d, T: CaptureCompare16bitInstance> SimplePwm<'d, T> {
this
}
+ /// Enable the given channel.
pub fn enable(&mut self, channel: Channel) {
self.inner.enable_channel(channel, true);
}
+ /// Disable the given channel.
pub fn disable(&mut self, channel: Channel) {
self.inner.enable_channel(channel, false);
}
- pub fn set_freq(&mut self, freq: Hertz) {
+ /// Set PWM frequency.
+ ///
+ /// Note: when you call this, the max duty value changes, so you will have to
+ /// call `set_duty` on all channels with the duty calculated based on the new max duty.
+ pub fn set_frequency(&mut self, freq: Hertz) {
let multiplier = if self.inner.get_counting_mode().is_center_aligned() {
2u8
} else {
@@ -104,15 +120,22 @@ impl<'d, T: CaptureCompare16bitInstance> SimplePwm<'d, T> {
self.inner.set_frequency(freq * multiplier);
}
+ /// Get max duty value.
+ ///
+ /// This value depends on the configured frequency and the timer's clock rate from RCC.
pub fn get_max_duty(&self) -> u16 {
self.inner.get_max_compare_value() + 1
}
+ /// Set the duty for a given channel.
+ ///
+ /// The value ranges from 0 for 0% duty, to [`get_max_duty`](Self::get_max_duty) for 100% duty, both included.
pub fn set_duty(&mut self, channel: Channel, duty: u16) {
assert!(duty <= self.get_max_duty());
self.inner.set_compare_value(channel, duty)
}
+ /// Set the output polarity for a given channel.
pub fn set_polarity(&mut self, channel: Channel, polarity: OutputPolarity) {
self.inner.set_output_polarity(channel, polarity);
}
diff --git a/embassy-stm32/src/usb/mod.rs b/embassy-stm32/src/usb/mod.rs
index d0b289462..4debd4e54 100644
--- a/embassy-stm32/src/usb/mod.rs
+++ b/embassy-stm32/src/usb/mod.rs
@@ -1,3 +1,5 @@
+//! Universal Serial Bus (USB)
+
use crate::interrupt;
use crate::rcc::RccPeripheral;
@@ -10,7 +12,9 @@ pub(crate) mod sealed {
}
}
+/// USB instance trait.
pub trait Instance: sealed::Instance + RccPeripheral + 'static {
+ /// Interrupt for this USB instance.
type Interrupt: interrupt::typelevel::Interrupt;
}
diff --git a/embassy-stm32/src/usb/usb.rs b/embassy-stm32/src/usb/usb.rs
index 295dc9198..a8aebfe1f 100644
--- a/embassy-stm32/src/usb/usb.rs
+++ b/embassy-stm32/src/usb/usb.rs
@@ -244,6 +244,7 @@ struct EndpointData {
used_out: bool,
}
+/// USB driver.
pub struct Driver<'d, T: Instance> {
phantom: PhantomData<&'d mut T>,
alloc: [EndpointData; EP_COUNT],
@@ -251,6 +252,7 @@ pub struct Driver<'d, T: Instance> {
}
impl<'d, T: Instance> Driver<'d, T> {
+ /// Create a new USB driver.
pub fn new(
_usb: impl Peripheral + 'd,
_irq: impl interrupt::typelevel::Binding> + 'd,
@@ -465,6 +467,7 @@ impl<'d, T: Instance> driver::Driver<'d> for Driver<'d, T> {
}
}
+/// USB bus.
pub struct Bus<'d, T: Instance> {
phantom: PhantomData<&'d mut T>,
ep_types: [EpType; EP_COUNT - 1],
@@ -640,6 +643,7 @@ trait Dir {
fn waker(i: usize) -> &'static AtomicWaker;
}
+/// Marker type for the "IN" direction.
pub enum In {}
impl Dir for In {
fn dir() -> Direction {
@@ -652,6 +656,7 @@ impl Dir for In {
}
}
+/// Marker type for the "OUT" direction.
pub enum Out {}
impl Dir for Out {
fn dir() -> Direction {
@@ -664,6 +669,7 @@ impl Dir for Out {
}
}
+/// USB endpoint.
pub struct Endpoint<'d, T: Instance, D> {
_phantom: PhantomData<(&'d mut T, D)>,
info: EndpointInfo,
@@ -813,6 +819,7 @@ impl<'d, T: Instance> driver::EndpointIn for Endpoint<'d, T, In> {
}
}
+/// USB control pipe.
pub struct ControlPipe<'d, T: Instance> {
_phantom: PhantomData<&'d mut T>,
max_packet_size: u16,
diff --git a/embassy-stm32/src/usb_otg/mod.rs b/embassy-stm32/src/usb_otg/mod.rs
index 1abd031dd..0649e684b 100644
--- a/embassy-stm32/src/usb_otg/mod.rs
+++ b/embassy-stm32/src/usb_otg/mod.rs
@@ -20,7 +20,9 @@ pub(crate) mod sealed {
}
}
+/// USB OTG instance.
pub trait Instance: sealed::Instance + RccPeripheral {
+ /// Interrupt for this USB OTG instance.
type Interrupt: interrupt::typelevel::Interrupt;
}
diff --git a/embassy-stm32/src/usb_otg/usb.rs b/embassy-stm32/src/usb_otg/usb.rs
index ba77bfb16..190fb274f 100644
--- a/embassy-stm32/src/usb_otg/usb.rs
+++ b/embassy-stm32/src/usb_otg/usb.rs
@@ -204,6 +204,7 @@ pub enum PhyType {
}
impl PhyType {
+ /// Get whether this PHY is any of the internal types.
pub fn internal(&self) -> bool {
match self {
PhyType::InternalFullSpeed | PhyType::InternalHighSpeed => true,
@@ -211,6 +212,7 @@ impl PhyType {
}
}
+ /// Get whether this PHY is any of the high-speed types.
pub fn high_speed(&self) -> bool {
match self {
PhyType::InternalFullSpeed => false,
@@ -218,7 +220,7 @@ impl PhyType {
}
}
- pub fn to_dspd(&self) -> vals::Dspd {
+ fn to_dspd(&self) -> vals::Dspd {
match self {
PhyType::InternalFullSpeed => vals::Dspd::FULL_SPEED_INTERNAL,
PhyType::InternalHighSpeed => vals::Dspd::HIGH_SPEED,
@@ -230,6 +232,7 @@ impl PhyType {
/// Indicates that [State::ep_out_buffers] is empty.
const EP_OUT_BUFFER_EMPTY: u16 = u16::MAX;
+/// USB OTG driver state.
pub struct State {
/// Holds received SETUP packets. Available if [State::ep0_setup_ready] is true.
ep0_setup_data: UnsafeCell<[u8; 8]>,
@@ -247,6 +250,7 @@ unsafe impl Send for State {}
unsafe impl Sync for State {}
impl State {
+ /// Create a new State.
pub const fn new() -> Self {
const NEW_AW: AtomicWaker = AtomicWaker::new();
const NEW_BUF: UnsafeCell<*mut u8> = UnsafeCell::new(0 as _);
@@ -271,6 +275,7 @@ struct EndpointData {
fifo_size_words: u16,
}
+/// USB driver config.
#[non_exhaustive]
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub struct Config {
@@ -297,6 +302,7 @@ impl Default for Config {
}
}
+/// USB driver.
pub struct Driver<'d, T: Instance> {
config: Config,
phantom: PhantomData<&'d mut T>,
@@ -527,6 +533,7 @@ impl<'d, T: Instance> embassy_usb_driver::Driver<'d> for Driver<'d, T> {
}
}
+/// USB bus.
pub struct Bus<'d, T: Instance> {
config: Config,
phantom: PhantomData<&'d mut T>,
@@ -1092,6 +1099,7 @@ trait Dir {
fn dir() -> Direction;
}
+/// Marker type for the "IN" direction.
pub enum In {}
impl Dir for In {
fn dir() -> Direction {
@@ -1099,6 +1107,7 @@ impl Dir for In {
}
}
+/// Marker type for the "OUT" direction.
pub enum Out {}
impl Dir for Out {
fn dir() -> Direction {
@@ -1106,6 +1115,7 @@ impl Dir for Out {
}
}
+/// USB endpoint.
pub struct Endpoint<'d, T: Instance, D> {
_phantom: PhantomData<(&'d mut T, D)>,
info: EndpointInfo,
@@ -1299,6 +1309,7 @@ impl<'d, T: Instance> embassy_usb_driver::EndpointIn for Endpoint<'d, T, In> {
}
}
+/// USB control pipe.
pub struct ControlPipe<'d, T: Instance> {
_phantom: PhantomData<&'d mut T>,
max_packet_size: u16,
diff --git a/embassy-stm32/src/wdg/mod.rs b/embassy-stm32/src/wdg/mod.rs
index 5751a9ff3..dc701ef64 100644
--- a/embassy-stm32/src/wdg/mod.rs
+++ b/embassy-stm32/src/wdg/mod.rs
@@ -6,6 +6,7 @@ use stm32_metapac::iwdg::vals::{Key, Pr};
use crate::rcc::LSI_FREQ;
+/// Independent watchdog (IWDG) driver.
pub struct IndependentWatchdog<'d, T: Instance> {
wdg: PhantomData<&'d mut T>,
}
@@ -64,10 +65,12 @@ impl<'d, T: Instance> IndependentWatchdog<'d, T> {
IndependentWatchdog { wdg: PhantomData }
}
+ /// Unleash (start) the watchdog.
pub fn unleash(&mut self) {
T::regs().kr().write(|w| w.set_key(Key::START));
}
+ /// Pet (reload, refresh) the watchdog.
pub fn pet(&mut self) {
T::regs().kr().write(|w| w.set_key(Key::RESET));
}
@@ -79,6 +82,7 @@ mod sealed {
}
}
+/// IWDG instance trait.
pub trait Instance: sealed::Instance {}
foreach_peripheral!(
diff --git a/examples/stm32f4/src/bin/ws2812_pwm_dma.rs b/examples/stm32f4/src/bin/ws2812_pwm_dma.rs
index 52cc665c7..39f5d3421 100644
--- a/examples/stm32f4/src/bin/ws2812_pwm_dma.rs
+++ b/examples/stm32f4/src/bin/ws2812_pwm_dma.rs
@@ -110,7 +110,7 @@ async fn main(_spawner: Spawner) {
&mut dp.DMA1_CH2,
5,
color_list[color_list_index],
- pac::TIM3.ccr(pwm_channel.raw()).as_ptr() as *mut _,
+ pac::TIM3.ccr(pwm_channel.index()).as_ptr() as *mut _,
dma_transfer_option,
)
.await;
diff --git a/examples/stm32h7/src/bin/low_level_timer_api.rs b/examples/stm32h7/src/bin/low_level_timer_api.rs
index e0be495d1..394ed3281 100644
--- a/examples/stm32h7/src/bin/low_level_timer_api.rs
+++ b/examples/stm32h7/src/bin/low_level_timer_api.rs
@@ -85,7 +85,7 @@ impl<'d, T: CaptureCompare32bitInstance> SimplePwm32<'d, T> {
let mut this = Self { inner: tim };
- this.set_freq(freq);
+ this.set_frequency(freq);
this.inner.start();
let r = T::regs_gp32();
@@ -102,14 +102,14 @@ impl<'d, T: CaptureCompare32bitInstance> SimplePwm32<'d, T> {
}
pub fn enable(&mut self, channel: Channel) {
- T::regs_gp32().ccer().modify(|w| w.set_cce(channel.raw(), true));
+ T::regs_gp32().ccer().modify(|w| w.set_cce(channel.index(), true));
}
pub fn disable(&mut self, channel: Channel) {
- T::regs_gp32().ccer().modify(|w| w.set_cce(channel.raw(), false));
+ T::regs_gp32().ccer().modify(|w| w.set_cce(channel.index(), false));
}
- pub fn set_freq(&mut self, freq: Hertz) {
+ pub fn set_frequency(&mut self, freq: Hertz) {
::set_frequency(&mut self.inner, freq);
}
@@ -119,6 +119,6 @@ impl<'d, T: CaptureCompare32bitInstance> SimplePwm32<'d, T> {
pub fn set_duty(&mut self, channel: Channel, duty: u32) {
defmt::assert!(duty < self.get_max_duty());
- T::regs_gp32().ccr(channel.raw()).modify(|w| w.set_ccr(duty))
+ T::regs_gp32().ccr(channel.index()).modify(|w| w.set_ccr(duty))
}
}