commit
227ace6c3c
@ -1,5 +1,6 @@
|
|||||||
//! Analog to Digital (ADC) converter driver.
|
//! Analog to Digital (ADC) converter driver.
|
||||||
#![macro_use]
|
#![macro_use]
|
||||||
|
#![allow(missing_docs)] // TODO
|
||||||
|
|
||||||
#[cfg(not(adc_f3_v2))]
|
#[cfg(not(adc_f3_v2))]
|
||||||
#[cfg_attr(adc_f1, path = "f1.rs")]
|
#[cfg_attr(adc_f1, path = "f1.rs")]
|
||||||
|
@ -5,6 +5,7 @@ use crate::peripherals::CRC;
|
|||||||
use crate::rcc::sealed::RccPeripheral;
|
use crate::rcc::sealed::RccPeripheral;
|
||||||
use crate::Peripheral;
|
use crate::Peripheral;
|
||||||
|
|
||||||
|
/// CRC driver.
|
||||||
pub struct Crc<'d> {
|
pub struct Crc<'d> {
|
||||||
_peri: PeripheralRef<'d, CRC>,
|
_peri: PeripheralRef<'d, CRC>,
|
||||||
}
|
}
|
||||||
@ -34,6 +35,7 @@ impl<'d> Crc<'d> {
|
|||||||
PAC_CRC.dr().write_value(word);
|
PAC_CRC.dr().write_value(word);
|
||||||
self.read()
|
self.read()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Feed a slice of words to the peripheral and return the result.
|
/// Feed a slice of words to the peripheral and return the result.
|
||||||
pub fn feed_words(&mut self, words: &[u32]) -> u32 {
|
pub fn feed_words(&mut self, words: &[u32]) -> u32 {
|
||||||
for word in words {
|
for word in words {
|
||||||
@ -42,6 +44,8 @@ impl<'d> Crc<'d> {
|
|||||||
|
|
||||||
self.read()
|
self.read()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Read the CRC result value.
|
||||||
pub fn read(&self) -> u32 {
|
pub fn read(&self) -> u32 {
|
||||||
PAC_CRC.dr().read()
|
PAC_CRC.dr().read()
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
//! Direct Memory Access (DMA)
|
||||||
|
|
||||||
#[cfg(dma)]
|
#[cfg(dma)]
|
||||||
pub(crate) mod dma;
|
pub(crate) mod dma;
|
||||||
#[cfg(dma)]
|
#[cfg(dma)]
|
||||||
|
@ -43,6 +43,7 @@ impl interrupt::typelevel::Handler<interrupt::typelevel::ETH> for InterruptHandl
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Ethernet driver.
|
||||||
pub struct Ethernet<'d, T: Instance, P: PHY> {
|
pub struct Ethernet<'d, T: Instance, P: PHY> {
|
||||||
_peri: PeripheralRef<'d, T>,
|
_peri: PeripheralRef<'d, T>,
|
||||||
pub(crate) tx: TDesRing<'d>,
|
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> {
|
pub struct EthernetStationManagement<T: Instance> {
|
||||||
peri: PhantomData<T>,
|
peri: PhantomData<T>,
|
||||||
clock_range: Cr,
|
clock_range: Cr,
|
||||||
|
@ -17,6 +17,7 @@ use crate::{interrupt, Peripheral};
|
|||||||
pub(super) static REGION_ACCESS: Mutex<CriticalSectionRawMutex, ()> = Mutex::new(());
|
pub(super) static REGION_ACCESS: Mutex<CriticalSectionRawMutex, ()> = Mutex::new(());
|
||||||
|
|
||||||
impl<'d> Flash<'d, Async> {
|
impl<'d> Flash<'d, Async> {
|
||||||
|
/// Create a new flash driver with async capabilities.
|
||||||
pub fn new(
|
pub fn new(
|
||||||
p: impl Peripheral<P = FLASH> + 'd,
|
p: impl Peripheral<P = FLASH> + 'd,
|
||||||
_irq: impl interrupt::typelevel::Binding<crate::interrupt::typelevel::FLASH, InterruptHandler> + '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> {
|
pub fn into_regions(self) -> FlashLayout<'d, Async> {
|
||||||
assert!(family::is_default_layout());
|
assert!(family::is_default_layout());
|
||||||
FlashLayout::new(self.inner)
|
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> {
|
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 }
|
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> {
|
pub async fn erase(&mut self, from: u32, to: u32) -> Result<(), Error> {
|
||||||
unsafe { erase_sectored(FLASH_BASE as u32, from, to).await }
|
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! {
|
foreach_flash_region! {
|
||||||
($type_name:ident, $write_size:literal, $erase_size:literal) => {
|
($type_name:ident, $write_size:literal, $erase_size:literal) => {
|
||||||
impl crate::_generated::flash_regions::$type_name<'_, Async> {
|
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> {
|
pub async fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Error> {
|
||||||
blocking_read(self.0.base, self.0.size, offset, bytes)
|
blocking_read(self.0.base, self.0.size, offset, bytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Async write.
|
||||||
pub async fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Error> {
|
pub async fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Error> {
|
||||||
let _guard = REGION_ACCESS.lock().await;
|
let _guard = REGION_ACCESS.lock().await;
|
||||||
unsafe { write_chunked(self.0.base, self.0.size, offset, bytes).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> {
|
pub async fn erase(&mut self, from: u32, to: u32) -> Result<(), Error> {
|
||||||
let _guard = REGION_ACCESS.lock().await;
|
let _guard = REGION_ACCESS.lock().await;
|
||||||
unsafe { erase_sectored(self.0.base, from, to).await }
|
unsafe { erase_sectored(self.0.base, from, to).await }
|
||||||
|
@ -9,7 +9,7 @@ use pac::FLASH_SIZE;
|
|||||||
use super::{FlashBank, FlashRegion, FlashSector, FLASH_REGIONS, WRITE_SIZE};
|
use super::{FlashBank, FlashRegion, FlashSector, FLASH_REGIONS, WRITE_SIZE};
|
||||||
use crate::flash::Error;
|
use crate::flash::Error;
|
||||||
use crate::pac;
|
use crate::pac;
|
||||||
|
#[allow(missing_docs)] // TODO
|
||||||
#[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f469, stm32f479))]
|
#[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f469, stm32f479))]
|
||||||
mod alt_regions {
|
mod alt_regions {
|
||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
|
@ -6,6 +6,7 @@ use crate::gpio::sealed::AFType;
|
|||||||
use crate::gpio::{Pull, Speed};
|
use crate::gpio::{Pull, Speed};
|
||||||
use crate::Peripheral;
|
use crate::Peripheral;
|
||||||
|
|
||||||
|
/// FMC driver
|
||||||
pub struct Fmc<'d, T: Instance> {
|
pub struct Fmc<'d, T: Instance> {
|
||||||
peri: PhantomData<&'d mut T>,
|
peri: PhantomData<&'d mut T>,
|
||||||
}
|
}
|
||||||
@ -38,6 +39,7 @@ where
|
|||||||
T::REGS.bcr1().modify(|r| r.set_fmcen(true));
|
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 {
|
pub fn source_clock_hz(&self) -> u32 {
|
||||||
<T as crate::rcc::sealed::RccPeripheral>::frequency().0
|
<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)),*],
|
nbl: [$(($nbl_pin_name:ident: $nbl_signal:ident)),*],
|
||||||
ctrl: [$(($ctrl_pin_name:ident: $ctrl_signal:ident)),*]
|
ctrl: [$(($ctrl_pin_name:ident: $ctrl_signal:ident)),*]
|
||||||
)) => {
|
)) => {
|
||||||
|
/// Create a new FMC instance.
|
||||||
pub fn $name<CHIP: stm32_fmc::SdramChip>(
|
pub fn $name<CHIP: stm32_fmc::SdramChip>(
|
||||||
_instance: impl Peripheral<P = T> + 'd,
|
_instance: impl Peripheral<P = T> + 'd,
|
||||||
$($addr_pin_name: impl Peripheral<P = impl $addr_signal<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 {}
|
pub trait Instance: sealed::Instance + 'static {}
|
||||||
|
|
||||||
foreach_peripheral!(
|
foreach_peripheral!(
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
//! General-purpose Input/Output (GPIO)
|
||||||
|
|
||||||
#![macro_use]
|
#![macro_use]
|
||||||
use core::convert::Infallible;
|
use core::convert::Infallible;
|
||||||
|
|
||||||
|
@ -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> {
|
pub fn blocking_read(&mut self, addr: u8, read: &mut [u8]) -> Result<(), Error> {
|
||||||
self.blocking_read_timeout(addr, read, self.timeout())
|
self.blocking_read_timeout(addr, read, self.timeout())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Blocking write.
|
||||||
pub fn blocking_write(&mut self, addr: u8, write: &[u8]) -> Result<(), Error> {
|
pub fn blocking_write(&mut self, addr: u8, write: &[u8]) -> Result<(), Error> {
|
||||||
let timeout = self.timeout();
|
let timeout = self.timeout();
|
||||||
|
|
||||||
@ -266,6 +268,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Blocking write, restart, read.
|
||||||
pub fn blocking_write_read(&mut self, addr: u8, write: &[u8], read: &mut [u8]) -> Result<(), Error> {
|
pub fn blocking_write_read(&mut self, addr: u8, write: &[u8], read: &mut [u8]) -> Result<(), Error> {
|
||||||
let timeout = self.timeout();
|
let timeout = self.timeout();
|
||||||
|
|
||||||
@ -435,6 +438,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Write.
|
||||||
pub async fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Error>
|
pub async fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Error>
|
||||||
where
|
where
|
||||||
TXDMA: crate::i2c::TxDma<T>,
|
TXDMA: crate::i2c::TxDma<T>,
|
||||||
@ -457,6 +461,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Read.
|
||||||
pub async fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Error>
|
pub async fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Error>
|
||||||
where
|
where
|
||||||
RXDMA: crate::i2c::RxDma<T>,
|
RXDMA: crate::i2c::RxDma<T>,
|
||||||
@ -616,6 +621,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Write, restart, read.
|
||||||
pub async fn write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Error>
|
pub async fn write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Error>
|
||||||
where
|
where
|
||||||
RXDMA: crate::i2c::RxDma<T>,
|
RXDMA: crate::i2c::RxDma<T>,
|
||||||
|
@ -8,30 +8,42 @@ use crate::spi::{Config as SpiConfig, *};
|
|||||||
use crate::time::Hertz;
|
use crate::time::Hertz;
|
||||||
use crate::{Peripheral, PeripheralRef};
|
use crate::{Peripheral, PeripheralRef};
|
||||||
|
|
||||||
|
/// I2S mode
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub enum Mode {
|
pub enum Mode {
|
||||||
|
/// Master mode
|
||||||
Master,
|
Master,
|
||||||
|
/// Slave mode
|
||||||
Slave,
|
Slave,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// I2S function
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub enum Function {
|
pub enum Function {
|
||||||
|
/// Transmit audio data
|
||||||
Transmit,
|
Transmit,
|
||||||
|
/// Receive audio data
|
||||||
Receive,
|
Receive,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// I2C standard
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub enum Standard {
|
pub enum Standard {
|
||||||
|
/// Philips
|
||||||
Philips,
|
Philips,
|
||||||
|
/// Most significant bit first.
|
||||||
MsbFirst,
|
MsbFirst,
|
||||||
|
/// Least significant bit first.
|
||||||
LsbFirst,
|
LsbFirst,
|
||||||
|
/// PCM with long sync.
|
||||||
PcmLongSync,
|
PcmLongSync,
|
||||||
|
/// PCM with short sync.
|
||||||
PcmShortSync,
|
PcmShortSync,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Standard {
|
impl Standard {
|
||||||
#[cfg(any(spi_v1, spi_f1))]
|
#[cfg(any(spi_v1, spi_f1))]
|
||||||
pub const fn i2sstd(&self) -> vals::I2sstd {
|
const fn i2sstd(&self) -> vals::I2sstd {
|
||||||
match self {
|
match self {
|
||||||
Standard::Philips => vals::I2sstd::PHILIPS,
|
Standard::Philips => vals::I2sstd::PHILIPS,
|
||||||
Standard::MsbFirst => vals::I2sstd::MSB,
|
Standard::MsbFirst => vals::I2sstd::MSB,
|
||||||
@ -42,7 +54,7 @@ impl Standard {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(spi_v1, spi_f1))]
|
#[cfg(any(spi_v1, spi_f1))]
|
||||||
pub const fn pcmsync(&self) -> vals::Pcmsync {
|
const fn pcmsync(&self) -> vals::Pcmsync {
|
||||||
match self {
|
match self {
|
||||||
Standard::PcmLongSync => vals::Pcmsync::LONG,
|
Standard::PcmLongSync => vals::Pcmsync::LONG,
|
||||||
_ => vals::Pcmsync::SHORT,
|
_ => vals::Pcmsync::SHORT,
|
||||||
@ -50,6 +62,7 @@ impl Standard {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// I2S data format.
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub enum Format {
|
pub enum Format {
|
||||||
/// 16 bit data length on 16 bit wide channel
|
/// 16 bit data length on 16 bit wide channel
|
||||||
@ -64,7 +77,7 @@ pub enum Format {
|
|||||||
|
|
||||||
impl Format {
|
impl Format {
|
||||||
#[cfg(any(spi_v1, spi_f1))]
|
#[cfg(any(spi_v1, spi_f1))]
|
||||||
pub const fn datlen(&self) -> vals::Datlen {
|
const fn datlen(&self) -> vals::Datlen {
|
||||||
match self {
|
match self {
|
||||||
Format::Data16Channel16 => vals::Datlen::SIXTEENBIT,
|
Format::Data16Channel16 => vals::Datlen::SIXTEENBIT,
|
||||||
Format::Data16Channel32 => vals::Datlen::SIXTEENBIT,
|
Format::Data16Channel32 => vals::Datlen::SIXTEENBIT,
|
||||||
@ -74,7 +87,7 @@ impl Format {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(spi_v1, spi_f1))]
|
#[cfg(any(spi_v1, spi_f1))]
|
||||||
pub const fn chlen(&self) -> vals::Chlen {
|
const fn chlen(&self) -> vals::Chlen {
|
||||||
match self {
|
match self {
|
||||||
Format::Data16Channel16 => vals::Chlen::SIXTEENBIT,
|
Format::Data16Channel16 => vals::Chlen::SIXTEENBIT,
|
||||||
Format::Data16Channel32 => vals::Chlen::THIRTYTWOBIT,
|
Format::Data16Channel32 => vals::Chlen::THIRTYTWOBIT,
|
||||||
@ -84,15 +97,18 @@ impl Format {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Clock polarity
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub enum ClockPolarity {
|
pub enum ClockPolarity {
|
||||||
|
/// Low on idle.
|
||||||
IdleLow,
|
IdleLow,
|
||||||
|
/// High on idle.
|
||||||
IdleHigh,
|
IdleHigh,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ClockPolarity {
|
impl ClockPolarity {
|
||||||
#[cfg(any(spi_v1, spi_f1))]
|
#[cfg(any(spi_v1, spi_f1))]
|
||||||
pub const fn ckpol(&self) -> vals::Ckpol {
|
const fn ckpol(&self) -> vals::Ckpol {
|
||||||
match self {
|
match self {
|
||||||
ClockPolarity::IdleHigh => vals::Ckpol::IDLEHIGH,
|
ClockPolarity::IdleHigh => vals::Ckpol::IDLEHIGH,
|
||||||
ClockPolarity::IdleLow => vals::Ckpol::IDLELOW,
|
ClockPolarity::IdleLow => vals::Ckpol::IDLELOW,
|
||||||
@ -109,11 +125,17 @@ impl ClockPolarity {
|
|||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
|
/// Mode
|
||||||
pub mode: Mode,
|
pub mode: Mode,
|
||||||
|
/// Function (transmit, receive)
|
||||||
pub function: Function,
|
pub function: Function,
|
||||||
|
/// Which I2S standard to use.
|
||||||
pub standard: Standard,
|
pub standard: Standard,
|
||||||
|
/// Data format.
|
||||||
pub format: Format,
|
pub format: Format,
|
||||||
|
/// Clock polarity.
|
||||||
pub clock_polarity: ClockPolarity,
|
pub clock_polarity: ClockPolarity,
|
||||||
|
/// True to eanble master clock output from this instance.
|
||||||
pub master_clock: bool,
|
pub master_clock: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -130,6 +152,7 @@ impl Default for Config {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// I2S driver.
|
||||||
pub struct I2S<'d, T: Instance, Tx, Rx> {
|
pub struct I2S<'d, T: Instance, Tx, Rx> {
|
||||||
_peri: Spi<'d, T, Tx, Rx>,
|
_peri: Spi<'d, T, Tx, Rx>,
|
||||||
sd: Option<PeripheralRef<'d, AnyPin>>,
|
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>
|
pub async fn write<W: Word>(&mut self, data: &[W]) -> Result<(), Error>
|
||||||
where
|
where
|
||||||
Tx: TxDma<T>,
|
Tx: TxDma<T>,
|
||||||
@ -249,6 +273,7 @@ impl<'d, T: Instance, Tx, Rx> I2S<'d, T, Tx, Rx> {
|
|||||||
self._peri.write(data).await
|
self._peri.write(data).await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Read audio data.
|
||||||
pub async fn read<W: Word>(&mut self, data: &mut [W]) -> Result<(), Error>
|
pub async fn read<W: Word>(&mut self, data: &mut [W]) -> Result<(), Error>
|
||||||
where
|
where
|
||||||
Tx: TxDma<T>,
|
Tx: TxDma<T>,
|
||||||
|
@ -1,4 +1,7 @@
|
|||||||
|
//! Reset and Clock Control (RCC)
|
||||||
|
|
||||||
#![macro_use]
|
#![macro_use]
|
||||||
|
#![allow(missing_docs)] // TODO
|
||||||
|
|
||||||
use core::mem::MaybeUninit;
|
use core::mem::MaybeUninit;
|
||||||
|
|
||||||
|
@ -13,13 +13,19 @@ use crate::{interrupt, pac, peripherals, Peripheral};
|
|||||||
|
|
||||||
static RNG_WAKER: AtomicWaker = AtomicWaker::new();
|
static RNG_WAKER: AtomicWaker = AtomicWaker::new();
|
||||||
|
|
||||||
|
/// RNG error
|
||||||
#[derive(Debug, PartialEq, Eq)]
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
|
/// Seed error.
|
||||||
SeedError,
|
SeedError,
|
||||||
|
/// Clock error. Double-check the RCC configuration,
|
||||||
|
/// see the Reference Manual for details on restrictions
|
||||||
|
/// on RNG clocks.
|
||||||
ClockError,
|
ClockError,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// RNG interrupt handler.
|
||||||
pub struct InterruptHandler<T: Instance> {
|
pub struct InterruptHandler<T: Instance> {
|
||||||
_phantom: PhantomData<T>,
|
_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> {
|
pub struct Rng<'d, T: Instance> {
|
||||||
_inner: PeripheralRef<'d, T>,
|
_inner: PeripheralRef<'d, T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, T: Instance> Rng<'d, T> {
|
impl<'d, T: Instance> Rng<'d, T> {
|
||||||
|
/// Create a new RNG driver.
|
||||||
pub fn new(
|
pub fn new(
|
||||||
inner: impl Peripheral<P = T> + 'd,
|
inner: impl Peripheral<P = T> + 'd,
|
||||||
_irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
|
_irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
|
||||||
@ -54,6 +62,7 @@ impl<'d, T: Instance> Rng<'d, T> {
|
|||||||
random
|
random
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Reset the RNG.
|
||||||
#[cfg(rng_v1)]
|
#[cfg(rng_v1)]
|
||||||
pub fn reset(&mut self) {
|
pub fn reset(&mut self) {
|
||||||
T::regs().cr().write(|reg| {
|
T::regs().cr().write(|reg| {
|
||||||
@ -106,7 +115,8 @@ impl<'d, T: Instance> Rng<'d, T> {
|
|||||||
while T::regs().cr().read().condrst() {}
|
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();
|
self.reset();
|
||||||
// reset should also clear the SEIS flag
|
// reset should also clear the SEIS flag
|
||||||
if T::regs().sr().read().seis() {
|
if T::regs().sr().read().seis() {
|
||||||
@ -117,6 +127,7 @@ impl<'d, T: Instance> Rng<'d, T> {
|
|||||||
while T::regs().sr().read().secs() {}
|
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> {
|
pub async fn async_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {
|
||||||
for chunk in dest.chunks_mut(4) {
|
for chunk in dest.chunks_mut(4) {
|
||||||
let mut bits = T::regs().sr().read();
|
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 {
|
pub trait Instance: sealed::Instance + Peripheral<P = Self> + crate::rcc::RccPeripheral + 'static + Send {
|
||||||
|
/// Interrupt for this RNG instance.
|
||||||
type Interrupt: interrupt::typelevel::Interrupt;
|
type Interrupt: interrupt::typelevel::Interrupt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -104,45 +104,51 @@ pub struct DateTime {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl DateTime {
|
impl DateTime {
|
||||||
|
/// Get the year (0..=4095)
|
||||||
pub const fn year(&self) -> u16 {
|
pub const fn year(&self) -> u16 {
|
||||||
self.year
|
self.year
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the month (1..=12, 1 is January)
|
||||||
pub const fn month(&self) -> u8 {
|
pub const fn month(&self) -> u8 {
|
||||||
self.month
|
self.month
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the day (1..=31)
|
||||||
pub const fn day(&self) -> u8 {
|
pub const fn day(&self) -> u8 {
|
||||||
self.day
|
self.day
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the day of week
|
||||||
pub const fn day_of_week(&self) -> DayOfWeek {
|
pub const fn day_of_week(&self) -> DayOfWeek {
|
||||||
self.day_of_week
|
self.day_of_week
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the hour (0..=23)
|
||||||
pub const fn hour(&self) -> u8 {
|
pub const fn hour(&self) -> u8 {
|
||||||
self.hour
|
self.hour
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the minute (0..=59)
|
||||||
pub const fn minute(&self) -> u8 {
|
pub const fn minute(&self) -> u8 {
|
||||||
self.minute
|
self.minute
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the second (0..=59)
|
||||||
pub const fn second(&self) -> u8 {
|
pub const fn second(&self) -> u8 {
|
||||||
self.second
|
self.second
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Create a new DateTime with the given information.
|
||||||
pub fn from(
|
pub fn from(
|
||||||
year: u16,
|
year: u16,
|
||||||
month: u8,
|
month: u8,
|
||||||
day: u8,
|
day: u8,
|
||||||
day_of_week: u8,
|
day_of_week: DayOfWeek,
|
||||||
hour: u8,
|
hour: u8,
|
||||||
minute: u8,
|
minute: u8,
|
||||||
second: u8,
|
second: u8,
|
||||||
) -> Result<Self, Error> {
|
) -> Result<Self, Error> {
|
||||||
let day_of_week = day_of_week_from_u8(day_of_week)?;
|
|
||||||
|
|
||||||
if year > 4095 {
|
if year > 4095 {
|
||||||
Err(Error::InvalidYear)
|
Err(Error::InvalidYear)
|
||||||
} else if month < 1 || month > 12 {
|
} else if month < 1 || month > 12 {
|
||||||
|
@ -9,9 +9,9 @@ use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
|
|||||||
#[cfg(feature = "low-power")]
|
#[cfg(feature = "low-power")]
|
||||||
use embassy_sync::blocking_mutex::Mutex;
|
use embassy_sync::blocking_mutex::Mutex;
|
||||||
|
|
||||||
use self::datetime::day_of_week_to_u8;
|
|
||||||
#[cfg(not(rtc_v2f2))]
|
#[cfg(not(rtc_v2f2))]
|
||||||
use self::datetime::RtcInstant;
|
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};
|
pub use self::datetime::{DateTime, DayOfWeek, Error as DateTimeError};
|
||||||
use crate::pac::rtc::regs::{Dr, Tr};
|
use crate::pac::rtc::regs::{Dr, Tr};
|
||||||
use crate::time::Hertz;
|
use crate::time::Hertz;
|
||||||
@ -102,7 +102,7 @@ pub enum RtcError {
|
|||||||
NotRunning,
|
NotRunning,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct RtcTimeProvider {
|
pub(crate) struct RtcTimeProvider {
|
||||||
_private: (),
|
_private: (),
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -127,7 +127,7 @@ impl RtcTimeProvider {
|
|||||||
let minute = bcd2_to_byte((tr.mnt(), tr.mnu()));
|
let minute = bcd2_to_byte((tr.mnt(), tr.mnu()));
|
||||||
let hour = bcd2_to_byte((tr.ht(), tr.hu()));
|
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 day = bcd2_to_byte((dr.dt(), dr.du()));
|
||||||
let month = bcd2_to_byte((dr.mt() as u8, dr.mu()));
|
let month = bcd2_to_byte((dr.mt() as u8, dr.mu()));
|
||||||
let year = bcd2_to_byte((dr.yt(), dr.yu())) as u16 + 1970_u16;
|
let year = bcd2_to_byte((dr.yt(), dr.yu())) as u16 + 1970_u16;
|
||||||
@ -171,6 +171,7 @@ pub struct Rtc {
|
|||||||
_private: (),
|
_private: (),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// RTC configuration.
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
#[derive(Copy, Clone, PartialEq)]
|
#[derive(Copy, Clone, PartialEq)]
|
||||||
pub struct RtcConfig {
|
pub struct RtcConfig {
|
||||||
@ -188,6 +189,7 @@ impl Default for RtcConfig {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Calibration cycle period.
|
||||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
pub enum RtcCalibrationCyclePeriod {
|
pub enum RtcCalibrationCyclePeriod {
|
||||||
@ -206,6 +208,7 @@ impl Default for RtcCalibrationCyclePeriod {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Rtc {
|
impl Rtc {
|
||||||
|
/// Create a new RTC instance.
|
||||||
pub fn new(_rtc: impl Peripheral<P = RTC>, rtc_config: RtcConfig) -> Self {
|
pub fn new(_rtc: impl Peripheral<P = RTC>, rtc_config: RtcConfig) -> Self {
|
||||||
#[cfg(not(any(stm32l0, stm32f3, stm32l1, stm32f0, stm32f2)))]
|
#[cfg(not(any(stm32l0, stm32f3, stm32l1, stm32f0, stm32f2)))]
|
||||||
<RTC as crate::rcc::sealed::RccPeripheral>::enable_and_reset();
|
<RTC as crate::rcc::sealed::RccPeripheral>::enable_and_reset();
|
||||||
@ -240,7 +243,7 @@ impl Rtc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Acquire a [`RtcTimeProvider`] instance.
|
/// Acquire a [`RtcTimeProvider`] instance.
|
||||||
pub const fn time_provider(&self) -> RtcTimeProvider {
|
pub(crate) const fn time_provider(&self) -> RtcTimeProvider {
|
||||||
RtcTimeProvider { _private: () }
|
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;
|
pub const BACKUP_REGISTER_COUNT: usize = RTC::BACKUP_REGISTER_COUNT;
|
||||||
|
|
||||||
/// Read content of the backup register.
|
/// Read content of the backup register.
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
//! PWM driver with complementary output support.
|
||||||
|
|
||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
|
|
||||||
use embassy_hal_internal::{into_ref, PeripheralRef};
|
use embassy_hal_internal::{into_ref, PeripheralRef};
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
//! Timers, PWM, quadrature decoder.
|
||||||
|
|
||||||
pub mod complementary_pwm;
|
pub mod complementary_pwm;
|
||||||
pub mod qei;
|
pub mod qei;
|
||||||
pub mod simple_pwm;
|
pub mod simple_pwm;
|
||||||
@ -8,6 +10,7 @@ use crate::interrupt;
|
|||||||
use crate::rcc::RccPeripheral;
|
use crate::rcc::RccPeripheral;
|
||||||
use crate::time::Hertz;
|
use crate::time::Hertz;
|
||||||
|
|
||||||
|
/// Low-level timer access.
|
||||||
#[cfg(feature = "unstable-pac")]
|
#[cfg(feature = "unstable-pac")]
|
||||||
pub mod low_level {
|
pub mod low_level {
|
||||||
pub use super::sealed::*;
|
pub use super::sealed::*;
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
//! Quadrature decoder using a timer.
|
||||||
|
|
||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
|
|
||||||
use embassy_hal_internal::{into_ref, PeripheralRef};
|
use embassy_hal_internal::{into_ref, PeripheralRef};
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
//! Simple PWM driver.
|
||||||
|
|
||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
|
|
||||||
use embassy_hal_internal::{into_ref, PeripheralRef};
|
use embassy_hal_internal::{into_ref, PeripheralRef};
|
||||||
|
Loading…
Reference in New Issue
Block a user