From 7f5526a9b18ab773da958eb33cb0eb769039c0e5 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Mon, 18 Dec 2023 19:11:13 +0100 Subject: [PATCH] stm32: more docs. --- embassy-stm32/src/adc/mod.rs | 1 + embassy-stm32/src/crc/v1.rs | 4 +++ embassy-stm32/src/dma/mod.rs | 2 ++ embassy-stm32/src/eth/v1/mod.rs | 2 ++ embassy-stm32/src/flash/asynch.rs | 17 ++++++++++ embassy-stm32/src/flash/f4.rs | 2 +- embassy-stm32/src/fmc.rs | 4 +++ embassy-stm32/src/gpio.rs | 2 ++ embassy-stm32/src/i2c/v1.rs | 6 ++++ embassy-stm32/src/i2s.rs | 35 +++++++++++++++++--- embassy-stm32/src/rcc/mod.rs | 3 ++ embassy-stm32/src/rng.rs | 15 ++++++++- embassy-stm32/src/rtc/datetime.rs | 12 +++++-- embassy-stm32/src/rtc/mod.rs | 12 ++++--- embassy-stm32/src/timer/complementary_pwm.rs | 2 ++ embassy-stm32/src/timer/mod.rs | 3 ++ embassy-stm32/src/timer/qei.rs | 2 ++ embassy-stm32/src/timer/simple_pwm.rs | 2 ++ 18 files changed, 112 insertions(+), 14 deletions(-) diff --git a/embassy-stm32/src/adc/mod.rs b/embassy-stm32/src/adc/mod.rs index 2e470662..ff523ca3 100644 --- a/embassy-stm32/src/adc/mod.rs +++ b/embassy-stm32/src/adc/mod.rs @@ -1,5 +1,6 @@ //! Analog to Digital (ADC) converter driver. #![macro_use] +#![allow(missing_docs)] // TODO #[cfg(not(adc_f3_v2))] #[cfg_attr(adc_f1, path = "f1.rs")] diff --git a/embassy-stm32/src/crc/v1.rs b/embassy-stm32/src/crc/v1.rs index c0f58083..0166ab81 100644 --- a/embassy-stm32/src/crc/v1.rs +++ b/embassy-stm32/src/crc/v1.rs @@ -5,6 +5,7 @@ use crate::peripherals::CRC; use crate::rcc::sealed::RccPeripheral; use crate::Peripheral; +/// CRC driver. pub struct Crc<'d> { _peri: PeripheralRef<'d, CRC>, } @@ -34,6 +35,7 @@ impl<'d> Crc<'d> { PAC_CRC.dr().write_value(word); self.read() } + /// Feed a slice of words to the peripheral and return the result. pub fn feed_words(&mut self, words: &[u32]) -> u32 { for word in words { @@ -42,6 +44,8 @@ impl<'d> Crc<'d> { self.read() } + + /// Read the CRC result value. pub fn read(&self) -> u32 { PAC_CRC.dr().read() } diff --git a/embassy-stm32/src/dma/mod.rs b/embassy-stm32/src/dma/mod.rs index fb40a4b5..38945ac3 100644 --- a/embassy-stm32/src/dma/mod.rs +++ b/embassy-stm32/src/dma/mod.rs @@ -1,3 +1,5 @@ +//! Direct Memory Access (DMA) + #[cfg(dma)] pub(crate) mod dma; #[cfg(dma)] diff --git a/embassy-stm32/src/eth/v1/mod.rs b/embassy-stm32/src/eth/v1/mod.rs index 13e53f68..2ce5b392 100644 --- a/embassy-stm32/src/eth/v1/mod.rs +++ b/embassy-stm32/src/eth/v1/mod.rs @@ -43,6 +43,7 @@ impl interrupt::typelevel::Handler for InterruptHandl } } +/// Ethernet driver. pub struct Ethernet<'d, T: Instance, P: PHY> { _peri: PeripheralRef<'d, T>, pub(crate) tx: TDesRing<'d>, @@ -266,6 +267,7 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> { } } +/// Ethernet station management interface. pub struct EthernetStationManagement { peri: PhantomData, clock_range: Cr, diff --git a/embassy-stm32/src/flash/asynch.rs b/embassy-stm32/src/flash/asynch.rs index e3c6d4d6..97eaece8 100644 --- a/embassy-stm32/src/flash/asynch.rs +++ b/embassy-stm32/src/flash/asynch.rs @@ -17,6 +17,7 @@ use crate::{interrupt, Peripheral}; pub(super) static REGION_ACCESS: Mutex = Mutex::new(()); impl<'d> Flash<'d, Async> { + /// Create a new flash driver with async capabilities. pub fn new( p: impl Peripheral

