Merge pull request #2308 from embassy-rs/stm32-docs

stm32: more docs.
This commit is contained in:
Dario Nieuwenhuis 2023-12-18 18:20:07 +00:00 committed by GitHub
commit 227ace6c3c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 112 additions and 14 deletions

View File

@ -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")]

View File

@ -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()
}

View File

@ -1,3 +1,5 @@
//! Direct Memory Access (DMA)
#[cfg(dma)]
pub(crate) mod dma;
#[cfg(dma)]

View File

@ -43,6 +43,7 @@ impl interrupt::typelevel::Handler<interrupt::typelevel::ETH> 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<T: Instance> {
peri: PhantomData<T>,
clock_range: Cr,

View File

@ -17,6 +17,7 @@ use crate::{interrupt, Peripheral};
pub(super) static REGION_ACCESS: Mutex<CriticalSectionRawMutex, ()> = Mutex::new(());
impl<'d> Flash<'d, Async> {
/// Create a new flash driver with async capabilities.
pub fn new(
p: impl Peripheral<P = FLASH> + 'd,
_irq: impl interrupt::typelevel::Binding<crate::interrupt::typelevel::FLASH, InterruptHandler> + '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 }

View File

@ -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;

View File

@ -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 {
<T as crate::rcc::sealed::RccPeripheral>::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<CHIP: stm32_fmc::SdramChip>(
_instance: impl Peripheral<P = T> + 'd,
$($addr_pin_name: impl Peripheral<P = impl $addr_signal<T>> + 'd),*,
@ -199,6 +202,7 @@ pub(crate) mod sealed {
}
}
/// FMC instance trait.
pub trait Instance: sealed::Instance + 'static {}
foreach_peripheral!(

View File

@ -1,3 +1,5 @@
//! General-purpose Input/Output (GPIO)
#![macro_use]
use core::convert::Infallible;

View File

@ -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<T>,
@ -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<T>,
@ -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<T>,

View File

@ -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<PeripheralRef<'d, AnyPin>>,
@ -242,6 +265,7 @@ impl<'d, T: Instance, Tx, Rx> I2S<'d, T, Tx, Rx> {
}
}
/// Write audio data.
pub async fn write<W: Word>(&mut self, data: &[W]) -> Result<(), Error>
where
Tx: TxDma<T>,
@ -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<W: Word>(&mut self, data: &mut [W]) -> Result<(), Error>
where
Tx: TxDma<T>,

View File

@ -1,4 +1,7 @@
//! Reset and Clock Control (RCC)
#![macro_use]
#![allow(missing_docs)] // TODO
use core::mem::MaybeUninit;

View File

@ -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<T: Instance> {
_phantom: PhantomData<T>,
}
@ -34,11 +40,13 @@ impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> 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<P = T> + 'd,
_irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + '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<P = Self> + crate::rcc::RccPeripheral + 'static + Send {
/// Interrupt for this RNG instance.
type Interrupt: interrupt::typelevel::Interrupt;
}

View File

@ -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<Self, Error> {
let day_of_week = day_of_week_from_u8(day_of_week)?;
if year > 4095 {
Err(Error::InvalidYear)
} else if month < 1 || month > 12 {

View File

@ -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<P = RTC>, rtc_config: RtcConfig) -> Self {
#[cfg(not(any(stm32l0, stm32f3, stm32l1, stm32f0, stm32f2)))]
<RTC as crate::rcc::sealed::RccPeripheral>::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.

View File

@ -1,3 +1,5 @@
//! PWM driver with complementary output support.
use core::marker::PhantomData;
use embassy_hal_internal::{into_ref, PeripheralRef};

View File

@ -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::*;

View File

@ -1,3 +1,5 @@
//! Quadrature decoder using a timer.
use core::marker::PhantomData;
use embassy_hal_internal::{into_ref, PeripheralRef};

View File

@ -1,3 +1,5 @@
//! Simple PWM driver.
use core::marker::PhantomData;
use embassy_hal_internal::{into_ref, PeripheralRef};