+ 'd, _irq: impl interrupt::typelevel::Binding + 'd, @@ -32,15 +33,26 @@ impl<'d> Flash<'d, Async> { } } + /// 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_regions(self) -> FlashLayout<'d, Async> { assert!(family::is_default_layout()); FlashLayout::new(self.inner) } + /// Async 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 async fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Error> { unsafe { write_chunked(FLASH_BASE as u32, FLASH_SIZE as u32, offset, bytes).await } } + /// Async 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 async fn erase(&mut self, from: u32, to: u32) -> Result<(), Error> { unsafe { erase_sectored(FLASH_BASE as u32, from, to).await } } @@ -141,15 +153,20 @@ pub(super) async unsafe fn erase_sectored(base: u32, from: u32, to: u32) -> Resu foreach_flash_region! { ($type_name:ident, $write_size:literal, $erase_size:literal) => { impl crate::_generated::flash_regions::$type_name<'_, Async> { + /// Async read. + /// + /// Note: reading from flash can't actually block, so this is the same as `blocking_read`. pub async fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Error> { blocking_read(self.0.base, self.0.size, offset, bytes) } + /// Async write. pub async fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Error> { let _guard = REGION_ACCESS.lock().await; unsafe { write_chunked(self.0.base, self.0.size, offset, bytes).await } } + /// Async erase. pub async fn erase(&mut self, from: u32, to: u32) -> Result<(), Error> { let _guard = REGION_ACCESS.lock().await; unsafe { erase_sectored(self.0.base, from, to).await } diff --git a/embassy-stm32/src/flash/f4.rs b/embassy-stm32/src/flash/f4.rs index f442c589..2671dfb0 100644 --- a/embassy-stm32/src/flash/f4.rs +++ b/embassy-stm32/src/flash/f4.rs @@ -9,7 +9,7 @@ use pac::FLASH_SIZE; use super::{FlashBank, FlashRegion, FlashSector, FLASH_REGIONS, WRITE_SIZE}; use crate::flash::Error; use crate::pac; - +#[allow(missing_docs)] // TODO #[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f469, stm32f479))] mod alt_regions { use core::marker::PhantomData; diff --git a/embassy-stm32/src/fmc.rs b/embassy-stm32/src/fmc.rs index dd0d2721..23ac82f6 100644 --- a/embassy-stm32/src/fmc.rs +++ b/embassy-stm32/src/fmc.rs @@ -6,6 +6,7 @@ use crate::gpio::sealed::AFType; use crate::gpio::{Pull, Speed}; use crate::Peripheral; +/// FMC driver pub struct Fmc<'d, T: Instance> { peri: PhantomData<&'d mut T>, } @@ -38,6 +39,7 @@ where T::REGS.bcr1().modify(|r| r.set_fmcen(true)); } + /// Get the kernel clock currently in use for this FMC instance. pub fn source_clock_hz(&self) -> u32 { ::frequency().0 } @@ -85,6 +87,7 @@ macro_rules! fmc_sdram_constructor { nbl: [$(($nbl_pin_name:ident: $nbl_signal:ident)),*], ctrl: [$(($ctrl_pin_name:ident: $ctrl_signal:ident)),*] )) => { + /// Create a new FMC instance. pub fn $name( _instance: impl Peripheral

+ 'd, $($addr_pin_name: impl Peripheral

> + 'd),*, @@ -199,6 +202,7 @@ pub(crate) mod sealed { } } +/// FMC instance trait. pub trait Instance: sealed::Instance + 'static {} foreach_peripheral!( diff --git a/embassy-stm32/src/gpio.rs b/embassy-stm32/src/gpio.rs index 083b3237..c300a079 100644 --- a/embassy-stm32/src/gpio.rs +++ b/embassy-stm32/src/gpio.rs @@ -1,3 +1,5 @@ +//! General-purpose Input/Output (GPIO) + #![macro_use] use core::convert::Infallible; diff --git a/embassy-stm32/src/i2c/v1.rs b/embassy-stm32/src/i2c/v1.rs index 84802d12..df5b44c2 100644 --- a/embassy-stm32/src/i2c/v1.rs +++ b/embassy-stm32/src/i2c/v1.rs @@ -247,10 +247,12 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { } } + /// Blocking read. pub fn blocking_read(&mut self, addr: u8, read: &mut [u8]) -> Result<(), Error> { self.blocking_read_timeout(addr, read, self.timeout()) } + /// Blocking write. pub fn blocking_write(&mut self, addr: u8, write: &[u8]) -> Result<(), Error> { let timeout = self.timeout(); @@ -266,6 +268,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { Ok(()) } + /// Blocking write, restart, read. pub fn blocking_write_read(&mut self, addr: u8, write: &[u8], read: &mut [u8]) -> Result<(), Error> { let timeout = self.timeout(); @@ -435,6 +438,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { Ok(()) } + /// Write. pub async fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Error> where TXDMA: crate::i2c::TxDma, @@ -457,6 +461,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { Ok(()) } + /// Read. pub async fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Error> where RXDMA: crate::i2c::RxDma, @@ -616,6 +621,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { Ok(()) } + /// Write, restart, read. pub async fn write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Error> where RXDMA: crate::i2c::RxDma, diff --git a/embassy-stm32/src/i2s.rs b/embassy-stm32/src/i2s.rs index 67d40c47..372c86db 100644 --- a/embassy-stm32/src/i2s.rs +++ b/embassy-stm32/src/i2s.rs @@ -8,30 +8,42 @@ use crate::spi::{Config as SpiConfig, *}; use crate::time::Hertz; use crate::{Peripheral, PeripheralRef}; +/// I2S mode #[derive(Copy, Clone)] pub enum Mode { + /// Master mode Master, + /// Slave mode Slave, } +/// I2S function #[derive(Copy, Clone)] pub enum Function { + /// Transmit audio data Transmit, + /// Receive audio data Receive, } +/// I2C standard #[derive(Copy, Clone)] pub enum Standard { + /// Philips Philips, + /// Most significant bit first. MsbFirst, + /// Least significant bit first. LsbFirst, + /// PCM with long sync. PcmLongSync, + /// PCM with short sync. PcmShortSync, } impl Standard { #[cfg(any(spi_v1, spi_f1))] - pub const fn i2sstd(&self) -> vals::I2sstd { + const fn i2sstd(&self) -> vals::I2sstd { match self { Standard::Philips => vals::I2sstd::PHILIPS, Standard::MsbFirst => vals::I2sstd::MSB, @@ -42,7 +54,7 @@ impl Standard { } #[cfg(any(spi_v1, spi_f1))] - pub const fn pcmsync(&self) -> vals::Pcmsync { + const fn pcmsync(&self) -> vals::Pcmsync { match self { Standard::PcmLongSync => vals::Pcmsync::LONG, _ => vals::Pcmsync::SHORT, @@ -50,6 +62,7 @@ impl Standard { } } +/// I2S data format. #[derive(Copy, Clone)] pub enum Format { /// 16 bit data length on 16 bit wide channel @@ -64,7 +77,7 @@ pub enum Format { impl Format { #[cfg(any(spi_v1, spi_f1))] - pub const fn datlen(&self) -> vals::Datlen { + const fn datlen(&self) -> vals::Datlen { match self { Format::Data16Channel16 => vals::Datlen::SIXTEENBIT, Format::Data16Channel32 => vals::Datlen::SIXTEENBIT, @@ -74,7 +87,7 @@ impl Format { } #[cfg(any(spi_v1, spi_f1))] - pub const fn chlen(&self) -> vals::Chlen { + const fn chlen(&self) -> vals::Chlen { match self { Format::Data16Channel16 => vals::Chlen::SIXTEENBIT, Format::Data16Channel32 => vals::Chlen::THIRTYTWOBIT, @@ -84,15 +97,18 @@ impl Format { } } +/// Clock polarity #[derive(Copy, Clone)] pub enum ClockPolarity { + /// Low on idle. IdleLow, + /// High on idle. IdleHigh, } impl ClockPolarity { #[cfg(any(spi_v1, spi_f1))] - pub const fn ckpol(&self) -> vals::Ckpol { + const fn ckpol(&self) -> vals::Ckpol { match self { ClockPolarity::IdleHigh => vals::Ckpol::IDLEHIGH, ClockPolarity::IdleLow => vals::Ckpol::IDLELOW, @@ -109,11 +125,17 @@ impl ClockPolarity { #[non_exhaustive] #[derive(Copy, Clone)] pub struct Config { + /// Mode pub mode: Mode, + /// Function (transmit, receive) pub function: Function, + /// Which I2S standard to use. pub standard: Standard, + /// Data format. pub format: Format, + /// Clock polarity. pub clock_polarity: ClockPolarity, + /// True to eanble master clock output from this instance. pub master_clock: bool, } @@ -130,6 +152,7 @@ impl Default for Config { } } +/// I2S driver. pub struct I2S<'d, T: Instance, Tx, Rx> { _peri: Spi<'d, T, Tx, Rx>, sd: Option>, @@ -242,6 +265,7 @@ impl<'d, T: Instance, Tx, Rx> I2S<'d, T, Tx, Rx> { } } + /// Write audio data. pub async fn write(&mut self, data: &[W]) -> Result<(), Error> where Tx: TxDma, @@ -249,6 +273,7 @@ impl<'d, T: Instance, Tx, Rx> I2S<'d, T, Tx, Rx> { self._peri.write(data).await } + /// Read audio data. pub async fn read(&mut self, data: &mut [W]) -> Result<(), Error> where Tx: TxDma, diff --git a/embassy-stm32/src/rcc/mod.rs b/embassy-stm32/src/rcc/mod.rs index dc829a9a..04a51110 100644 --- a/embassy-stm32/src/rcc/mod.rs +++ b/embassy-stm32/src/rcc/mod.rs @@ -1,4 +1,7 @@ +//! Reset and Clock Control (RCC) + #![macro_use] +#![allow(missing_docs)] // TODO use core::mem::MaybeUninit; diff --git a/embassy-stm32/src/rng.rs b/embassy-stm32/src/rng.rs index 5e6922e9..b2196b0d 100644 --- a/embassy-stm32/src/rng.rs +++ b/embassy-stm32/src/rng.rs @@ -13,13 +13,19 @@ use crate::{interrupt, pac, peripherals, Peripheral}; static RNG_WAKER: AtomicWaker = AtomicWaker::new(); +/// RNG error #[derive(Debug, PartialEq, Eq)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum Error { + /// Seed error. SeedError, + /// Clock error. Double-check the RCC configuration, + /// see the Reference Manual for details on restrictions + /// on RNG clocks. ClockError, } +/// RNG interrupt handler. pub struct InterruptHandler { _phantom: PhantomData, } @@ -34,11 +40,13 @@ impl interrupt::typelevel::Handler for InterruptHandl } } +/// RNG driver. pub struct Rng<'d, T: Instance> { _inner: PeripheralRef<'d, T>, } impl<'d, T: Instance> Rng<'d, T> { + /// Create a new RNG driver. pub fn new( inner: impl Peripheral

+ 'd, _irq: impl interrupt::typelevel::Binding> + 'd, @@ -54,6 +62,7 @@ impl<'d, T: Instance> Rng<'d, T> { random } + /// Reset the RNG. #[cfg(rng_v1)] pub fn reset(&mut self) { T::regs().cr().write(|reg| { @@ -106,7 +115,8 @@ impl<'d, T: Instance> Rng<'d, T> { while T::regs().cr().read().condrst() {} } - pub fn recover_seed_error(&mut self) -> () { + /// Try to recover from a seed error. + pub fn recover_seed_error(&mut self) { self.reset(); // reset should also clear the SEIS flag if T::regs().sr().read().seis() { @@ -117,6 +127,7 @@ impl<'d, T: Instance> Rng<'d, T> { while T::regs().sr().read().secs() {} } + /// Fill the given slice with random values. pub async fn async_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> { for chunk in dest.chunks_mut(4) { let mut bits = T::regs().sr().read(); @@ -217,7 +228,9 @@ pub(crate) mod sealed { } } +/// RNG instance trait. pub trait Instance: sealed::Instance + Peripheral

+ crate::rcc::RccPeripheral + 'static + Send { + /// Interrupt for this RNG instance. type Interrupt: interrupt::typelevel::Interrupt; } diff --git a/embassy-stm32/src/rtc/datetime.rs b/embassy-stm32/src/rtc/datetime.rs index f4e86dd8..ef92fa4b 100644 --- a/embassy-stm32/src/rtc/datetime.rs +++ b/embassy-stm32/src/rtc/datetime.rs @@ -104,45 +104,51 @@ pub struct DateTime { } impl DateTime { + /// Get the year (0..=4095) pub const fn year(&self) -> u16 { self.year } + /// Get the month (1..=12, 1 is January) pub const fn month(&self) -> u8 { self.month } + /// Get the day (1..=31) pub const fn day(&self) -> u8 { self.day } + /// Get the day of week pub const fn day_of_week(&self) -> DayOfWeek { self.day_of_week } + /// Get the hour (0..=23) pub const fn hour(&self) -> u8 { self.hour } + /// Get the minute (0..=59) pub const fn minute(&self) -> u8 { self.minute } + /// Get the second (0..=59) pub const fn second(&self) -> u8 { self.second } + /// Create a new DateTime with the given information. pub fn from( year: u16, month: u8, day: u8, - day_of_week: u8, + day_of_week: DayOfWeek, hour: u8, minute: u8, second: u8, ) -> Result { - let day_of_week = day_of_week_from_u8(day_of_week)?; - if year > 4095 { Err(Error::InvalidYear) } else if month < 1 || month > 12 { diff --git a/embassy-stm32/src/rtc/mod.rs b/embassy-stm32/src/rtc/mod.rs index b4315f53..fa359cda 100644 --- a/embassy-stm32/src/rtc/mod.rs +++ b/embassy-stm32/src/rtc/mod.rs @@ -9,9 +9,9 @@ use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; #[cfg(feature = "low-power")] use embassy_sync::blocking_mutex::Mutex; -use self::datetime::day_of_week_to_u8; #[cfg(not(rtc_v2f2))] use self::datetime::RtcInstant; +use self::datetime::{day_of_week_from_u8, day_of_week_to_u8}; pub use self::datetime::{DateTime, DayOfWeek, Error as DateTimeError}; use crate::pac::rtc::regs::{Dr, Tr}; use crate::time::Hertz; @@ -102,7 +102,7 @@ pub enum RtcError { NotRunning, } -pub struct RtcTimeProvider { +pub(crate) struct RtcTimeProvider { _private: (), } @@ -127,7 +127,7 @@ impl RtcTimeProvider { let minute = bcd2_to_byte((tr.mnt(), tr.mnu())); let hour = bcd2_to_byte((tr.ht(), tr.hu())); - let weekday = dr.wdu(); + let weekday = day_of_week_from_u8(dr.wdu()).map_err(RtcError::InvalidDateTime)?; let day = bcd2_to_byte((dr.dt(), dr.du())); let month = bcd2_to_byte((dr.mt() as u8, dr.mu())); let year = bcd2_to_byte((dr.yt(), dr.yu())) as u16 + 1970_u16; @@ -171,6 +171,7 @@ pub struct Rtc { _private: (), } +/// RTC configuration. #[non_exhaustive] #[derive(Copy, Clone, PartialEq)] pub struct RtcConfig { @@ -188,6 +189,7 @@ impl Default for RtcConfig { } } +/// Calibration cycle period. #[derive(Copy, Clone, Debug, PartialEq)] #[repr(u8)] pub enum RtcCalibrationCyclePeriod { @@ -206,6 +208,7 @@ impl Default for RtcCalibrationCyclePeriod { } impl Rtc { + /// Create a new RTC instance. pub fn new(_rtc: impl Peripheral

, rtc_config: RtcConfig) -> Self { #[cfg(not(any(stm32l0, stm32f3, stm32l1, stm32f0, stm32f2)))] ::enable_and_reset(); @@ -240,7 +243,7 @@ impl Rtc { } /// Acquire a [`RtcTimeProvider`] instance. - pub const fn time_provider(&self) -> RtcTimeProvider { + pub(crate) const fn time_provider(&self) -> RtcTimeProvider { RtcTimeProvider { _private: () } } @@ -315,6 +318,7 @@ impl Rtc { }) } + /// Number of backup registers of this instance. pub const BACKUP_REGISTER_COUNT: usize = RTC::BACKUP_REGISTER_COUNT; /// Read content of the backup register. diff --git a/embassy-stm32/src/timer/complementary_pwm.rs b/embassy-stm32/src/timer/complementary_pwm.rs index 6654366c..e543a5b4 100644 --- a/embassy-stm32/src/timer/complementary_pwm.rs +++ b/embassy-stm32/src/timer/complementary_pwm.rs @@ -1,3 +1,5 @@ +//! PWM driver with complementary output support. + use core::marker::PhantomData; use embassy_hal_internal::{into_ref, PeripheralRef}; diff --git a/embassy-stm32/src/timer/mod.rs b/embassy-stm32/src/timer/mod.rs index 9f93c642..42ef878f 100644 --- a/embassy-stm32/src/timer/mod.rs +++ b/embassy-stm32/src/timer/mod.rs @@ -1,3 +1,5 @@ +//! Timers, PWM, quadrature decoder. + pub mod complementary_pwm; pub mod qei; pub mod simple_pwm; @@ -8,6 +10,7 @@ use crate::interrupt; use crate::rcc::RccPeripheral; use crate::time::Hertz; +/// Low-level timer access. #[cfg(feature = "unstable-pac")] pub mod low_level { pub use super::sealed::*; diff --git a/embassy-stm32/src/timer/qei.rs b/embassy-stm32/src/timer/qei.rs index 01d028bf..9f9379c2 100644 --- a/embassy-stm32/src/timer/qei.rs +++ b/embassy-stm32/src/timer/qei.rs @@ -1,3 +1,5 @@ +//! Quadrature decoder using a timer. + use core::marker::PhantomData; use embassy_hal_internal::{into_ref, PeripheralRef}; diff --git a/embassy-stm32/src/timer/simple_pwm.rs b/embassy-stm32/src/timer/simple_pwm.rs index 1cf0ad72..234bbaff 100644 --- a/embassy-stm32/src/timer/simple_pwm.rs +++ b/embassy-stm32/src/timer/simple_pwm.rs @@ -1,3 +1,5 @@ +//! Simple PWM driver. + use core::marker::PhantomData; use embassy_hal_internal::{into_ref, PeripheralRef};