Merge remote-tracking branch 'origin/main' into bxcan_timestamp

This commit is contained in:
chemicstry
2023-07-31 10:29:20 +03:00
237 changed files with 3313 additions and 1870 deletions

View File

@ -34,7 +34,7 @@ flavors = [
embassy-sync = { version = "0.2.0", path = "../embassy-sync" }
embassy-time = { version = "0.1.2", path = "../embassy-time", optional = true }
embassy-futures = { version = "0.1.0", path = "../embassy-futures" }
embassy-hal-common = {version = "0.1.0", path = "../embassy-hal-common", features = ["cortex-m", "prio-bits-4"] }
embassy-hal-internal = {version = "0.1.0", path = "../embassy-hal-internal", features = ["cortex-m", "prio-bits-4"] }
embassy-embedded-hal = {version = "0.1.0", path = "../embassy-embedded-hal" }
embassy-net-driver = { version = "0.1.0", path = "../embassy-net-driver" }
embassy-usb-driver = {version = "0.1.0", path = "../embassy-usb-driver", optional = true }
@ -57,7 +57,7 @@ sdio-host = "0.5.0"
embedded-sdmmc = { git = "https://github.com/embassy-rs/embedded-sdmmc-rs", rev = "a4f293d3a6f72158385f79c98634cb8a14d0d2fc", optional = true }
critical-section = "1.1"
atomic-polyfill = "1.0.1"
stm32-metapac = "13"
stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-1f8ab493e029fc601edebc6bac105a63cc9858fe" }
vcell = "0.1.3"
bxcan = "0.7.0"
nb = "1.0.0"
@ -67,6 +67,7 @@ cfg-if = "1.0.0"
embedded-io = { version = "0.4.0", features = ["async"], optional = true }
chrono = { version = "^0.4", default-features = false, optional = true}
bit_field = "0.10.2"
document-features = "0.2.7"
[dev-dependencies]
critical-section = { version = "1.1", features = ["std"] }
@ -74,44 +75,67 @@ critical-section = { version = "1.1", features = ["std"] }
[build-dependencies]
proc-macro2 = "1.0.36"
quote = "1.0.15"
stm32-metapac = { version = "13", default-features = false, features = ["metadata"]}
stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-1f8ab493e029fc601edebc6bac105a63cc9858fe", default-features = false, features = ["metadata"]}
[features]
default = ["rt"]
## Enable `stm32-metapac`'s `rt` feature
rt = ["stm32-metapac/rt"]
defmt = ["dep:defmt", "bxcan/unstable-defmt", "embassy-sync/defmt", "embassy-embedded-hal/defmt", "embassy-hal-common/defmt", "embedded-io?/defmt", "embassy-usb-driver?/defmt", "embassy-net-driver/defmt", "embassy-time?/defmt"]
memory-x = ["stm32-metapac/memory-x"]
## Use [`defmt`](https://docs.rs/defmt/latest/defmt/) for logging
defmt = ["dep:defmt", "bxcan/unstable-defmt", "embassy-sync/defmt", "embassy-embedded-hal/defmt", "embassy-hal-internal/defmt", "embedded-io?/defmt", "embassy-usb-driver?/defmt", "embassy-net-driver/defmt", "embassy-time?/defmt"]
exti = []
# Enables additional driver features that depend on embassy-time
## Automatically generate `memory.x` file using [`stm32-metapac`](https://docs.rs/stm32-metapac/)
memory-x = ["stm32-metapac/memory-x"]
## Enable nightly-only features
nightly = ["embedded-hal-1", "embedded-hal-async", "embedded-storage-async", "dep:embedded-io", "dep:embassy-usb-driver", "embassy-embedded-hal/nightly"]
## Re-export stm32-metapac at `embassy_stm32::pac`.
## This is unstable because semver-minor (non-breaking) releases of embassy-stm32 may major-bump (breaking) the stm32-metapac version.
## If this is an issue for you, you're encouraged to directly depend on a fixed version of the PAC.
## There are no plans to make this stable.
unstable-pac = []
## Implement embedded-hal 1.0 alpha traits.
## Implement embedded-hal-async traits if `nightly` is set as well.
unstable-traits = ["embedded-hal-1", "dep:embedded-hal-nb"]
#! ## Time
## Enables additional driver features that depend on embassy-time
time = ["dep:embassy-time"]
# Features starting with `_` are for internal use only. They're not intended
# to be enabled by other crates, and are not covered by semver guarantees.
_time-driver = ["time"]
## Use any time driver
time-driver-any = ["_time-driver"]
## Use TIM2 as time driver
time-driver-tim2 = ["_time-driver"]
## Use TIM3 as time driver
time-driver-tim3 = ["_time-driver"]
## Use TIM4 as time driver
time-driver-tim4 = ["_time-driver"]
## Use TIM5 as time driver
time-driver-tim5 = ["_time-driver"]
## Use TIM12 as time driver
time-driver-tim12 = ["_time-driver"]
## Use TIM15 as time driver
time-driver-tim15 = ["_time-driver"]
# Enable nightly-only features
nightly = ["embedded-hal-1", "embedded-hal-async", "embedded-storage-async", "dep:embedded-io", "dep:embassy-usb-driver", "embassy-embedded-hal/nightly"]
# Reexport stm32-metapac at `embassy_stm32::pac`.
# This is unstable because semver-minor (non-breaking) releases of embassy-stm32 may major-bump (breaking) the stm32-metapac version.
# If this is an issue for you, you're encouraged to directly depend on a fixed version of the PAC.
# There are no plans to make this stable.
unstable-pac = []
#! ## Chip-selection features
#! Select your chip by specifying the model as a feature, e.g. `stm32c011d6`.
#! Check the `Cargo.toml` for the latest list of supported chips.
#!
#! **Important:** Do not forget to adapt the target chip in your toolchain,
#! e.g. in `.cargo/config.toml`.
# Implement embedded-hal 1.0 alpha traits.
# Implement embedded-hal-async traits if `nightly` is set as well.
unstable-traits = ["embedded-hal-1", "dep:embedded-hal-nb"]
# Chip-selection features
stm32c011d6 = [ "stm32-metapac/stm32c011d6" ]
stm32c011f4 = [ "stm32-metapac/stm32c011f4" ]
stm32c011f6 = [ "stm32-metapac/stm32c011f6" ]

View File

@ -138,7 +138,7 @@ fn main() {
let singleton_tokens: Vec<_> = singletons.iter().map(|s| format_ident!("{}", s)).collect();
g.extend(quote! {
embassy_hal_common::peripherals_definition!(#(#singleton_tokens),*);
embassy_hal_internal::peripherals_definition!(#(#singleton_tokens),*);
});
let singleton_tokens: Vec<_> = singletons
@ -148,7 +148,7 @@ fn main() {
.collect();
g.extend(quote! {
embassy_hal_common::peripherals_struct!(#(#singleton_tokens),*);
embassy_hal_internal::peripherals_struct!(#(#singleton_tokens),*);
});
// ========
@ -160,7 +160,7 @@ fn main() {
}
g.extend(quote! {
embassy_hal_common::interrupt_mod!(
embassy_hal_internal::interrupt_mod!(
#(
#irqs,
)*
@ -211,7 +211,7 @@ fn main() {
let region_type = format_ident!("{}", get_flash_region_type_name(region.name));
flash_regions.extend(quote! {
#[cfg(flash)]
pub struct #region_type<'d, MODE = crate::flash::Async>(pub &'static crate::flash::FlashRegion, pub(crate) embassy_hal_common::PeripheralRef<'d, crate::peripherals::FLASH>, pub(crate) core::marker::PhantomData<MODE>);
pub struct #region_type<'d, MODE = crate::flash::Async>(pub &'static crate::flash::FlashRegion, pub(crate) embassy_hal_internal::PeripheralRef<'d, crate::peripherals::FLASH>, pub(crate) core::marker::PhantomData<MODE>);
});
}
@ -243,7 +243,7 @@ fn main() {
#[cfg(flash)]
impl<'d, MODE> FlashLayout<'d, MODE> {
pub(crate) fn new(p: embassy_hal_common::PeripheralRef<'d, crate::peripherals::FLASH>) -> Self {
pub(crate) fn new(p: embassy_hal_internal::PeripheralRef<'d, crate::peripherals::FLASH>) -> Self {
Self {
#(#inits),*,
_mode: core::marker::PhantomData,
@ -572,21 +572,31 @@ fn main() {
(("fmc", "Clk"), quote!(crate::fmc::ClkPin)),
(("fmc", "BA0"), quote!(crate::fmc::BA0Pin)),
(("fmc", "BA1"), quote!(crate::fmc::BA1Pin)),
(("timer", "CH1"), quote!(crate::pwm::Channel1Pin)),
(("timer", "CH1N"), quote!(crate::pwm::Channel1ComplementaryPin)),
(("timer", "CH2"), quote!(crate::pwm::Channel2Pin)),
(("timer", "CH2N"), quote!(crate::pwm::Channel2ComplementaryPin)),
(("timer", "CH3"), quote!(crate::pwm::Channel3Pin)),
(("timer", "CH3N"), quote!(crate::pwm::Channel3ComplementaryPin)),
(("timer", "CH4"), quote!(crate::pwm::Channel4Pin)),
(("timer", "CH4N"), quote!(crate::pwm::Channel4ComplementaryPin)),
(("timer", "ETR"), quote!(crate::pwm::ExternalTriggerPin)),
(("timer", "BKIN"), quote!(crate::pwm::BreakInputPin)),
(("timer", "BKIN_COMP1"), quote!(crate::pwm::BreakInputComparator1Pin)),
(("timer", "BKIN_COMP2"), quote!(crate::pwm::BreakInputComparator2Pin)),
(("timer", "BKIN2"), quote!(crate::pwm::BreakInput2Pin)),
(("timer", "BKIN2_COMP1"), quote!(crate::pwm::BreakInput2Comparator1Pin)),
(("timer", "BKIN2_COMP2"), quote!(crate::pwm::BreakInput2Comparator2Pin)),
(("timer", "CH1"), quote!(crate::timer::Channel1Pin)),
(("timer", "CH1N"), quote!(crate::timer::Channel1ComplementaryPin)),
(("timer", "CH2"), quote!(crate::timer::Channel2Pin)),
(("timer", "CH2N"), quote!(crate::timer::Channel2ComplementaryPin)),
(("timer", "CH3"), quote!(crate::timer::Channel3Pin)),
(("timer", "CH3N"), quote!(crate::timer::Channel3ComplementaryPin)),
(("timer", "CH4"), quote!(crate::timer::Channel4Pin)),
(("timer", "CH4N"), quote!(crate::timer::Channel4ComplementaryPin)),
(("timer", "ETR"), quote!(crate::timer::ExternalTriggerPin)),
(("timer", "BKIN"), quote!(crate::timer::BreakInputPin)),
(("timer", "BKIN_COMP1"), quote!(crate::timer::BreakInputComparator1Pin)),
(("timer", "BKIN_COMP2"), quote!(crate::timer::BreakInputComparator2Pin)),
(("timer", "BKIN2"), quote!(crate::timer::BreakInput2Pin)),
(("timer", "BKIN2_COMP1"), quote!(crate::timer::BreakInput2Comparator1Pin)),
(("timer", "BKIN2_COMP2"), quote!(crate::timer::BreakInput2Comparator2Pin)),
(("hrtim", "CHA1"), quote!(crate::hrtim::ChannelAPin)),
(("hrtim", "CHA2"), quote!(crate::hrtim::ChannelAComplementaryPin)),
(("hrtim", "CHB1"), quote!(crate::hrtim::ChannelBPin)),
(("hrtim", "CHB2"), quote!(crate::hrtim::ChannelBComplementaryPin)),
(("hrtim", "CHC1"), quote!(crate::hrtim::ChannelCPin)),
(("hrtim", "CHC2"), quote!(crate::hrtim::ChannelCComplementaryPin)),
(("hrtim", "CHD1"), quote!(crate::hrtim::ChannelDPin)),
(("hrtim", "CHD2"), quote!(crate::hrtim::ChannelDComplementaryPin)),
(("hrtim", "CHE1"), quote!(crate::hrtim::ChannelEPin)),
(("hrtim", "CHE2"), quote!(crate::hrtim::ChannelEComplementaryPin)),
(("sdmmc", "CK"), quote!(crate::sdmmc::CkPin)),
(("sdmmc", "CMD"), quote!(crate::sdmmc::CmdPin)),
(("sdmmc", "D0"), quote!(crate::sdmmc::D0Pin)),

View File

@ -1,4 +1,4 @@
use embassy_hal_common::into_ref;
use embassy_hal_internal::into_ref;
use embedded_hal_02::blocking::delay::DelayUs;
use crate::adc::{Adc, AdcPin, Instance, SampleTime};

View File

@ -1,4 +1,4 @@
use embassy_hal_common::into_ref;
use embassy_hal_internal::into_ref;
use embedded_hal_02::blocking::delay::DelayUs;
use crate::adc::{Adc, AdcPin, Instance, InternalChannel, Resolution, SampleTime};

View File

@ -1,4 +1,4 @@
use embassy_hal_common::into_ref;
use embassy_hal_internal::into_ref;
use embedded_hal_02::blocking::delay::DelayUs;
use super::InternalChannel;

View File

@ -1,4 +1,4 @@
use embassy_hal_common::into_ref;
use embassy_hal_internal::into_ref;
use embedded_hal_02::blocking::delay::DelayUs;
use crate::adc::{Adc, AdcPin, Instance, Resolution, SampleTime};

View File

@ -226,7 +226,7 @@ impl Prescaler {
impl<'d, T: Instance> Adc<'d, T> {
pub fn new(adc: impl Peripheral<P = T> + 'd, delay: &mut impl DelayUs<u16>) -> Self {
embassy_hal_common::into_ref!(adc);
embassy_hal_internal::into_ref!(adc);
T::enable();
T::reset();

View File

@ -6,7 +6,7 @@ use core::task::Poll;
pub use bxcan;
use bxcan::{Data, ExtendedId, Frame, Id, StandardId};
use embassy_hal_common::{into_ref, PeripheralRef};
use embassy_hal_internal::{into_ref, PeripheralRef};
use futures::FutureExt;
use crate::gpio::sealed::AFType;
@ -88,6 +88,7 @@ pub struct Can<'d, T: Instance> {
}
#[derive(Debug)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum BusError {
Stuff,
Form,
@ -101,6 +102,22 @@ pub enum BusError {
BusWarning,
}
#[derive(Debug)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum TryReadError {
/// Bus error
BusError(BusError),
/// Receive buffer is empty
Empty,
}
#[derive(Debug)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum TryWriteError {
/// All transmit mailboxes are full
Full,
}
impl<'d, T: Instance> Can<'d, T> {
/// Creates a new Bxcan instance, keeping the peripheral in sleep mode.
/// You must call [Can::enable_non_blocking] to use the peripheral.
@ -186,56 +203,46 @@ impl<'d, T: Instance> Can<'d, T> {
/// Queues the message to be sent but exerts backpressure
pub async fn write(&mut self, frame: &Frame) -> bxcan::TransmitStatus {
poll_fn(|cx| {
T::state().tx_waker.register(cx.waker());
if let Ok(status) = self.can.borrow_mut().transmit(frame) {
return Poll::Ready(status);
}
Poll::Pending
})
.await
CanTx { can: &self.can }.write(frame).await
}
pub async fn flush(&self, mb: bxcan::Mailbox) {
poll_fn(|cx| {
T::state().tx_waker.register(cx.waker());
if T::regs().tsr().read().tme(mb.index()) {
return Poll::Ready(());
}
/// Attempts to transmit a frame without blocking.
///
/// Returns [Err(TryWriteError::Full)] if all transmit mailboxes are full.
pub fn try_write(&mut self, frame: &Frame) -> Result<bxcan::TransmitStatus, TryWriteError> {
CanTx { can: &self.can }.try_write(frame)
}
Poll::Pending
})
.await;
/// Waits for a specific transmit mailbox to become empty
pub async fn flush(&self, mb: bxcan::Mailbox) {
CanTx { can: &self.can }.flush(mb).await
}
/// Waits until any of the transmit mailboxes become empty
pub async fn flush_any(&self) {
CanTx { can: &self.can }.flush_any().await
}
/// Waits until all of the transmit mailboxes become empty
pub async fn flush_all(&self) {
CanTx { can: &self.can }.flush_all().await
}
/// Returns a tuple of the time the message was received and the message frame
pub async fn read(&mut self) -> Result<Envelope, BusError> {
poll_fn(|cx| {
T::state().err_waker.register(cx.waker());
if let Poll::Ready(envelope) = T::state().rx_queue.recv().poll_unpin(cx) {
return Poll::Ready(Ok(envelope));
} else if let Some(err) = self.curr_error() {
return Poll::Ready(Err(err));
}
Poll::Pending
})
.await
CanRx { can: &self.can }.read().await
}
fn curr_error(&self) -> Option<BusError> {
let err = { T::regs().esr().read() };
if err.boff() {
return Some(BusError::BusOff);
} else if err.epvf() {
return Some(BusError::BusPassive);
} else if err.ewgf() {
return Some(BusError::BusWarning);
} else if let Some(err) = err.lec().into_bus_err() {
return Some(err);
}
None
/// Attempts to read a can frame without blocking.
///
/// Returns [Err(TryReadError::Empty)] if there are no frames in the rx queue.
pub fn try_read(&mut self) -> Result<Envelope, TryReadError> {
CanRx { can: &self.can }.try_read()
}
/// Waits while receive queue is empty.
pub async fn wait_not_empty(&mut self) {
CanRx { can: &self.can }.wait_not_empty().await
}
unsafe fn receive_fifo(fifo: RxFifo) {
@ -405,6 +412,14 @@ impl<'c, 'd, T: Instance> CanTx<'c, 'd, T> {
.await
}
/// Attempts to transmit a frame without blocking.
///
/// Returns [Err(TryWriteError::Full)] if all transmit mailboxes are full.
pub fn try_write(&mut self, frame: &Frame) -> Result<bxcan::TransmitStatus, TryWriteError> {
self.can.borrow_mut().transmit(frame).map_err(|_| TryWriteError::Full)
}
/// Waits for a specific transmit mailbox to become empty
pub async fn flush(&self, mb: bxcan::Mailbox) {
poll_fn(|cx| {
T::state().tx_waker.register(cx.waker());
@ -416,6 +431,42 @@ impl<'c, 'd, T: Instance> CanTx<'c, 'd, T> {
})
.await;
}
/// Waits until any of the transmit mailboxes become empty
pub async fn flush_any(&self) {
poll_fn(|cx| {
T::state().tx_waker.register(cx.waker());
let tsr = T::regs().tsr().read();
if tsr.tme(bxcan::Mailbox::Mailbox0.index())
|| tsr.tme(bxcan::Mailbox::Mailbox1.index())
|| tsr.tme(bxcan::Mailbox::Mailbox2.index())
{
return Poll::Ready(());
}
Poll::Pending
})
.await;
}
/// Waits until all of the transmit mailboxes become empty
pub async fn flush_all(&self) {
poll_fn(|cx| {
T::state().tx_waker.register(cx.waker());
let tsr = T::regs().tsr().read();
if tsr.tme(bxcan::Mailbox::Mailbox0.index())
&& tsr.tme(bxcan::Mailbox::Mailbox1.index())
&& tsr.tme(bxcan::Mailbox::Mailbox2.index())
{
return Poll::Ready(());
}
Poll::Pending
})
.await;
}
}
#[allow(dead_code)]
@ -438,6 +489,33 @@ impl<'c, 'd, T: Instance> CanRx<'c, 'd, T> {
.await
}
/// Attempts to read a CAN frame without blocking.
///
/// Returns [Err(TryReadError::Empty)] if there are no frames in the rx queue.
pub fn try_read(&mut self) -> Result<Envelope, TryReadError> {
if let Ok(envelope) = T::state().rx_queue.try_recv() {
return Ok(envelope);
}
if let Some(err) = self.curr_error() {
return Err(TryReadError::BusError(err));
}
Err(TryReadError::Empty)
}
/// Waits while receive queue is empty.
pub async fn wait_not_empty(&mut self) {
poll_fn(|cx| {
if T::state().rx_queue.poll_ready_to_receive(cx) {
Poll::Ready(())
} else {
Poll::Pending
}
})
.await
}
fn curr_error(&self) -> Option<BusError> {
let err = { T::regs().esr().read() };
if err.boff() {

View File

@ -1,5 +1,5 @@
pub use bxcan;
use embassy_hal_common::PeripheralRef;
use embassy_hal_internal::PeripheralRef;
use crate::peripherals;

View File

@ -1,4 +1,4 @@
use embassy_hal_common::{into_ref, PeripheralRef};
use embassy_hal_internal::{into_ref, PeripheralRef};
use crate::pac::CRC as PAC_CRC;
use crate::peripherals::CRC;

View File

@ -1,4 +1,4 @@
use embassy_hal_common::{into_ref, PeripheralRef};
use embassy_hal_internal::{into_ref, PeripheralRef};
use crate::pac::crc::vals;
use crate::pac::CRC as PAC_CRC;

View File

@ -3,7 +3,7 @@
//! Provide access to the STM32 digital-to-analog converter (DAC).
use core::marker::PhantomData;
use embassy_hal_common::{into_ref, PeripheralRef};
use embassy_hal_internal::{into_ref, PeripheralRef};
use crate::pac::dac;
use crate::rcc::RccPeripheral;

View File

@ -2,7 +2,7 @@ use core::future::poll_fn;
use core::marker::PhantomData;
use core::task::Poll;
use embassy_hal_common::{into_ref, PeripheralRef};
use embassy_hal_internal::{into_ref, PeripheralRef};
use embassy_sync::waitqueue::AtomicWaker;
use crate::dma::Transfer;

View File

@ -6,7 +6,7 @@ use core::sync::atomic::{fence, Ordering};
use core::task::{Context, Poll, Waker};
use atomic_polyfill::AtomicUsize;
use embassy_hal_common::{into_ref, Peripheral, PeripheralRef};
use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef};
use embassy_sync::waitqueue::AtomicWaker;
use super::ringbuffer::{DmaCtrl, DmaRingBuffer, OverrunError};
@ -466,15 +466,53 @@ impl<'a, C: Channel, W: Word> RingBuffer<'a, C, W> {
self.ringbuf.clear(DmaCtrlImpl(self.channel.reborrow()));
}
/// Read bytes from the ring buffer
/// Read elements from the ring buffer
/// Return a tuple of the length read and the length remaining in the buffer
/// If not all of the bytes were read, then there will be some bytes in the buffer remaining
/// The length remaining is the capacity, ring_buf.len(), less the bytes remaining after the read
/// If not all of the elements were read, then there will be some elements in the buffer remaining
/// The length remaining is the capacity, ring_buf.len(), less the elements remaining after the read
/// OverrunError is returned if the portion to be read was overwritten by the DMA controller.
pub fn read(&mut self, buf: &mut [W]) -> Result<(usize, usize), OverrunError> {
self.ringbuf.read(DmaCtrlImpl(self.channel.reborrow()), buf)
}
/// Read an exact number of elements from the ringbuffer.
///
/// Returns the remaining number of elements available for immediate reading.
/// OverrunError is returned if the portion to be read was overwritten by the DMA controller.
///
/// Async/Wake Behavior:
/// The underlying DMA peripheral only can wake us when its buffer pointer has reached the halfway point,
/// and when it wraps around. This means that when called with a buffer of length 'M', when this
/// ring buffer was created with a buffer of size 'N':
/// - If M equals N/2 or N/2 divides evenly into M, this function will return every N/2 elements read on the DMA source.
/// - Otherwise, this function may need up to N/2 extra elements to arrive before returning.
pub async fn read_exact(&mut self, buffer: &mut [W]) -> Result<usize, OverrunError> {
use core::future::poll_fn;
use core::sync::atomic::compiler_fence;
let mut read_data = 0;
let buffer_len = buffer.len();
poll_fn(|cx| {
self.set_waker(cx.waker());
compiler_fence(Ordering::SeqCst);
match self.read(&mut buffer[read_data..buffer_len]) {
Ok((len, remaining)) => {
read_data += len;
if read_data == buffer_len {
Poll::Ready(Ok(remaining))
} else {
Poll::Pending
}
}
Err(e) => Poll::Ready(Err(e)),
}
})
.await
}
/// The capacity of the ringbuffer
pub fn cap(&self) -> usize {
self.ringbuf.cap()

View File

@ -4,7 +4,7 @@ use core::pin::Pin;
use core::sync::atomic::{fence, AtomicUsize, Ordering};
use core::task::{Context, Poll, Waker};
use embassy_hal_common::{into_ref, Peripheral, PeripheralRef};
use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef};
use embassy_sync::waitqueue::AtomicWaker;
use super::ringbuffer::{DmaCtrl, DmaRingBuffer, OverrunError};
@ -711,15 +711,53 @@ impl<'a, C: Channel, W: Word> RingBuffer<'a, C, W> {
self.ringbuf.clear(DmaCtrlImpl(self.channel.reborrow()));
}
/// Read bytes from the ring buffer
/// Read elements from the ring buffer
/// Return a tuple of the length read and the length remaining in the buffer
/// If not all of the bytes were read, then there will be some bytes in the buffer remaining
/// The length remaining is the capacity, ring_buf.len(), less the bytes remaining after the read
/// If not all of the elements were read, then there will be some elements in the buffer remaining
/// The length remaining is the capacity, ring_buf.len(), less the elements remaining after the read
/// OverrunError is returned if the portion to be read was overwritten by the DMA controller.
pub fn read(&mut self, buf: &mut [W]) -> Result<(usize, usize), OverrunError> {
self.ringbuf.read(DmaCtrlImpl(self.channel.reborrow()), buf)
}
/// Read an exact number of elements from the ringbuffer.
///
/// Returns the remaining number of elements available for immediate reading.
/// OverrunError is returned if the portion to be read was overwritten by the DMA controller.
///
/// Async/Wake Behavior:
/// The underlying DMA peripheral only can wake us when its buffer pointer has reached the halfway point,
/// and when it wraps around. This means that when called with a buffer of length 'M', when this
/// ring buffer was created with a buffer of size 'N':
/// - If M equals N/2 or N/2 divides evenly into M, this function will return every N/2 elements read on the DMA source.
/// - Otherwise, this function may need up to N/2 extra elements to arrive before returning.
pub async fn read_exact(&mut self, buffer: &mut [W]) -> Result<usize, OverrunError> {
use core::future::poll_fn;
use core::sync::atomic::compiler_fence;
let mut read_data = 0;
let buffer_len = buffer.len();
poll_fn(|cx| {
self.set_waker(cx.waker());
compiler_fence(Ordering::SeqCst);
match self.read(&mut buffer[read_data..buffer_len]) {
Ok((len, remaining)) => {
read_data += len;
if read_data == buffer_len {
Poll::Ready(Ok(remaining))
} else {
Poll::Pending
}
}
Err(e) => Poll::Ready(Err(e)),
}
})
.await
}
// The capacity of the ringbuffer
pub fn cap(&self) -> usize {
self.ringbuf.cap()

View File

@ -5,7 +5,7 @@ use core::pin::Pin;
use core::sync::atomic::{fence, Ordering};
use core::task::{Context, Poll};
use embassy_hal_common::{into_ref, Peripheral, PeripheralRef};
use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef};
use embassy_sync::waitqueue::AtomicWaker;
use super::word::{Word, WordSize};

View File

@ -26,7 +26,7 @@ pub mod word;
use core::mem;
use embassy_hal_common::impl_peripheral;
use embassy_hal_internal::impl_peripheral;
#[cfg(dmamux)]
pub use self::dmamux::*;

View File

@ -72,10 +72,10 @@ impl<'a, W: Word> DmaRingBuffer<'a, W> {
self.cap() - remaining_transfers
}
/// Read bytes from the ring buffer
/// Read elements from the ring buffer
/// Return a tuple of the length read and the length remaining in the buffer
/// If not all of the bytes were read, then there will be some bytes in the buffer remaining
/// The length remaining is the capacity, ring_buf.len(), less the bytes remaining after the read
/// If not all of the elements were read, then there will be some elements in the buffer remaining
/// The length remaining is the capacity, ring_buf.len(), less the elements remaining after the read
/// OverrunError is returned if the portion to be read was overwritten by the DMA controller.
pub fn read(&mut self, mut dma: impl DmaCtrl, buf: &mut [W]) -> Result<(usize, usize), OverrunError> {
/*
@ -95,11 +95,11 @@ impl<'a, W: Word> DmaRingBuffer<'a, W> {
*/
let end = self.pos(dma.get_remaining_transfers());
if self.start == end && dma.get_complete_count() == 0 {
// No bytes are available in the buffer
// No elements are available in the buffer
Ok((0, self.cap()))
} else if self.start < end {
// The available, unread portion in the ring buffer DOES NOT wrap
// Copy out the bytes from the dma buffer
// Copy out the elements from the dma buffer
let len = self.copy_to(buf, self.start..end);
compiler_fence(Ordering::SeqCst);
@ -128,7 +128,7 @@ impl<'a, W: Word> DmaRingBuffer<'a, W> {
// The DMA writer has wrapped since we last read and is currently
// writing (or the next byte added will be) in the beginning of the ring buffer.
// The provided read buffer is not large enough to include all bytes from the tail of the dma buffer.
// The provided read buffer is not large enough to include all elements from the tail of the dma buffer.
// Copy out from the dma buffer
let len = self.copy_to(buf, self.start..self.cap());
@ -154,8 +154,8 @@ impl<'a, W: Word> DmaRingBuffer<'a, W> {
// The DMA writer has wrapped since we last read and is currently
// writing (or the next byte added will be) in the beginning of the ring buffer.
// The provided read buffer is large enough to include all bytes from the tail of the dma buffer,
// so the next read will not have any unread tail bytes in the ring buffer.
// The provided read buffer is large enough to include all elements from the tail of the dma buffer,
// so the next read will not have any unread tail elements in the ring buffer.
// Copy out from the dma buffer
let tail = self.copy_to(buf, self.start..self.cap());
@ -180,7 +180,7 @@ impl<'a, W: Word> DmaRingBuffer<'a, W> {
}
/// Copy from the dma buffer at `data_range` into `buf`
fn copy_to(&mut self, buf: &mut [W], data_range: Range<usize>) -> usize {
// Limit the number of bytes that can be copied
// Limit the number of elements that can be copied
let length = usize::min(data_range.len(), buf.len());
// Copy from dma buffer into read buffer

View File

@ -6,7 +6,7 @@ mod tx_desc;
use core::marker::PhantomData;
use core::sync::atomic::{fence, Ordering};
use embassy_hal_common::{into_ref, PeripheralRef};
use embassy_hal_internal::{into_ref, PeripheralRef};
use stm32_metapac::eth::vals::{Apcs, Cr, Dm, DmaomrSr, Fes, Ftf, Ifg, MbProgress, Mw, Pbl, Rsf, St, Tsf};
pub(crate) use self::rx_desc::{RDes, RDesRing};

View File

@ -3,7 +3,7 @@ mod descriptors;
use core::marker::PhantomData;
use core::sync::atomic::{fence, Ordering};
use embassy_hal_common::{into_ref, PeripheralRef};
use embassy_hal_internal::{into_ref, PeripheralRef};
pub(crate) use self::descriptors::{RDes, RDesRing, TDes, TDesRing};
use super::*;

View File

@ -3,7 +3,7 @@ use core::marker::PhantomData;
use core::pin::Pin;
use core::task::{Context, Poll};
use embassy_hal_common::impl_peripheral;
use embassy_hal_internal::impl_peripheral;
use embassy_sync::waitqueue::AtomicWaker;
use crate::gpio::{AnyPin, Input, Pin as GpioPin};

View File

@ -1,8 +1,8 @@
use core::marker::PhantomData;
use core::sync::atomic::{fence, Ordering};
use embassy_hal_common::drop::OnDrop;
use embassy_hal_common::into_ref;
use embassy_hal_internal::drop::OnDrop;
use embassy_hal_internal::into_ref;
use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
use embassy_sync::mutex::Mutex;

View File

@ -1,8 +1,8 @@
use core::marker::PhantomData;
use core::sync::atomic::{fence, Ordering};
use embassy_hal_common::drop::OnDrop;
use embassy_hal_common::{into_ref, PeripheralRef};
use embassy_hal_internal::drop::OnDrop;
use embassy_hal_internal::{into_ref, PeripheralRef};
use stm32_metapac::FLASH_BASE;
use super::{

View File

@ -14,7 +14,7 @@ use crate::pac;
mod alt_regions {
use core::marker::PhantomData;
use embassy_hal_common::PeripheralRef;
use embassy_hal_internal::PeripheralRef;
use stm32_metapac::FLASH_SIZE;
use crate::_generated::flash_regions::{OTPRegion, BANK1_REGION1, BANK1_REGION2, BANK1_REGION3, OTP_REGION};

View File

@ -1,6 +1,6 @@
use core::marker::PhantomData;
use embassy_hal_common::into_ref;
use embassy_hal_internal::into_ref;
use crate::gpio::sealed::AFType;
use crate::gpio::{Pull, Speed};

View File

@ -1,7 +1,7 @@
#![macro_use]
use core::convert::Infallible;
use embassy_hal_common::{impl_peripheral, into_ref, PeripheralRef};
use embassy_hal_internal::{impl_peripheral, into_ref, PeripheralRef};
use crate::pac::gpio::{self, vals};
use crate::{pac, peripherals, Peripheral};
@ -502,6 +502,20 @@ impl<'d, T: Pin> OutputOpenDrain<'d, T> {
}
}
pub enum OutputType {
PushPull,
OpenDrain,
}
impl From<OutputType> for sealed::AFType {
fn from(value: OutputType) -> Self {
match value {
OutputType::OpenDrain => sealed::AFType::OutputOpenDrain,
OutputType::PushPull => sealed::AFType::OutputPushPull,
}
}
}
pub(crate) mod sealed {
use super::*;

View File

@ -0,0 +1,409 @@
mod traits;
use core::marker::PhantomData;
use embassy_hal_internal::{into_ref, PeripheralRef};
pub use traits::Instance;
#[allow(unused_imports)]
use crate::gpio::sealed::{AFType, Pin};
use crate::gpio::AnyPin;
use crate::time::Hertz;
use crate::Peripheral;
pub enum Source {
Master,
ChA,
ChB,
ChC,
ChD,
ChE,
}
pub struct BurstController<T: Instance> {
phantom: PhantomData<T>,
}
pub struct Master<T: Instance> {
phantom: PhantomData<T>,
}
pub struct ChA<T: Instance> {
phantom: PhantomData<T>,
}
pub struct ChB<T: Instance> {
phantom: PhantomData<T>,
}
pub struct ChC<T: Instance> {
phantom: PhantomData<T>,
}
pub struct ChD<T: Instance> {
phantom: PhantomData<T>,
}
pub struct ChE<T: Instance> {
phantom: PhantomData<T>,
}
mod sealed {
use super::Instance;
pub trait AdvancedChannel<T: Instance> {
fn raw() -> usize;
}
}
pub trait AdvancedChannel<T: Instance>: sealed::AdvancedChannel<T> {}
pub struct PwmPin<'d, Perip, Channel> {
_pin: PeripheralRef<'d, AnyPin>,
phantom: PhantomData<(Perip, Channel)>,
}
pub struct ComplementaryPwmPin<'d, Perip, Channel> {
_pin: PeripheralRef<'d, AnyPin>,
phantom: PhantomData<(Perip, Channel)>,
}
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<Perip>> {
pub fn $new_chx(pin: impl Peripheral<P = impl $pin_trait<Perip>> + 'd) -> Self {
into_ref!(pin);
critical_section::with(|_| {
pin.set_low();
pin.set_as_af(pin.af_num(), AFType::OutputPushPull);
#[cfg(gpio_v2)]
pin.set_speed(crate::gpio::Speed::VeryHigh);
});
PwmPin {
_pin: pin.map_into(),
phantom: PhantomData,
}
}
}
impl<'d, Perip: Instance> ComplementaryPwmPin<'d, Perip, $channel<Perip>> {
pub fn $new_chx(pin: impl Peripheral<P = impl $complementary_pin_trait<Perip>> + 'd) -> Self {
into_ref!(pin);
critical_section::with(|_| {
pin.set_low();
pin.set_as_af(pin.af_num(), AFType::OutputPushPull);
#[cfg(gpio_v2)]
pin.set_speed(crate::gpio::Speed::VeryHigh);
});
ComplementaryPwmPin {
_pin: pin.map_into(),
phantom: PhantomData,
}
}
}
impl<T: Instance> sealed::AdvancedChannel<T> for $channel<T> {
fn raw() -> usize {
$ch_num
}
}
impl<T: Instance> AdvancedChannel<T> for $channel<T> {}
};
}
advanced_channel_impl!(new_cha, ChA, 0, ChannelAPin, ChannelAComplementaryPin);
advanced_channel_impl!(new_chb, ChB, 1, ChannelBPin, ChannelBComplementaryPin);
advanced_channel_impl!(new_chc, ChC, 2, ChannelCPin, ChannelCComplementaryPin);
advanced_channel_impl!(new_chd, ChD, 3, ChannelDPin, ChannelDComplementaryPin);
advanced_channel_impl!(new_che, ChE, 4, ChannelEPin, ChannelEComplementaryPin);
/// Struct used to divide a high resolution timer into multiple channels
pub struct AdvancedPwm<'d, T: Instance> {
_inner: PeripheralRef<'d, T>,
pub master: Master<T>,
pub burst_controller: BurstController<T>,
pub ch_a: ChA<T>,
pub ch_b: ChB<T>,
pub ch_c: ChC<T>,
pub ch_d: ChD<T>,
pub ch_e: ChE<T>,
}
impl<'d, T: Instance> AdvancedPwm<'d, T> {
pub fn new(
tim: impl Peripheral<P = T> + 'd,
_cha: Option<PwmPin<'d, T, ChA<T>>>,
_chan: Option<ComplementaryPwmPin<'d, T, ChA<T>>>,
_chb: Option<PwmPin<'d, T, ChB<T>>>,
_chbn: Option<ComplementaryPwmPin<'d, T, ChB<T>>>,
_chc: Option<PwmPin<'d, T, ChC<T>>>,
_chcn: Option<ComplementaryPwmPin<'d, T, ChC<T>>>,
_chd: Option<PwmPin<'d, T, ChD<T>>>,
_chdn: Option<ComplementaryPwmPin<'d, T, ChD<T>>>,
_che: Option<PwmPin<'d, T, ChE<T>>>,
_chen: Option<ComplementaryPwmPin<'d, T, ChE<T>>>,
) -> Self {
Self::new_inner(tim)
}
fn new_inner(tim: impl Peripheral<P = T> + 'd) -> Self {
into_ref!(tim);
T::enable();
<T as crate::rcc::sealed::RccPeripheral>::reset();
// // Enable and and stabilize the DLL
// T::regs().dllcr().modify(|w| {
// // w.set_calen(true);
// // w.set_calrte(11);
// w.set_cal(true);
// });
//
// debug!("wait for dll calibration");
// while !T::regs().isr().read().dllrdy() {}
//
// debug!("dll calibration complete");
Self {
_inner: tim,
master: Master { phantom: PhantomData },
burst_controller: BurstController { phantom: PhantomData },
ch_a: ChA { phantom: PhantomData },
ch_b: ChB { phantom: PhantomData },
ch_c: ChC { phantom: PhantomData },
ch_d: ChD { phantom: PhantomData },
ch_e: ChE { phantom: PhantomData },
}
}
}
impl<T: Instance> BurstController<T> {
pub fn set_source(&mut self, _source: Source) {
todo!("burst mode control registers not implemented")
}
}
/// Represents a fixed-frequency bridge converter
///
/// Our implementation of the bridge converter uses a single channel and three compare registers,
/// allowing implementation of a synchronous buck or boost converter in continuous or discontinuous
/// conduction mode.
///
/// It is important to remember that in synchronous topologies, energy can flow in reverse during
/// light loading conditions, and that the low-side switch must be active for a short time to drive
/// a bootstrapped high-side switch.
pub struct BridgeConverter<T: Instance, C: AdvancedChannel<T>> {
timer: PhantomData<T>,
channel: PhantomData<C>,
dead_time: u16,
primary_duty: u16,
min_secondary_duty: u16,
max_secondary_duty: u16,
}
impl<T: Instance, C: AdvancedChannel<T>> BridgeConverter<T, C> {
pub fn new(_channel: C, frequency: Hertz) -> Self {
use crate::pac::hrtim::vals::{Activeeffect, Inactiveeffect};
T::set_channel_frequency(C::raw(), frequency);
// Always enable preload
T::regs().tim(C::raw()).cr().modify(|w| {
w.set_preen(true);
w.set_repu(true);
w.set_cont(true);
});
// Enable timer outputs
T::regs().oenr().modify(|w| {
w.set_t1oen(C::raw(), true);
w.set_t2oen(C::raw(), true);
});
// The dead-time generation unit cannot be used because it forces the other output
// to be completely complementary to the first output, which restricts certain waveforms
// Therefore, software-implemented dead time must be used when setting the duty cycles
// Set output 1 to active on a period event
T::regs()
.tim(C::raw())
.setr(0)
.modify(|w| w.set_per(Activeeffect::SETACTIVE));
// Set output 1 to inactive on a compare 1 event
T::regs()
.tim(C::raw())
.rstr(0)
.modify(|w| w.set_cmp(0, Inactiveeffect::SETINACTIVE));
// Set output 2 to active on a compare 2 event
T::regs()
.tim(C::raw())
.setr(1)
.modify(|w| w.set_cmp(1, Activeeffect::SETACTIVE));
// Set output 2 to inactive on a compare 3 event
T::regs()
.tim(C::raw())
.rstr(1)
.modify(|w| w.set_cmp(2, Inactiveeffect::SETINACTIVE));
Self {
timer: PhantomData,
channel: PhantomData,
dead_time: 0,
primary_duty: 0,
min_secondary_duty: 0,
max_secondary_duty: 0,
}
}
pub fn start(&mut self) {
T::regs().mcr().modify(|w| w.set_tcen(C::raw(), true));
}
pub fn stop(&mut self) {
T::regs().mcr().modify(|w| w.set_tcen(C::raw(), false));
}
pub fn enable_burst_mode(&mut self) {
T::regs().tim(C::raw()).outr().modify(|w| {
// Enable Burst Mode
w.set_idlem(0, true);
w.set_idlem(1, true);
// Set output to active during the burst
w.set_idles(0, true);
w.set_idles(1, true);
})
}
pub fn disable_burst_mode(&mut self) {
T::regs().tim(C::raw()).outr().modify(|w| {
// Disable Burst Mode
w.set_idlem(0, false);
w.set_idlem(1, false);
})
}
fn update_primary_duty_or_dead_time(&mut self) {
self.min_secondary_duty = self.primary_duty + self.dead_time;
T::regs().tim(C::raw()).cmp(0).modify(|w| w.set_cmp(self.primary_duty));
T::regs()
.tim(C::raw())
.cmp(1)
.modify(|w| w.set_cmp(self.min_secondary_duty));
}
/// Set the dead time as a proportion of the maximum compare value
pub fn set_dead_time(&mut self, dead_time: u16) {
self.dead_time = dead_time;
self.max_secondary_duty = self.get_max_compare_value() - dead_time;
self.update_primary_duty_or_dead_time();
}
/// Get the maximum compare value of a duty cycle
pub fn get_max_compare_value(&mut self) -> u16 {
T::regs().tim(C::raw()).per().read().per()
}
/// The primary duty is the period in which the primary switch is active
///
/// In the case of a buck converter, this is the high-side switch
/// In the case of a boost converter, this is the low-side switch
pub fn set_primary_duty(&mut self, primary_duty: u16) {
self.primary_duty = primary_duty;
self.update_primary_duty_or_dead_time();
}
/// The secondary duty is the period in any switch is active
///
/// If less than or equal to the primary duty, the secondary switch will be active for one tick
/// If a fully complementary output is desired, the secondary duty can be set to the max compare
pub fn set_secondary_duty(&mut self, secondary_duty: u16) {
let secondary_duty = if secondary_duty > self.max_secondary_duty {
self.max_secondary_duty
} else if secondary_duty <= self.min_secondary_duty {
self.min_secondary_duty + 1
} else {
secondary_duty
};
T::regs().tim(C::raw()).cmp(2).modify(|w| w.set_cmp(secondary_duty));
}
}
/// Represents a variable-frequency resonant converter
///
/// This implementation of a resonsant converter is appropriate for a half or full bridge,
/// but does not include secondary rectification, which is appropriate for applications
/// with a low-voltage on the secondary side.
pub struct ResonantConverter<T: Instance, C: AdvancedChannel<T>> {
timer: PhantomData<T>,
channel: PhantomData<C>,
min_period: u16,
max_period: u16,
}
impl<T: Instance, C: AdvancedChannel<T>> ResonantConverter<T, C> {
pub fn new(_channel: C, min_frequency: Hertz, max_frequency: Hertz) -> Self {
T::set_channel_frequency(C::raw(), min_frequency);
// Always enable preload
T::regs().tim(C::raw()).cr().modify(|w| {
w.set_preen(true);
w.set_repu(true);
w.set_cont(true);
w.set_half(true);
});
// Enable timer outputs
T::regs().oenr().modify(|w| {
w.set_t1oen(C::raw(), true);
w.set_t2oen(C::raw(), true);
});
// Dead-time generator can be used in this case because the primary fets
// of a resonant converter are always complementary
T::regs().tim(C::raw()).outr().modify(|w| w.set_dten(true));
let max_period = T::regs().tim(C::raw()).per().read().per();
let min_period = max_period * (min_frequency.0 / max_frequency.0) as u16;
Self {
timer: PhantomData,
channel: PhantomData,
min_period: min_period,
max_period: max_period,
}
}
/// Set the dead time as a proportion of the maximum compare value
pub fn set_dead_time(&mut self, value: u16) {
T::set_channel_dead_time(C::raw(), value);
}
pub fn set_period(&mut self, period: u16) {
assert!(period < self.max_period);
assert!(period > self.min_period);
T::regs().tim(C::raw()).per().modify(|w| w.set_per(period));
}
/// Get the minimum compare value of a duty cycle
pub fn get_min_period(&mut self) -> u16 {
self.min_period
}
/// Get the maximum compare value of a duty cycle
pub fn get_max_period(&mut self) -> u16 {
self.max_period
}
}
pin_trait!(ChannelAPin, Instance);
pin_trait!(ChannelAComplementaryPin, Instance);
pin_trait!(ChannelBPin, Instance);
pin_trait!(ChannelBComplementaryPin, Instance);
pin_trait!(ChannelCPin, Instance);
pin_trait!(ChannelCComplementaryPin, Instance);
pin_trait!(ChannelDPin, Instance);
pin_trait!(ChannelDComplementaryPin, Instance);
pin_trait!(ChannelEPin, Instance);
pin_trait!(ChannelEComplementaryPin, Instance);

View File

@ -0,0 +1,193 @@
use crate::rcc::sealed::RccPeripheral;
use crate::time::Hertz;
#[derive(Clone, Copy)]
pub(crate) enum Prescaler {
Div1,
Div2,
Div4,
Div8,
Div16,
Div32,
Div64,
Div128,
}
impl From<Prescaler> for u32 {
fn from(val: Prescaler) -> Self {
match val {
Prescaler::Div1 => 1,
Prescaler::Div2 => 2,
Prescaler::Div4 => 4,
Prescaler::Div8 => 8,
Prescaler::Div16 => 16,
Prescaler::Div32 => 32,
Prescaler::Div64 => 64,
Prescaler::Div128 => 128,
}
}
}
impl From<Prescaler> for u8 {
fn from(val: Prescaler) -> Self {
match val {
Prescaler::Div1 => 0b000,
Prescaler::Div2 => 0b001,
Prescaler::Div4 => 0b010,
Prescaler::Div8 => 0b011,
Prescaler::Div16 => 0b100,
Prescaler::Div32 => 0b101,
Prescaler::Div64 => 0b110,
Prescaler::Div128 => 0b111,
}
}
}
impl From<u8> for Prescaler {
fn from(val: u8) -> Self {
match val {
0b000 => Prescaler::Div1,
0b001 => Prescaler::Div2,
0b010 => Prescaler::Div4,
0b011 => Prescaler::Div8,
0b100 => Prescaler::Div16,
0b101 => Prescaler::Div32,
0b110 => Prescaler::Div64,
0b111 => Prescaler::Div128,
_ => unreachable!(),
}
}
}
impl Prescaler {
pub fn compute_min_high_res(val: u32) -> Self {
*[
Prescaler::Div1,
Prescaler::Div2,
Prescaler::Div4,
Prescaler::Div8,
Prescaler::Div16,
Prescaler::Div32,
Prescaler::Div64,
Prescaler::Div128,
]
.iter()
.skip_while(|psc| <Prescaler as Into<u32>>::into(**psc) <= val)
.next()
.unwrap()
}
pub fn compute_min_low_res(val: u32) -> Self {
*[Prescaler::Div32, Prescaler::Div64, Prescaler::Div128]
.iter()
.skip_while(|psc| <Prescaler as Into<u32>>::into(**psc) <= val)
.next()
.unwrap()
}
}
pub(crate) mod sealed {
use super::*;
pub trait Instance: RccPeripheral {
fn regs() -> crate::pac::hrtim::Hrtim;
fn set_master_frequency(frequency: Hertz);
fn set_channel_frequency(channnel: usize, frequency: Hertz);
/// Set the dead time as a proportion of max_duty
fn set_channel_dead_time(channnel: usize, dead_time: u16);
// fn enable_outputs(enable: bool);
//
// fn enable_channel(&mut self, channel: usize, enable: bool);
}
}
pub trait Instance: sealed::Instance + 'static {}
foreach_interrupt! {
($inst:ident, hrtim, HRTIM, MASTER, $irq:ident) => {
impl sealed::Instance for crate::peripherals::$inst {
fn regs() -> crate::pac::hrtim::Hrtim {
crate::pac::$inst
}
fn set_master_frequency(frequency: Hertz) {
use crate::rcc::sealed::RccPeripheral;
let f = frequency.0;
let timer_f = Self::frequency().0;
let psc_min = (timer_f / f) / (u16::MAX as u32 / 32);
let psc = if Self::regs().isr().read().dllrdy() {
Prescaler::compute_min_high_res(psc_min)
} else {
Prescaler::compute_min_low_res(psc_min)
};
let psc_val: u32 = psc.into();
let timer_f = 32 * (timer_f / psc_val);
let per: u16 = (timer_f / f) as u16;
let regs = Self::regs();
regs.mcr().modify(|w| w.set_ckpsc(psc.into()));
regs.mper().modify(|w| w.set_mper(per));
}
fn set_channel_frequency(channel: usize, frequency: Hertz) {
use crate::rcc::sealed::RccPeripheral;
let f = frequency.0;
let timer_f = Self::frequency().0;
let psc_min = (timer_f / f) / (u16::MAX as u32 / 32);
let psc = if Self::regs().isr().read().dllrdy() {
Prescaler::compute_min_high_res(psc_min)
} else {
Prescaler::compute_min_low_res(psc_min)
};
let psc_val: u32 = psc.into();
let timer_f = 32 * (timer_f / psc_val);
let per: u16 = (timer_f / f) as u16;
let regs = Self::regs();
regs.tim(channel).cr().modify(|w| w.set_ckpsc(psc.into()));
regs.tim(channel).per().modify(|w| w.set_per(per));
}
fn set_channel_dead_time(channel: usize, dead_time: u16) {
let regs = Self::regs();
let channel_psc: Prescaler = regs.tim(channel).cr().read().ckpsc().into();
let psc_val: u32 = channel_psc.into();
// The dead-time base clock runs 4 times slower than the hrtim base clock
// u9::MAX = 511
let psc_min = (psc_val * dead_time as u32) / (4 * 511);
let psc = if Self::regs().isr().read().dllrdy() {
Prescaler::compute_min_high_res(psc_min)
} else {
Prescaler::compute_min_low_res(psc_min)
};
let dt_psc_val: u32 = psc.into();
let dt_val = (dt_psc_val * dead_time as u32) / (4 * psc_val);
regs.tim(channel).dt().modify(|w| {
w.set_dtprsc(psc.into());
w.set_dtf(dt_val as u16);
w.set_dtr(dt_val as u16);
});
}
}
impl Instance for crate::peripherals::$inst {
}
};
}

View File

@ -6,8 +6,8 @@ use super::{Error, I2c, Instance};
///
/// This is useful for recovering from a shorted bus or a device stuck in a clock stretching state.
/// A regular [I2c] would freeze until condition is removed.
pub struct TimeoutI2c<'d, T: Instance, TXDMA, RXDMA> {
i2c: &'d mut I2c<'d, T, TXDMA, RXDMA>,
pub struct TimeoutI2c<'a, 'd: 'a, T: Instance, TXDMA, RXDMA> {
i2c: &'a mut I2c<'d, T, TXDMA, RXDMA>,
timeout: Duration,
}
@ -22,8 +22,8 @@ fn timeout_fn(timeout: Duration) -> impl Fn() -> Result<(), Error> {
}
}
impl<'d, T: Instance, TXDMA, RXDMA> TimeoutI2c<'d, T, TXDMA, RXDMA> {
pub fn new(i2c: &'d mut I2c<'d, T, TXDMA, RXDMA>, timeout: Duration) -> Self {
impl<'a, 'd, T: Instance, TXDMA, RXDMA> TimeoutI2c<'a, 'd, T, TXDMA, RXDMA> {
pub fn new(i2c: &'a mut I2c<'d, T, TXDMA, RXDMA>, timeout: Duration) -> Self {
Self { i2c, timeout }
}
@ -65,7 +65,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> TimeoutI2c<'d, T, TXDMA, RXDMA> {
}
}
impl<'d, T: Instance, TXDMA, RXDMA> embedded_hal_02::blocking::i2c::Read for TimeoutI2c<'d, T, TXDMA, RXDMA> {
impl<'a, 'd, T: Instance, TXDMA, RXDMA> embedded_hal_02::blocking::i2c::Read for TimeoutI2c<'a, 'd, T, TXDMA, RXDMA> {
type Error = Error;
fn read(&mut self, addr: u8, read: &mut [u8]) -> Result<(), Self::Error> {
@ -73,7 +73,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> embedded_hal_02::blocking::i2c::Read for Tim
}
}
impl<'d, T: Instance, TXDMA, RXDMA> embedded_hal_02::blocking::i2c::Write for TimeoutI2c<'d, T, TXDMA, RXDMA> {
impl<'a, 'd, T: Instance, TXDMA, RXDMA> embedded_hal_02::blocking::i2c::Write for TimeoutI2c<'a, 'd, T, TXDMA, RXDMA> {
type Error = Error;
fn write(&mut self, addr: u8, write: &[u8]) -> Result<(), Self::Error> {
@ -81,7 +81,9 @@ impl<'d, T: Instance, TXDMA, RXDMA> embedded_hal_02::blocking::i2c::Write for Ti
}
}
impl<'d, T: Instance, TXDMA, RXDMA> embedded_hal_02::blocking::i2c::WriteRead for TimeoutI2c<'d, T, TXDMA, RXDMA> {
impl<'a, 'd, T: Instance, TXDMA, RXDMA> embedded_hal_02::blocking::i2c::WriteRead
for TimeoutI2c<'a, 'd, T, TXDMA, RXDMA>
{
type Error = Error;
fn write_read(&mut self, addr: u8, write: &[u8], read: &mut [u8]) -> Result<(), Self::Error> {
@ -93,11 +95,11 @@ impl<'d, T: Instance, TXDMA, RXDMA> embedded_hal_02::blocking::i2c::WriteRead fo
mod eh1 {
use super::*;
impl<'d, T: Instance, TXDMA, RXDMA> embedded_hal_1::i2c::ErrorType for TimeoutI2c<'d, T, TXDMA, RXDMA> {
impl<'a, 'd, T: Instance, TXDMA, RXDMA> embedded_hal_1::i2c::ErrorType for TimeoutI2c<'a, 'd, T, TXDMA, RXDMA> {
type Error = Error;
}
impl<'d, T: Instance, TXDMA, RXDMA> embedded_hal_1::i2c::I2c for TimeoutI2c<'d, T, TXDMA, RXDMA> {
impl<'a, 'd, T: Instance, TXDMA, RXDMA> embedded_hal_1::i2c::I2c for TimeoutI2c<'a, 'd, T, TXDMA, RXDMA> {
fn read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Self::Error> {
self.blocking_read(address, read)
}

View File

@ -1,7 +1,7 @@
use core::marker::PhantomData;
use embassy_embedded_hal::SetConfig;
use embassy_hal_common::{into_ref, PeripheralRef};
use embassy_hal_internal::{into_ref, PeripheralRef};
use crate::dma::NoDma;
use crate::gpio::sealed::AFType;

View File

@ -4,8 +4,8 @@ use core::marker::PhantomData;
use core::task::Poll;
use embassy_embedded_hal::SetConfig;
use embassy_hal_common::drop::OnDrop;
use embassy_hal_common::{into_ref, PeripheralRef};
use embassy_hal_internal::drop::OnDrop;
use embassy_hal_internal::{into_ref, PeripheralRef};
use embassy_sync::waitqueue::AtomicWaker;
use crate::dma::{NoDma, Transfer};

View File

@ -1,4 +1,4 @@
use embassy_hal_common::into_ref;
use embassy_hal_internal::into_ref;
use crate::gpio::sealed::{AFType, Pin as _};
use crate::gpio::AnyPin;
@ -165,7 +165,9 @@ impl<'d, T: Instance, Tx, Rx> I2S<'d, T, Tx, Rx> {
mck.set_as_af(mck.af_num(), AFType::OutputPushPull);
mck.set_speed(crate::gpio::Speed::VeryHigh);
let spi = Spi::new_internal(peri, txdma, rxdma, freq, SpiConfig::default());
let mut spi_cfg = SpiConfig::default();
spi_cfg.frequency = freq;
let spi = Spi::new_internal(peri, txdma, rxdma, spi_cfg);
#[cfg(all(rcc_f4, not(stm32f410)))]
let pclk = unsafe { get_freqs() }.plli2s.unwrap();

View File

@ -1,6 +1,9 @@
#![cfg_attr(not(test), no_std)]
#![cfg_attr(feature = "nightly", feature(async_fn_in_trait, impl_trait_projections))]
//! ## Feature flags
#![doc = document_features::document_features!(feature_label = r#"<span class="stab portability"><code>{feature}</code></span>"#)]
// This must go FIRST so that all the other modules see its macros.
pub mod fmt;
include!(concat!(env!("OUT_DIR"), "/_macros.rs"));
@ -23,6 +26,8 @@ pub mod timer;
pub mod adc;
#[cfg(can)]
pub mod can;
#[cfg(crc)]
pub mod crc;
#[cfg(dac)]
pub mod dac;
#[cfg(dcmi)]
@ -31,19 +36,17 @@ pub mod dcmi;
pub mod eth;
#[cfg(feature = "exti")]
pub mod exti;
pub mod flash;
#[cfg(fmc)]
pub mod fmc;
#[cfg(hrtim_v1)]
pub mod hrtim;
#[cfg(i2c)]
pub mod i2c;
#[cfg(crc)]
pub mod crc;
pub mod flash;
#[cfg(all(spi_v1, rcc_f4))]
pub mod i2s;
#[cfg(stm32wb)]
pub mod ipcc;
pub mod pwm;
#[cfg(quadspi)]
pub mod qspi;
#[cfg(rng)]
@ -79,7 +82,7 @@ pub use crate::_generated::interrupt;
/// This defines the right interrupt handlers, and creates a unit struct (like `struct Irqs;`)
/// and implements the right [`Binding`]s for it. You can pass this struct to drivers to
/// prove at compile-time that the right interrupts have been bound.
// developer note: this macro can't be in `embassy-hal-common` due to the use of `$crate`.
// developer note: this macro can't be in `embassy-hal-internal` due to the use of `$crate`.
#[macro_export]
macro_rules! bind_interrupts {
($vis:vis struct $name:ident { $($irq:ident => $($handler:ty),*;)* }) => {
@ -103,7 +106,7 @@ macro_rules! bind_interrupts {
// Reexports
pub use _generated::{peripherals, Peripherals};
pub use embassy_hal_common::{into_ref, Peripheral, PeripheralRef};
pub use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef};
#[cfg(feature = "unstable-pac")]
pub use stm32_metapac as pac;
#[cfg(not(feature = "unstable-pac"))]

View File

@ -1,269 +0,0 @@
pub mod complementary_pwm;
pub mod simple_pwm;
use stm32_metapac::timer::vals::Ckd;
#[cfg(feature = "unstable-pac")]
pub mod low_level {
pub use super::sealed::*;
}
#[derive(Clone, Copy)]
pub enum Channel {
Ch1,
Ch2,
Ch3,
Ch4,
}
impl Channel {
pub fn raw(&self) -> usize {
match self {
Channel::Ch1 => 0,
Channel::Ch2 => 1,
Channel::Ch3 => 2,
Channel::Ch4 => 3,
}
}
}
#[derive(Clone, Copy)]
pub enum OutputCompareMode {
Frozen,
ActiveOnMatch,
InactiveOnMatch,
Toggle,
ForceInactive,
ForceActive,
PwmMode1,
PwmMode2,
}
impl From<OutputCompareMode> for stm32_metapac::timer::vals::Ocm {
fn from(mode: OutputCompareMode) -> Self {
match mode {
OutputCompareMode::Frozen => stm32_metapac::timer::vals::Ocm::FROZEN,
OutputCompareMode::ActiveOnMatch => stm32_metapac::timer::vals::Ocm::ACTIVEONMATCH,
OutputCompareMode::InactiveOnMatch => stm32_metapac::timer::vals::Ocm::INACTIVEONMATCH,
OutputCompareMode::Toggle => stm32_metapac::timer::vals::Ocm::TOGGLE,
OutputCompareMode::ForceInactive => stm32_metapac::timer::vals::Ocm::FORCEINACTIVE,
OutputCompareMode::ForceActive => stm32_metapac::timer::vals::Ocm::FORCEACTIVE,
OutputCompareMode::PwmMode1 => stm32_metapac::timer::vals::Ocm::PWMMODE1,
OutputCompareMode::PwmMode2 => stm32_metapac::timer::vals::Ocm::PWMMODE2,
}
}
}
pub(crate) mod sealed {
use super::*;
pub trait CaptureCompare16bitInstance: crate::timer::sealed::GeneralPurpose16bitInstance {
/// Global output enable. Does not do anything on non-advanced timers.
fn enable_outputs(&mut self, enable: bool);
fn set_output_compare_mode(&mut self, channel: Channel, mode: OutputCompareMode);
fn enable_channel(&mut self, channel: Channel, enable: bool);
fn set_compare_value(&mut self, channel: Channel, value: u16);
fn get_max_compare_value(&self) -> u16;
}
pub trait ComplementaryCaptureCompare16bitInstance: CaptureCompare16bitInstance {
fn set_dead_time_clock_division(&mut self, value: Ckd);
fn set_dead_time_value(&mut self, value: u8);
fn enable_complementary_channel(&mut self, channel: Channel, enable: bool);
}
pub trait CaptureCompare32bitInstance: crate::timer::sealed::GeneralPurpose32bitInstance {
fn set_output_compare_mode(&mut self, channel: Channel, mode: OutputCompareMode);
fn enable_channel(&mut self, channel: Channel, enable: bool);
fn set_compare_value(&mut self, channel: Channel, value: u32);
fn get_max_compare_value(&self) -> u32;
}
}
pub trait CaptureCompare16bitInstance:
sealed::CaptureCompare16bitInstance + crate::timer::GeneralPurpose16bitInstance + 'static
{
}
pub trait ComplementaryCaptureCompare16bitInstance:
sealed::ComplementaryCaptureCompare16bitInstance + crate::timer::AdvancedControlInstance + 'static
{
}
pub trait CaptureCompare32bitInstance:
sealed::CaptureCompare32bitInstance + CaptureCompare16bitInstance + crate::timer::GeneralPurpose32bitInstance + 'static
{
}
#[allow(unused)]
macro_rules! impl_compare_capable_16bit {
($inst:ident) => {
impl crate::pwm::sealed::CaptureCompare16bitInstance for crate::peripherals::$inst {
fn enable_outputs(&mut self, _enable: bool) {}
fn set_output_compare_mode(&mut self, channel: crate::pwm::Channel, mode: OutputCompareMode) {
use crate::timer::sealed::GeneralPurpose16bitInstance;
let r = Self::regs_gp16();
let raw_channel: usize = channel.raw();
r.ccmr_output(raw_channel / 2)
.modify(|w| w.set_ocm(raw_channel % 2, mode.into()));
}
fn enable_channel(&mut self, channel: Channel, enable: bool) {
use crate::timer::sealed::GeneralPurpose16bitInstance;
Self::regs_gp16()
.ccer()
.modify(|w| w.set_cce(channel.raw(), enable));
}
fn set_compare_value(&mut self, channel: Channel, value: u16) {
use crate::timer::sealed::GeneralPurpose16bitInstance;
Self::regs_gp16().ccr(channel.raw()).modify(|w| w.set_ccr(value));
}
fn get_max_compare_value(&self) -> u16 {
use crate::timer::sealed::GeneralPurpose16bitInstance;
Self::regs_gp16().arr().read().arr()
}
}
};
}
foreach_interrupt! {
($inst:ident, timer, TIM_GP16, UP, $irq:ident) => {
impl_compare_capable_16bit!($inst);
impl CaptureCompare16bitInstance for crate::peripherals::$inst {
}
};
($inst:ident, timer, TIM_GP32, UP, $irq:ident) => {
impl_compare_capable_16bit!($inst);
impl crate::pwm::sealed::CaptureCompare32bitInstance for crate::peripherals::$inst {
fn set_output_compare_mode(
&mut self,
channel: crate::pwm::Channel,
mode: OutputCompareMode,
) {
use crate::timer::sealed::GeneralPurpose32bitInstance;
let raw_channel = channel.raw();
Self::regs_gp32().ccmr_output(raw_channel / 2).modify(|w| w.set_ocm(raw_channel % 2, mode.into()));
}
fn enable_channel(&mut self, channel: Channel, enable: bool) {
use crate::timer::sealed::GeneralPurpose32bitInstance;
Self::regs_gp32().ccer().modify(|w| w.set_cce(channel.raw(), enable));
}
fn set_compare_value(&mut self, channel: Channel, value: u32) {
use crate::timer::sealed::GeneralPurpose32bitInstance;
Self::regs_gp32().ccr(channel.raw()).modify(|w| w.set_ccr(value));
}
fn get_max_compare_value(&self) -> u32 {
use crate::timer::sealed::GeneralPurpose32bitInstance;
Self::regs_gp32().arr().read().arr() as u32
}
}
impl CaptureCompare16bitInstance for crate::peripherals::$inst {
}
impl CaptureCompare32bitInstance for crate::peripherals::$inst {
}
};
($inst:ident, timer, TIM_ADV, UP, $irq:ident) => {
impl crate::pwm::sealed::CaptureCompare16bitInstance for crate::peripherals::$inst {
fn enable_outputs(&mut self, enable: bool) {
use crate::timer::sealed::AdvancedControlInstance;
let r = Self::regs_advanced();
r.bdtr().modify(|w| w.set_moe(enable));
}
fn set_output_compare_mode(
&mut self,
channel: crate::pwm::Channel,
mode: OutputCompareMode,
) {
use crate::timer::sealed::AdvancedControlInstance;
let r = Self::regs_advanced();
let raw_channel: usize = channel.raw();
r.ccmr_output(raw_channel / 2)
.modify(|w| w.set_ocm(raw_channel % 2, mode.into()));
}
fn enable_channel(&mut self, channel: Channel, enable: bool) {
use crate::timer::sealed::AdvancedControlInstance;
Self::regs_advanced()
.ccer()
.modify(|w| w.set_cce(channel.raw(), enable));
}
fn set_compare_value(&mut self, channel: Channel, value: u16) {
use crate::timer::sealed::AdvancedControlInstance;
Self::regs_advanced()
.ccr(channel.raw())
.modify(|w| w.set_ccr(value));
}
fn get_max_compare_value(&self) -> u16 {
use crate::timer::sealed::AdvancedControlInstance;
Self::regs_advanced().arr().read().arr()
}
}
impl CaptureCompare16bitInstance for crate::peripherals::$inst {
}
impl crate::pwm::sealed::ComplementaryCaptureCompare16bitInstance for crate::peripherals::$inst {
fn set_dead_time_clock_division(&mut self, value: Ckd) {
use crate::timer::sealed::AdvancedControlInstance;
Self::regs_advanced().cr1().modify(|w| w.set_ckd(value));
}
fn set_dead_time_value(&mut self, value: u8) {
use crate::timer::sealed::AdvancedControlInstance;
Self::regs_advanced().bdtr().modify(|w| w.set_dtg(value));
}
fn enable_complementary_channel(&mut self, channel: Channel, enable: bool) {
use crate::timer::sealed::AdvancedControlInstance;
Self::regs_advanced()
.ccer()
.modify(|w| w.set_ccne(channel.raw(), enable));
}
}
impl ComplementaryCaptureCompare16bitInstance for crate::peripherals::$inst {
}
};
}
pin_trait!(Channel1Pin, CaptureCompare16bitInstance);
pin_trait!(Channel1ComplementaryPin, CaptureCompare16bitInstance);
pin_trait!(Channel2Pin, CaptureCompare16bitInstance);
pin_trait!(Channel2ComplementaryPin, CaptureCompare16bitInstance);
pin_trait!(Channel3Pin, CaptureCompare16bitInstance);
pin_trait!(Channel3ComplementaryPin, CaptureCompare16bitInstance);
pin_trait!(Channel4Pin, CaptureCompare16bitInstance);
pin_trait!(Channel4ComplementaryPin, CaptureCompare16bitInstance);
pin_trait!(ExternalTriggerPin, CaptureCompare16bitInstance);
pin_trait!(BreakInputPin, CaptureCompare16bitInstance);
pin_trait!(BreakInputComparator1Pin, CaptureCompare16bitInstance);
pin_trait!(BreakInputComparator2Pin, CaptureCompare16bitInstance);
pin_trait!(BreakInput2Pin, CaptureCompare16bitInstance);
pin_trait!(BreakInput2Comparator1Pin, CaptureCompare16bitInstance);
pin_trait!(BreakInput2Comparator2Pin, CaptureCompare16bitInstance);

View File

@ -2,7 +2,7 @@
pub mod enums;
use embassy_hal_common::{into_ref, PeripheralRef};
use embassy_hal_internal::{into_ref, PeripheralRef};
use enums::*;
use crate::dma::Transfer;

View File

@ -1,5 +1,6 @@
pub use super::common::{AHBPrescaler, APBPrescaler};
use crate::pac::flash::vals::Latency;
use crate::pac::rcc::vals::{Hpre, Hsidiv, Ppre, Sw};
use crate::pac::rcc::vals::{Hsidiv, Ppre, Sw};
use crate::pac::{FLASH, RCC};
use crate::rcc::{set_freqs, Clocks};
use crate::time::Hertz;
@ -45,58 +46,6 @@ impl Into<Hsidiv> for HSIPrescaler {
}
}
/// AHB prescaler
#[derive(Clone, Copy, PartialEq)]
pub enum AHBPrescaler {
NotDivided,
Div2,
Div4,
Div8,
Div16,
Div64,
Div128,
Div256,
Div512,
}
/// APB prescaler
#[derive(Clone, Copy)]
pub enum APBPrescaler {
NotDivided,
Div2,
Div4,
Div8,
Div16,
}
impl Into<Ppre> for APBPrescaler {
fn into(self) -> Ppre {
match self {
APBPrescaler::NotDivided => Ppre::DIV1,
APBPrescaler::Div2 => Ppre::DIV2,
APBPrescaler::Div4 => Ppre::DIV4,
APBPrescaler::Div8 => Ppre::DIV8,
APBPrescaler::Div16 => Ppre::DIV16,
}
}
}
impl Into<Hpre> for AHBPrescaler {
fn into(self) -> Hpre {
match self {
AHBPrescaler::NotDivided => Hpre::DIV1,
AHBPrescaler::Div2 => Hpre::DIV2,
AHBPrescaler::Div4 => Hpre::DIV4,
AHBPrescaler::Div8 => Hpre::DIV8,
AHBPrescaler::Div16 => Hpre::DIV16,
AHBPrescaler::Div64 => Hpre::DIV64,
AHBPrescaler::Div128 => Hpre::DIV128,
AHBPrescaler::Div256 => Hpre::DIV256,
AHBPrescaler::Div512 => Hpre::DIV512,
}
}
}
/// Clocks configutation
pub struct Config {
pub mux: ClockSrc,

View File

@ -0,0 +1,174 @@
use core::ops::Div;
#[allow(unused_imports)]
use crate::pac::rcc;
use crate::time::Hertz;
/// Voltage Scale
///
/// Represents the voltage range feeding the CPU core. The maximum core
/// clock frequency depends on this value.
///
/// Scale0 represents the highest voltage range
#[derive(Copy, Clone, PartialEq)]
pub enum VoltageScale {
Scale0,
Scale1,
#[cfg(not(any(rcc_wl5, rcc_wle)))]
Scale2,
#[cfg(not(any(rcc_wl5, rcc_wle)))]
Scale3,
}
/// AHB prescaler
#[derive(Clone, Copy, PartialEq)]
pub enum AHBPrescaler {
NotDivided,
Div2,
#[cfg(any(rcc_wb, rcc_wl5, rcc_wle))]
Div3,
Div4,
#[cfg(any(rcc_wb, rcc_wl5, rcc_wle))]
Div5,
#[cfg(any(rcc_wb, rcc_wl5, rcc_wle))]
Div6,
Div8,
#[cfg(any(rcc_wb, rcc_wl5, rcc_wle))]
Div10,
Div16,
#[cfg(any(rcc_wb, rcc_wl5, rcc_wle))]
Div32,
Div64,
Div128,
Div256,
Div512,
}
impl Div<AHBPrescaler> for Hertz {
type Output = Hertz;
fn div(self, rhs: AHBPrescaler) -> Self::Output {
let divisor = match rhs {
AHBPrescaler::NotDivided => 1,
AHBPrescaler::Div2 => 2,
#[cfg(any(rcc_wb, rcc_wl5, rcc_wle))]
AHBPrescaler::Div3 => 3,
AHBPrescaler::Div4 => 4,
#[cfg(any(rcc_wb, rcc_wl5, rcc_wle))]
AHBPrescaler::Div5 => 5,
#[cfg(any(rcc_wb, rcc_wl5, rcc_wle))]
AHBPrescaler::Div6 => 6,
AHBPrescaler::Div8 => 8,
#[cfg(any(rcc_wb, rcc_wl5, rcc_wle))]
AHBPrescaler::Div10 => 10,
AHBPrescaler::Div16 => 16,
#[cfg(any(rcc_wb, rcc_wl5, rcc_wle))]
AHBPrescaler::Div32 => 32,
AHBPrescaler::Div64 => 64,
AHBPrescaler::Div128 => 128,
AHBPrescaler::Div256 => 256,
AHBPrescaler::Div512 => 512,
};
Hertz(self.0 / divisor)
}
}
#[cfg(not(any(rcc_g4, rcc_wb, rcc_wl5, rcc_wle)))]
impl From<AHBPrescaler> for rcc::vals::Hpre {
fn from(val: AHBPrescaler) -> rcc::vals::Hpre {
use rcc::vals::Hpre;
match val {
#[cfg(not(rcc_u5))]
AHBPrescaler::NotDivided => Hpre::DIV1,
#[cfg(rcc_u5)]
AHBPrescaler::NotDivided => Hpre::NONE,
AHBPrescaler::Div2 => Hpre::DIV2,
AHBPrescaler::Div4 => Hpre::DIV4,
AHBPrescaler::Div8 => Hpre::DIV8,
AHBPrescaler::Div16 => Hpre::DIV16,
AHBPrescaler::Div64 => Hpre::DIV64,
AHBPrescaler::Div128 => Hpre::DIV128,
AHBPrescaler::Div256 => Hpre::DIV256,
AHBPrescaler::Div512 => Hpre::DIV512,
}
}
}
#[cfg(any(rcc_wb, rcc_wl5, rcc_wle))]
impl From<AHBPrescaler> for u8 {
fn from(val: AHBPrescaler) -> u8 {
match val {
AHBPrescaler::NotDivided => 0x0,
AHBPrescaler::Div2 => 0x08,
AHBPrescaler::Div3 => 0x01,
AHBPrescaler::Div4 => 0x09,
AHBPrescaler::Div5 => 0x02,
AHBPrescaler::Div6 => 0x05,
AHBPrescaler::Div8 => 0x0a,
AHBPrescaler::Div10 => 0x06,
AHBPrescaler::Div16 => 0x0b,
AHBPrescaler::Div32 => 0x07,
AHBPrescaler::Div64 => 0x0c,
AHBPrescaler::Div128 => 0x0d,
AHBPrescaler::Div256 => 0x0e,
AHBPrescaler::Div512 => 0x0f,
}
}
}
/// APB prescaler
#[derive(Clone, Copy)]
pub enum APBPrescaler {
NotDivided,
Div2,
Div4,
Div8,
Div16,
}
impl Div<APBPrescaler> for Hertz {
type Output = Hertz;
fn div(self, rhs: APBPrescaler) -> Self::Output {
let divisor = match rhs {
APBPrescaler::NotDivided => 1,
APBPrescaler::Div2 => 2,
APBPrescaler::Div4 => 4,
APBPrescaler::Div8 => 8,
APBPrescaler::Div16 => 16,
};
Hertz(self.0 / divisor)
}
}
#[cfg(not(any(rcc_f1, rcc_f100, rcc_f1cl, rcc_g4, rcc_h7, rcc_h7ab, rcc_wb, rcc_wl5, rcc_wle)))]
impl From<APBPrescaler> for rcc::vals::Ppre {
fn from(val: APBPrescaler) -> rcc::vals::Ppre {
use rcc::vals::Ppre;
match val {
#[cfg(not(rcc_u5))]
APBPrescaler::NotDivided => Ppre::DIV1,
#[cfg(rcc_u5)]
APBPrescaler::NotDivided => Ppre::NONE,
APBPrescaler::Div2 => Ppre::DIV2,
APBPrescaler::Div4 => Ppre::DIV4,
APBPrescaler::Div8 => Ppre::DIV8,
APBPrescaler::Div16 => Ppre::DIV16,
}
}
}
#[cfg(any(rcc_wb, rcc_wl5, rcc_wle))]
impl From<APBPrescaler> for u8 {
fn from(val: APBPrescaler) -> u8 {
match val {
APBPrescaler::NotDivided => 1,
APBPrescaler::Div2 => 0x04,
APBPrescaler::Div4 => 0x05,
APBPrescaler::Div8 => 0x06,
APBPrescaler::Div16 => 0x07,
}
}
}

View File

@ -1,8 +1,9 @@
use core::convert::TryFrom;
use core::ops::{Div, Mul};
pub use super::common::{AHBPrescaler, APBPrescaler};
use crate::pac::flash::vals::Latency;
use crate::pac::rcc::vals::{Hpre, Pllp, Pllsrc, Ppre, Sw};
use crate::pac::rcc::vals::{Pllp, Pllsrc, Sw};
use crate::pac::{FLASH, RCC};
use crate::rcc::{set_freqs, Clocks};
use crate::time::Hertz;
@ -58,7 +59,7 @@ impl Default for PLLConfig {
impl PLLConfig {
pub fn clocks(&self, src_freq: Hertz) -> PLLClocks {
let in_freq = src_freq / self.pre_div;
let vco_freq = src_freq * self.mul / self.pre_div;
let vco_freq = Hertz((src_freq.0 as u64 * self.mul.0 as u64 / self.pre_div.0 as u64) as u32);
let main_freq = vco_freq / self.main_div;
let pll48_freq = vco_freq / self.pll48_div;
PLLClocks {
@ -200,114 +201,15 @@ pub struct PLLClocks {
pub pll48_freq: Hertz,
}
/// AHB prescaler
#[derive(Clone, Copy, PartialEq)]
pub enum AHBPrescaler {
NotDivided,
Div2,
Div4,
Div8,
Div16,
Div64,
Div128,
Div256,
Div512,
}
pub use super::common::VoltageScale;
impl Div<AHBPrescaler> for Hertz {
type Output = Hertz;
fn div(self, rhs: AHBPrescaler) -> Self::Output {
let divisor = match rhs {
AHBPrescaler::NotDivided => 1,
AHBPrescaler::Div2 => 2,
AHBPrescaler::Div4 => 4,
AHBPrescaler::Div8 => 8,
AHBPrescaler::Div16 => 16,
AHBPrescaler::Div64 => 64,
AHBPrescaler::Div128 => 128,
AHBPrescaler::Div256 => 256,
AHBPrescaler::Div512 => 512,
};
Hertz(self.0 / divisor)
}
}
/// APB prescaler
#[derive(Clone, Copy)]
pub enum APBPrescaler {
NotDivided,
Div2,
Div4,
Div8,
Div16,
}
impl Div<APBPrescaler> for Hertz {
type Output = Hertz;
fn div(self, rhs: APBPrescaler) -> Self::Output {
let divisor = match rhs {
APBPrescaler::NotDivided => 1,
APBPrescaler::Div2 => 2,
APBPrescaler::Div4 => 4,
APBPrescaler::Div8 => 8,
APBPrescaler::Div16 => 16,
};
Hertz(self.0 / divisor)
}
}
impl Into<Ppre> for APBPrescaler {
fn into(self) -> Ppre {
match self {
APBPrescaler::NotDivided => Ppre::DIV1,
APBPrescaler::Div2 => Ppre::DIV2,
APBPrescaler::Div4 => Ppre::DIV4,
APBPrescaler::Div8 => Ppre::DIV8,
APBPrescaler::Div16 => Ppre::DIV16,
}
}
}
impl Into<Hpre> for AHBPrescaler {
fn into(self) -> Hpre {
match self {
AHBPrescaler::NotDivided => Hpre::DIV1,
AHBPrescaler::Div2 => Hpre::DIV2,
AHBPrescaler::Div4 => Hpre::DIV4,
AHBPrescaler::Div8 => Hpre::DIV8,
AHBPrescaler::Div16 => Hpre::DIV16,
AHBPrescaler::Div64 => Hpre::DIV64,
AHBPrescaler::Div128 => Hpre::DIV128,
AHBPrescaler::Div256 => Hpre::DIV256,
AHBPrescaler::Div512 => Hpre::DIV512,
}
}
}
/// Voltage Range
///
/// Represents the system supply voltage range
#[derive(Copy, Clone, PartialEq)]
pub enum VoltageRange {
/// 1.8 to 3.6 V
Min1V8,
/// 2.1 to 3.6 V
Min2V1,
/// 2.4 to 3.6 V
Min2V4,
/// 2.7 to 3.6 V
Min2V7,
}
impl VoltageRange {
impl VoltageScale {
const fn wait_states(&self, ahb_freq: Hertz) -> Option<Latency> {
let ahb_freq = ahb_freq.0;
// Reference: RM0033 - Table 3. Number of wait states according to Cortex®-M3 clock
// frequency
match self {
VoltageRange::Min1V8 => {
VoltageScale::Scale3 => {
if ahb_freq <= 16_000_000 {
Some(Latency::WS0)
} else if ahb_freq <= 32_000_000 {
@ -328,7 +230,7 @@ impl VoltageRange {
None
}
}
VoltageRange::Min2V1 => {
VoltageScale::Scale2 => {
if ahb_freq <= 18_000_000 {
Some(Latency::WS0)
} else if ahb_freq <= 36_000_000 {
@ -347,7 +249,7 @@ impl VoltageRange {
None
}
}
VoltageRange::Min2V4 => {
VoltageScale::Scale1 => {
if ahb_freq <= 24_000_000 {
Some(Latency::WS0)
} else if ahb_freq <= 48_000_000 {
@ -362,7 +264,7 @@ impl VoltageRange {
None
}
}
VoltageRange::Min2V7 => {
VoltageScale::Scale0 => {
if ahb_freq <= 30_000_000 {
Some(Latency::WS0)
} else if ahb_freq <= 60_000_000 {
@ -386,7 +288,7 @@ pub struct Config {
pub pll_mux: PLLSrc,
pub pll: PLLConfig,
pub mux: ClockSrc,
pub voltage: VoltageRange,
pub voltage: VoltageScale,
pub ahb_pre: AHBPrescaler,
pub apb1_pre: APBPrescaler,
pub apb2_pre: APBPrescaler,
@ -400,7 +302,7 @@ impl Default for Config {
hsi: true,
pll_mux: PLLSrc::HSI,
pll: PLLConfig::default(),
voltage: VoltageRange::Min1V8,
voltage: VoltageScale::Scale3,
mux: ClockSrc::HSI,
ahb_pre: AHBPrescaler::NotDivided,
apb1_pre: APBPrescaler::NotDivided,

View File

@ -264,6 +264,7 @@ fn calc_pll(config: &Config, Hertz(sysclk): Hertz) -> (Hertz, PllConfig) {
}
#[inline]
#[allow(unused_variables)]
fn get_usb_pre(config: &Config, sysclk: u32, pclk1: u32, pll_config: &Option<PllConfig>) -> Usbpre {
cfg_if::cfg_if! {
// Some chips do not have USB

View File

@ -1,6 +1,6 @@
use core::marker::PhantomData;
use embassy_hal_common::into_ref;
use embassy_hal_internal::into_ref;
use stm32_metapac::rcc::vals::{Mco1, Mco2, Mcopre};
use super::sealed::RccPeripheral;

View File

@ -1,5 +1,6 @@
pub use super::common::{AHBPrescaler, APBPrescaler};
use crate::pac::flash::vals::Latency;
use crate::pac::rcc::vals::{self, Hpre, Hsidiv, Ppre, Sw};
use crate::pac::rcc::vals::{self, Hsidiv, Ppre, Sw};
use crate::pac::{FLASH, PWR, RCC};
use crate::rcc::{set_freqs, Clocks};
use crate::time::Hertz;
@ -172,58 +173,6 @@ impl From<Pllr> for u32 {
}
}
/// AHB prescaler
#[derive(Clone, Copy, PartialEq)]
pub enum AHBPrescaler {
NotDivided,
Div2,
Div4,
Div8,
Div16,
Div64,
Div128,
Div256,
Div512,
}
/// APB prescaler
#[derive(Clone, Copy)]
pub enum APBPrescaler {
NotDivided,
Div2,
Div4,
Div8,
Div16,
}
impl Into<Ppre> for APBPrescaler {
fn into(self) -> Ppre {
match self {
APBPrescaler::NotDivided => Ppre::DIV1,
APBPrescaler::Div2 => Ppre::DIV2,
APBPrescaler::Div4 => Ppre::DIV4,
APBPrescaler::Div8 => Ppre::DIV8,
APBPrescaler::Div16 => Ppre::DIV16,
}
}
}
impl Into<Hpre> for AHBPrescaler {
fn into(self) -> Hpre {
match self {
AHBPrescaler::NotDivided => Hpre::DIV1,
AHBPrescaler::Div2 => Hpre::DIV2,
AHBPrescaler::Div4 => Hpre::DIV4,
AHBPrescaler::Div8 => Hpre::DIV8,
AHBPrescaler::Div16 => Hpre::DIV16,
AHBPrescaler::Div64 => Hpre::DIV64,
AHBPrescaler::Div128 => Hpre::DIV128,
AHBPrescaler::Div256 => Hpre::DIV256,
AHBPrescaler::Div512 => Hpre::DIV512,
}
}
}
/// Clocks configutation
pub struct Config {
pub mux: ClockSrc,
@ -425,25 +374,14 @@ pub(crate) unsafe fn init(config: Config) {
FLASH.acr().modify(|w| w.set_latency(target_flash_latency));
}
let ahb_div = match config.ahb_pre {
AHBPrescaler::NotDivided => 1,
AHBPrescaler::Div2 => 2,
AHBPrescaler::Div4 => 4,
AHBPrescaler::Div8 => 8,
AHBPrescaler::Div16 => 16,
AHBPrescaler::Div64 => 64,
AHBPrescaler::Div128 => 128,
AHBPrescaler::Div256 => 256,
AHBPrescaler::Div512 => 512,
};
let ahb_freq = sys_clk / ahb_div;
let ahb_freq = Hertz(sys_clk) / config.ahb_pre;
let (apb_freq, apb_tim_freq) = match config.apb_pre {
APBPrescaler::NotDivided => (ahb_freq, ahb_freq),
APBPrescaler::NotDivided => (ahb_freq.0, ahb_freq.0),
pre => {
let pre: Ppre = pre.into();
let pre: u8 = 1 << (pre.to_bits() - 3);
let freq = ahb_freq / pre as u32;
let freq = ahb_freq.0 / pre as u32;
(freq, freq * 2)
}
};
@ -455,7 +393,7 @@ pub(crate) unsafe fn init(config: Config) {
set_freqs(Clocks {
sys: Hertz(sys_clk),
ahb1: Hertz(ahb_freq),
ahb1: ahb_freq,
apb1: Hertz(apb_freq),
apb1_tim: Hertz(apb_tim_freq),
});

View File

@ -2,6 +2,7 @@ use stm32_metapac::flash::vals::Latency;
use stm32_metapac::rcc::vals::{Hpre, Pllsrc, Ppre, Sw};
use stm32_metapac::FLASH;
pub use super::common::{AHBPrescaler, APBPrescaler};
use crate::pac::{PWR, RCC};
use crate::rcc::sealed::RccPeripheral;
use crate::rcc::{set_freqs, Clocks};
@ -21,30 +22,6 @@ pub enum ClockSrc {
PLL,
}
/// AHB prescaler
#[derive(Clone, Copy, PartialEq)]
pub enum AHBPrescaler {
NotDivided,
Div2,
Div4,
Div8,
Div16,
Div64,
Div128,
Div256,
Div512,
}
/// APB prescaler
#[derive(Clone, Copy)]
pub enum APBPrescaler {
NotDivided,
Div2,
Div4,
Div8,
Div16,
}
/// PLL clock input source
#[derive(Clone, Copy, Debug)]
pub enum PllSrc {

View File

@ -1,6 +1,6 @@
use core::marker::PhantomData;
use stm32_metapac::rcc::vals::{Hpre, Ppre, Timpre};
use stm32_metapac::rcc::vals::Timpre;
use crate::pac::pwr::vals::Vos;
use crate::pac::rcc::vals::{Hseext, Hsidiv, Mco1, Mco2, Pllrge, Pllsrc, Pllvcosel, Sw};
@ -26,21 +26,7 @@ const VCO_MAX: u32 = 420_000_000;
const VCO_WIDE_MIN: u32 = 128_000_000;
const VCO_WIDE_MAX: u32 = 560_000_000;
/// Voltage Scale
///
/// Represents the voltage range feeding the CPU core. The maximum core
/// clock frequency depends on this value.
#[derive(Copy, Clone, PartialEq)]
pub enum VoltageScale {
/// VOS 0 range VCORE 1.30V - 1.40V
Scale0,
/// VOS 1 range VCORE 1.15V - 1.26V
Scale1,
/// VOS 2 range VCORE 1.05V - 1.15V
Scale2,
/// VOS 3 range VCORE 0.95V - 1.05V
Scale3,
}
pub use super::common::{AHBPrescaler, APBPrescaler, VoltageScale};
pub enum HseMode {
/// crystal/ceramic oscillator (HSEBYP=0)
@ -105,57 +91,7 @@ pub struct Pll {
pub divr: Option<u16>,
}
/// AHB prescaler
#[derive(Clone, Copy, PartialEq)]
pub enum AHBPrescaler {
NotDivided,
Div2,
Div4,
Div8,
Div16,
Div64,
Div128,
Div256,
Div512,
}
impl AHBPrescaler {
fn div(&self, clk: Hertz) -> Hertz {
match self {
Self::NotDivided => clk,
Self::Div2 => clk / 2u32,
Self::Div4 => clk / 4u32,
Self::Div8 => clk / 8u32,
Self::Div16 => clk / 16u32,
Self::Div64 => clk / 64u32,
Self::Div128 => clk / 128u32,
Self::Div256 => clk / 256u32,
Self::Div512 => clk / 512u32,
}
}
}
/// APB prescaler
#[derive(Clone, Copy)]
pub enum APBPrescaler {
NotDivided,
Div2,
Div4,
Div8,
Div16,
}
impl APBPrescaler {
fn div(&self, clk: Hertz) -> Hertz {
match self {
Self::NotDivided => clk,
Self::Div2 => clk / 2u32,
Self::Div4 => clk / 4u32,
Self::Div8 => clk / 8u32,
Self::Div16 => clk / 16u32,
}
}
fn div_tim(&self, clk: Hertz, tim: TimerPrescaler) -> Hertz {
match (tim, self) {
// The timers kernel clock is equal to rcc_hclk1 if PPRE1 or PPRE2 corresponds to a
@ -193,34 +129,6 @@ impl From<TimerPrescaler> for Timpre {
}
}
impl From<APBPrescaler> for Ppre {
fn from(val: APBPrescaler) -> Ppre {
match val {
APBPrescaler::NotDivided => Ppre::DIV1,
APBPrescaler::Div2 => Ppre::DIV2,
APBPrescaler::Div4 => Ppre::DIV4,
APBPrescaler::Div8 => Ppre::DIV8,
APBPrescaler::Div16 => Ppre::DIV16,
}
}
}
impl From<AHBPrescaler> for Hpre {
fn from(val: AHBPrescaler) -> Hpre {
match val {
AHBPrescaler::NotDivided => Hpre::DIV1,
AHBPrescaler::Div2 => Hpre::DIV2,
AHBPrescaler::Div4 => Hpre::DIV4,
AHBPrescaler::Div8 => Hpre::DIV8,
AHBPrescaler::Div16 => Hpre::DIV16,
AHBPrescaler::Div64 => Hpre::DIV64,
AHBPrescaler::Div128 => Hpre::DIV128,
AHBPrescaler::Div256 => Hpre::DIV256,
AHBPrescaler::Div512 => Hpre::DIV512,
}
}
}
/// Configuration of the core clocks
#[non_exhaustive]
pub struct Config {
@ -406,13 +314,13 @@ pub(crate) unsafe fn init(config: Config) {
};
assert!(sys <= max_clk);
let hclk = config.ahb_pre.div(sys);
let hclk = sys / config.ahb_pre;
let apb1 = config.apb1_pre.div(hclk);
let apb1 = hclk / config.apb1_pre;
let apb1_tim = config.apb1_pre.div_tim(hclk, config.timer_prescaler);
let apb2 = config.apb2_pre.div(hclk);
let apb2 = hclk / config.apb2_pre;
let apb2_tim = config.apb2_pre.div_tim(hclk, config.timer_prescaler);
let apb3 = config.apb3_pre.div(hclk);
let apb3 = hclk / config.apb3_pre;
flash_setup(hclk, config.voltage_scale);

View File

@ -1,6 +1,6 @@
use core::marker::PhantomData;
use embassy_hal_common::into_ref;
use embassy_hal_internal::into_ref;
pub use pll::PllConfig;
use stm32_metapac::rcc::vals::{Mco1, Mco2};
@ -24,21 +24,7 @@ pub const HSI48_FREQ: Hertz = Hertz(48_000_000);
/// LSI speed
pub const LSI_FREQ: Hertz = Hertz(32_000);
/// Voltage Scale
///
/// Represents the voltage range feeding the CPU core. The maximum core
/// clock frequency depends on this value.
#[derive(Copy, Clone, PartialEq)]
pub enum VoltageScale {
/// VOS 0 range VCORE 1.26V - 1.40V
Scale0,
/// VOS 1 range VCORE 1.15V - 1.26V
Scale1,
/// VOS 2 range VCORE 1.05V - 1.15V
Scale2,
/// VOS 3 range VCORE 0.95V - 1.05V
Scale3,
}
pub use super::common::VoltageScale;
#[derive(Clone, Copy)]
pub enum AdcClockSource {

View File

@ -1,3 +1,4 @@
pub use super::common::{AHBPrescaler, APBPrescaler};
use crate::pac::rcc::vals::{Hpre, Msirange, Plldiv, Pllmul, Pllsrc, Ppre, Sw};
use crate::pac::RCC;
#[cfg(crs)]
@ -70,30 +71,6 @@ pub enum PLLMul {
Mul48,
}
/// AHB prescaler
#[derive(Clone, Copy, PartialEq)]
pub enum AHBPrescaler {
NotDivided,
Div2,
Div4,
Div8,
Div16,
Div64,
Div128,
Div256,
Div512,
}
/// APB prescaler
#[derive(Clone, Copy)]
pub enum APBPrescaler {
NotDivided,
Div2,
Div4,
Div8,
Div16,
}
/// PLL clock input source
#[derive(Clone, Copy)]
pub enum PLLSource {
@ -136,34 +113,6 @@ impl From<PLLSource> for Pllsrc {
}
}
impl From<APBPrescaler> for Ppre {
fn from(val: APBPrescaler) -> Ppre {
match val {
APBPrescaler::NotDivided => Ppre::DIV1,
APBPrescaler::Div2 => Ppre::DIV2,
APBPrescaler::Div4 => Ppre::DIV4,
APBPrescaler::Div8 => Ppre::DIV8,
APBPrescaler::Div16 => Ppre::DIV16,
}
}
}
impl From<AHBPrescaler> for Hpre {
fn from(val: AHBPrescaler) -> Hpre {
match val {
AHBPrescaler::NotDivided => Hpre::DIV1,
AHBPrescaler::Div2 => Hpre::DIV2,
AHBPrescaler::Div4 => Hpre::DIV4,
AHBPrescaler::Div8 => Hpre::DIV8,
AHBPrescaler::Div16 => Hpre::DIV16,
AHBPrescaler::Div64 => Hpre::DIV64,
AHBPrescaler::Div128 => Hpre::DIV128,
AHBPrescaler::Div256 => Hpre::DIV256,
AHBPrescaler::Div512 => Hpre::DIV512,
}
}
}
impl From<MSIRange> for Msirange {
fn from(val: MSIRange) -> Msirange {
match val {

View File

@ -1,3 +1,4 @@
pub use super::common::{AHBPrescaler, APBPrescaler};
use crate::pac::rcc::vals::{Hpre, Msirange, Plldiv, Pllmul, Pllsrc, Ppre, Sw};
use crate::pac::{FLASH, RCC};
use crate::rcc::{set_freqs, Clocks};
@ -68,30 +69,6 @@ pub enum PLLMul {
Mul48,
}
/// AHB prescaler
#[derive(Clone, Copy, PartialEq)]
pub enum AHBPrescaler {
NotDivided,
Div2,
Div4,
Div8,
Div16,
Div64,
Div128,
Div256,
Div512,
}
/// APB prescaler
#[derive(Clone, Copy)]
pub enum APBPrescaler {
NotDivided,
Div2,
Div4,
Div8,
Div16,
}
/// PLL clock input source
#[derive(Clone, Copy)]
pub enum PLLSource {
@ -134,34 +111,6 @@ impl From<PLLSource> for Pllsrc {
}
}
impl From<APBPrescaler> for Ppre {
fn from(val: APBPrescaler) -> Ppre {
match val {
APBPrescaler::NotDivided => Ppre::DIV1,
APBPrescaler::Div2 => Ppre::DIV2,
APBPrescaler::Div4 => Ppre::DIV4,
APBPrescaler::Div8 => Ppre::DIV8,
APBPrescaler::Div16 => Ppre::DIV16,
}
}
}
impl From<AHBPrescaler> for Hpre {
fn from(val: AHBPrescaler) -> Hpre {
match val {
AHBPrescaler::NotDivided => Hpre::DIV1,
AHBPrescaler::Div2 => Hpre::DIV2,
AHBPrescaler::Div4 => Hpre::DIV4,
AHBPrescaler::Div8 => Hpre::DIV8,
AHBPrescaler::Div16 => Hpre::DIV16,
AHBPrescaler::Div64 => Hpre::DIV64,
AHBPrescaler::Div128 => Hpre::DIV128,
AHBPrescaler::Div256 => Hpre::DIV256,
AHBPrescaler::Div512 => Hpre::DIV512,
}
}
}
impl From<MSIRange> for Msirange {
fn from(val: MSIRange) -> Msirange {
match val {

View File

@ -1,9 +1,10 @@
use core::marker::PhantomData;
use embassy_hal_common::into_ref;
use embassy_hal_internal::into_ref;
use stm32_metapac::rcc::regs::Cfgr;
use stm32_metapac::rcc::vals::{Lsedrv, Mcopre, Mcosel};
pub use super::common::{AHBPrescaler, APBPrescaler};
use crate::gpio::sealed::AFType;
use crate::gpio::Speed;
use crate::pac::rcc::vals::{Hpre, Msirange, Pllsrc, Ppre, Sw};
@ -78,30 +79,6 @@ pub enum PLLDiv {
Div4,
}
/// AHB prescaler
#[derive(Clone, Copy, PartialEq)]
pub enum AHBPrescaler {
NotDivided,
Div2,
Div4,
Div8,
Div16,
Div64,
Div128,
Div256,
Div512,
}
/// APB prescaler
#[derive(Clone, Copy)]
pub enum APBPrescaler {
NotDivided,
Div2,
Div4,
Div8,
Div16,
}
/// PLL clock input source
#[derive(Clone, Copy)]
pub enum PLLSource {
@ -209,34 +186,6 @@ impl From<PLLSource> for Pllsrc {
}
}
impl From<APBPrescaler> for Ppre {
fn from(val: APBPrescaler) -> Ppre {
match val {
APBPrescaler::NotDivided => Ppre::DIV1,
APBPrescaler::Div2 => Ppre::DIV2,
APBPrescaler::Div4 => Ppre::DIV4,
APBPrescaler::Div8 => Ppre::DIV8,
APBPrescaler::Div16 => Ppre::DIV16,
}
}
}
impl From<AHBPrescaler> for Hpre {
fn from(val: AHBPrescaler) -> Hpre {
match val {
AHBPrescaler::NotDivided => Hpre::DIV1,
AHBPrescaler::Div2 => Hpre::DIV2,
AHBPrescaler::Div4 => Hpre::DIV4,
AHBPrescaler::Div8 => Hpre::DIV8,
AHBPrescaler::Div16 => Hpre::DIV16,
AHBPrescaler::Div64 => Hpre::DIV64,
AHBPrescaler::Div128 => Hpre::DIV128,
AHBPrescaler::Div256 => Hpre::DIV256,
AHBPrescaler::Div512 => Hpre::DIV512,
}
}
}
impl From<MSIRange> for Msirange {
fn from(val: MSIRange) -> Msirange {
match val {

View File

@ -1,5 +1,6 @@
use stm32_metapac::PWR;
pub use super::common::{AHBPrescaler, APBPrescaler};
use crate::pac::rcc::vals::{Hpre, Msirange, Pllsrc, Ppre, Sw};
use crate::pac::{FLASH, RCC};
use crate::rcc::{set_freqs, Clocks};
@ -71,30 +72,6 @@ pub enum PLLDiv {
Div4,
}
/// AHB prescaler
#[derive(Clone, Copy, PartialEq)]
pub enum AHBPrescaler {
NotDivided,
Div2,
Div4,
Div8,
Div16,
Div64,
Div128,
Div256,
Div512,
}
/// APB prescaler
#[derive(Clone, Copy)]
pub enum APBPrescaler {
NotDivided,
Div2,
Div4,
Div8,
Div16,
}
/// PLL clock input source
#[derive(Clone, Copy)]
pub enum PLLSource {
@ -202,34 +179,6 @@ impl From<PLLSource> for Pllsrc {
}
}
impl From<APBPrescaler> for Ppre {
fn from(val: APBPrescaler) -> Ppre {
match val {
APBPrescaler::NotDivided => Ppre::DIV1,
APBPrescaler::Div2 => Ppre::DIV2,
APBPrescaler::Div4 => Ppre::DIV4,
APBPrescaler::Div8 => Ppre::DIV8,
APBPrescaler::Div16 => Ppre::DIV16,
}
}
}
impl From<AHBPrescaler> for Hpre {
fn from(val: AHBPrescaler) -> Hpre {
match val {
AHBPrescaler::NotDivided => Hpre::DIV1,
AHBPrescaler::Div2 => Hpre::DIV2,
AHBPrescaler::Div4 => Hpre::DIV4,
AHBPrescaler::Div8 => Hpre::DIV8,
AHBPrescaler::Div16 => Hpre::DIV16,
AHBPrescaler::Div64 => Hpre::DIV64,
AHBPrescaler::Div128 => Hpre::DIV128,
AHBPrescaler::Div256 => Hpre::DIV256,
AHBPrescaler::Div512 => Hpre::DIV512,
}
}
}
impl From<MSIRange> for Msirange {
fn from(val: MSIRange) -> Msirange {
match val {

View File

@ -1,5 +1,7 @@
#![macro_use]
pub mod common;
use core::mem::MaybeUninit;
use crate::time::Hertz;

View File

@ -1,5 +1,6 @@
use stm32_metapac::rcc::vals::{Hpre, Msirange, Msirgsel, Pllm, Pllsrc, Ppre, Sw};
use stm32_metapac::rcc::vals::{Msirange, Msirgsel, Pllm, Pllsrc, Sw};
pub use super::common::{AHBPrescaler, APBPrescaler};
use crate::pac::{FLASH, RCC};
use crate::rcc::{set_freqs, Clocks};
use crate::time::Hertz;
@ -10,19 +11,7 @@ pub const HSI_FREQ: Hertz = Hertz(16_000_000);
/// LSI speed
pub const LSI_FREQ: Hertz = Hertz(32_000);
/// Voltage Scale
///
/// Represents the voltage range feeding the CPU core. The maximum core
/// clock frequency depends on this value.
#[derive(Copy, Clone, PartialEq)]
pub enum VoltageScale {
// Highest frequency
Range1,
Range2,
Range3,
// Lowest power
Range4,
}
pub use super::common::VoltageScale;
#[derive(Copy, Clone)]
pub enum ClockSrc {
@ -130,36 +119,6 @@ impl Into<Pllm> for PllM {
}
}
/// AHB prescaler
#[derive(Clone, Copy, PartialEq)]
pub enum AHBPrescaler {
NotDivided,
Div2,
Div4,
Div8,
Div16,
Div64,
Div128,
Div256,
Div512,
}
impl Into<Hpre> for AHBPrescaler {
fn into(self) -> Hpre {
match self {
AHBPrescaler::NotDivided => Hpre::NONE,
AHBPrescaler::Div2 => Hpre::DIV2,
AHBPrescaler::Div4 => Hpre::DIV4,
AHBPrescaler::Div8 => Hpre::DIV8,
AHBPrescaler::Div16 => Hpre::DIV16,
AHBPrescaler::Div64 => Hpre::DIV64,
AHBPrescaler::Div128 => Hpre::DIV128,
AHBPrescaler::Div256 => Hpre::DIV256,
AHBPrescaler::Div512 => Hpre::DIV512,
}
}
}
impl Into<u8> for AHBPrescaler {
fn into(self) -> u8 {
match self {
@ -182,28 +141,6 @@ impl Default for AHBPrescaler {
}
}
/// APB prescaler
#[derive(Clone, Copy)]
pub enum APBPrescaler {
NotDivided,
Div2,
Div4,
Div8,
Div16,
}
impl Into<Ppre> for APBPrescaler {
fn into(self) -> Ppre {
match self {
APBPrescaler::NotDivided => Ppre::NONE,
APBPrescaler::Div2 => Ppre::DIV2,
APBPrescaler::Div4 => Ppre::DIV4,
APBPrescaler::Div8 => Ppre::DIV8,
APBPrescaler::Div16 => Ppre::DIV16,
}
}
}
impl Default for APBPrescaler {
fn default() -> Self {
APBPrescaler::NotDivided
@ -389,12 +326,12 @@ pub(crate) unsafe fn init(config: Config) {
}
// TODO make configurable
let power_vos = VoltageScale::Range4;
let power_vos = VoltageScale::Scale3;
// states and programming delay
let wait_states = match power_vos {
// VOS 0 range VCORE 1.26V - 1.40V
VoltageScale::Range1 => {
VoltageScale::Scale0 => {
if sys_clk < 32_000_000 {
0
} else if sys_clk < 64_000_000 {
@ -408,7 +345,7 @@ pub(crate) unsafe fn init(config: Config) {
}
}
// VOS 1 range VCORE 1.15V - 1.26V
VoltageScale::Range2 => {
VoltageScale::Scale1 => {
if sys_clk < 30_000_000 {
0
} else if sys_clk < 60_000_000 {
@ -420,7 +357,7 @@ pub(crate) unsafe fn init(config: Config) {
}
}
// VOS 2 range VCORE 1.05V - 1.15V
VoltageScale::Range3 => {
VoltageScale::Scale2 => {
if sys_clk < 24_000_000 {
0
} else if sys_clk < 48_000_000 {
@ -430,7 +367,7 @@ pub(crate) unsafe fn init(config: Config) {
}
}
// VOS 3 range VCORE 0.95V - 1.05V
VoltageScale::Range4 => {
VoltageScale::Scale3 => {
if sys_clk < 12_000_000 {
0
} else {

View File

@ -1,3 +1,4 @@
pub use super::common::{AHBPrescaler, APBPrescaler};
use crate::rcc::Clocks;
use crate::time::{khz, mhz, Hertz};
@ -102,68 +103,6 @@ pub struct Pll {
pub divr: Option<u16>,
}
/// AHB prescaler
#[derive(Clone, Copy, PartialEq)]
pub enum AHBPrescaler {
NotDivided,
Div2,
Div3,
Div4,
Div5,
Div6,
Div8,
Div10,
Div16,
Div32,
Div64,
Div128,
Div256,
Div512,
}
/// APB prescaler
#[derive(Clone, Copy)]
pub enum APBPrescaler {
NotDivided,
Div2,
Div4,
Div8,
Div16,
}
impl Into<u8> for APBPrescaler {
fn into(self) -> u8 {
match self {
APBPrescaler::NotDivided => 1,
APBPrescaler::Div2 => 0x04,
APBPrescaler::Div4 => 0x05,
APBPrescaler::Div8 => 0x06,
APBPrescaler::Div16 => 0x07,
}
}
}
impl Into<u8> for AHBPrescaler {
fn into(self) -> u8 {
match self {
AHBPrescaler::NotDivided => 0x0,
AHBPrescaler::Div2 => 0x08,
AHBPrescaler::Div3 => 0x01,
AHBPrescaler::Div4 => 0x09,
AHBPrescaler::Div5 => 0x02,
AHBPrescaler::Div6 => 0x05,
AHBPrescaler::Div8 => 0x0a,
AHBPrescaler::Div10 => 0x06,
AHBPrescaler::Div16 => 0x0b,
AHBPrescaler::Div32 => 0x07,
AHBPrescaler::Div64 => 0x0c,
AHBPrescaler::Div128 => 0x0d,
AHBPrescaler::Div256 => 0x0e,
AHBPrescaler::Div512 => 0x0f,
}
}
}
/// Clocks configutation
pub struct Config {
pub hse: Option<Hse>,

View File

@ -1,3 +1,4 @@
pub use super::common::{AHBPrescaler, APBPrescaler, VoltageScale};
use crate::pac::pwr::vals::Dbp;
use crate::pac::{FLASH, PWR, RCC};
use crate::rcc::{set_freqs, Clocks};
@ -73,9 +74,9 @@ impl MSIRange {
fn vos(&self) -> VoltageScale {
if self > &MSIRange::Range8 {
VoltageScale::Range1
VoltageScale::Scale0
} else {
VoltageScale::Range2
VoltageScale::Scale1
}
}
}
@ -105,78 +106,6 @@ impl Into<u8> for MSIRange {
}
}
/// Voltage Scale
///
/// Represents the voltage range feeding the CPU core. The maximum core
/// clock frequency depends on this value.
#[derive(Copy, Clone, PartialEq)]
pub enum VoltageScale {
Range1,
Range2,
}
/// AHB prescaler
#[derive(Clone, Copy, PartialEq)]
pub enum AHBPrescaler {
NotDivided,
Div2,
Div3,
Div4,
Div5,
Div6,
Div8,
Div10,
Div16,
Div32,
Div64,
Div128,
Div256,
Div512,
}
/// APB prescaler
#[derive(Clone, Copy)]
pub enum APBPrescaler {
NotDivided,
Div2,
Div4,
Div8,
Div16,
}
impl Into<u8> for APBPrescaler {
fn into(self) -> u8 {
match self {
APBPrescaler::NotDivided => 1,
APBPrescaler::Div2 => 0x04,
APBPrescaler::Div4 => 0x05,
APBPrescaler::Div8 => 0x06,
APBPrescaler::Div16 => 0x07,
}
}
}
impl Into<u8> for AHBPrescaler {
fn into(self) -> u8 {
match self {
AHBPrescaler::NotDivided => 0x0,
AHBPrescaler::Div2 => 0x08,
AHBPrescaler::Div3 => 0x01,
AHBPrescaler::Div4 => 0x09,
AHBPrescaler::Div5 => 0x02,
AHBPrescaler::Div6 => 0x05,
AHBPrescaler::Div8 => 0x0a,
AHBPrescaler::Div10 => 0x06,
AHBPrescaler::Div16 => 0x0b,
AHBPrescaler::Div32 => 0x07,
AHBPrescaler::Div64 => 0x0c,
AHBPrescaler::Div128 => 0x0d,
AHBPrescaler::Div256 => 0x0e,
AHBPrescaler::Div512 => 0x0f,
}
}
}
/// Clocks configutation
pub struct Config {
pub mux: ClockSrc,
@ -220,8 +149,8 @@ pub enum Lsedrv {
pub(crate) unsafe fn init(config: Config) {
let (sys_clk, sw, vos) = match config.mux {
ClockSrc::HSI16 => (HSI_FREQ.0, 0x01, VoltageScale::Range2),
ClockSrc::HSE32 => (HSE32_FREQ.0, 0x02, VoltageScale::Range1),
ClockSrc::HSI16 => (HSI_FREQ.0, 0x01, VoltageScale::Scale1),
ClockSrc::HSE32 => (HSE32_FREQ.0, 0x02, VoltageScale::Scale0),
ClockSrc::MSI(range) => (range.freq(), 0x00, range.vos()),
};
@ -266,12 +195,12 @@ pub(crate) unsafe fn init(config: Config) {
// Adjust flash latency
let flash_clk_src_freq: u32 = shd_ahb_freq;
let ws = match vos {
VoltageScale::Range1 => match flash_clk_src_freq {
VoltageScale::Scale0 => match flash_clk_src_freq {
0..=18_000_000 => 0b000,
18_000_001..=36_000_000 => 0b001,
_ => 0b010,
},
VoltageScale::Range2 => match flash_clk_src_freq {
VoltageScale::Scale1 => match flash_clk_src_freq {
0..=6_000_000 => 0b000,
6_000_001..=12_000_000 => 0b001,
_ => 0b010,

View File

@ -1,15 +1,17 @@
#![macro_use]
use core::future::poll_fn;
use core::marker::PhantomData;
use core::task::Poll;
use embassy_hal_common::{into_ref, PeripheralRef};
use embassy_hal_internal::{into_ref, PeripheralRef};
use embassy_sync::waitqueue::AtomicWaker;
use rand_core::{CryptoRng, RngCore};
use crate::{pac, peripherals, Peripheral};
use crate::interrupt::typelevel::Interrupt;
use crate::{interrupt, pac, peripherals, Peripheral};
pub(crate) static RNG_WAKER: AtomicWaker = AtomicWaker::new();
static RNG_WAKER: AtomicWaker = AtomicWaker::new();
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum Error {
@ -17,68 +19,145 @@ pub enum Error {
ClockError,
}
pub struct InterruptHandler<T: Instance> {
_phantom: PhantomData<T>,
}
impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandler<T> {
unsafe fn on_interrupt() {
let bits = T::regs().sr().read();
if bits.drdy() || bits.seis() || bits.ceis() {
T::regs().cr().modify(|reg| reg.set_ie(false));
RNG_WAKER.wake();
}
}
}
pub struct Rng<'d, T: Instance> {
_inner: PeripheralRef<'d, T>,
}
impl<'d, T: Instance> Rng<'d, T> {
pub fn new(inner: impl Peripheral<P = T> + 'd) -> Self {
pub fn new(
inner: impl Peripheral<P = T> + 'd,
_irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
) -> Self {
T::enable();
T::reset();
into_ref!(inner);
let mut random = Self { _inner: inner };
random.reset();
T::Interrupt::unpend();
unsafe { T::Interrupt::enable() };
random
}
#[cfg(rng_v1)]
pub fn reset(&mut self) {
// rng_v2 locks up on seed error, needs reset
#[cfg(rng_v2)]
if T::regs().sr().read().seis() {
T::reset();
}
T::regs().cr().modify(|reg| {
reg.set_rngen(true);
reg.set_ie(true);
T::regs().cr().write(|reg| {
reg.set_rngen(false);
});
T::regs().sr().modify(|reg| {
reg.set_seis(false);
reg.set_ceis(false);
});
T::regs().cr().modify(|reg| {
reg.set_rngen(true);
});
// Reference manual says to discard the first.
let _ = self.next_u32();
}
pub async fn async_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {
#[cfg(not(rng_v1))]
pub fn reset(&mut self) {
T::regs().cr().write(|reg| {
reg.set_rngen(false);
reg.set_condrst(true);
// set RNG config "A" according to reference manual
// this has to be written within the same write access as setting the CONDRST bit
reg.set_nistc(pac::rng::vals::Nistc::DEFAULT);
reg.set_rng_config1(pac::rng::vals::RngConfig1::CONFIGA);
reg.set_rng_config2(pac::rng::vals::RngConfig2::CONFIGA_B);
reg.set_rng_config3(pac::rng::vals::RngConfig3::CONFIGA);
reg.set_clkdiv(pac::rng::vals::Clkdiv::NODIV);
});
// wait for CONDRST to be set
while !T::regs().cr().read().condrst() {}
// magic number must be written immediately before every read or write access to HTCR
T::regs().htcr().write(|w| w.set_htcfg(pac::rng::vals::Htcfg::MAGIC));
// write recommended value according to reference manual
// note: HTCR can only be written during conditioning
T::regs()
.htcr()
.write(|w| w.set_htcfg(pac::rng::vals::Htcfg::RECOMMENDED));
// finish conditioning
T::regs().cr().modify(|reg| {
reg.set_rngen(true);
reg.set_condrst(false);
});
// wait for CONDRST to be reset
while T::regs().cr().read().condrst() {}
}
pub fn recover_seed_error(&mut self) -> () {
self.reset();
// reset should also clear the SEIS flag
if T::regs().sr().read().seis() {
warn!("recovering from seed error failed");
return;
}
// wait for SECS to be cleared by RNG
while T::regs().sr().read().secs() {}
}
pub async fn async_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {
for chunk in dest.chunks_mut(4) {
poll_fn(|cx| {
RNG_WAKER.register(cx.waker());
T::regs().cr().modify(|reg| {
reg.set_ie(true);
});
let bits = T::regs().sr().read();
if bits.drdy() {
Poll::Ready(Ok(()))
} else if bits.seis() {
self.reset();
Poll::Ready(Err(Error::SeedError))
} else if bits.ceis() {
self.reset();
Poll::Ready(Err(Error::ClockError))
} else {
Poll::Pending
let bits = T::regs().sr().read();
if bits.seis() {
// in case of noise-source or seed error we try to recover here
// but we must not use the data in DR and we return an error
// to leave retry-logic to the application
self.recover_seed_error();
return Err(Error::SeedError);
} else if bits.ceis() {
// clock error detected, DR could still be used but keep it safe,
// clear the error and abort
T::regs().sr().modify(|sr| sr.set_ceis(false));
return Err(Error::ClockError);
} else if bits.drdy() {
// DR can be read up to four times until the output buffer is empty
// DRDY is cleared automatically when that happens
let random_word = T::regs().dr().read();
// reference manual: always check if DR is zero
if random_word == 0 {
return Err(Error::SeedError);
}
})
.await?;
let random_bytes = T::regs().dr().read().to_be_bytes();
for (dest, src) in chunk.iter_mut().zip(random_bytes.iter()) {
*dest = *src
// write bytes to chunk
for (dest, src) in chunk.iter_mut().zip(random_word.to_be_bytes().iter()) {
*dest = *src
}
} else {
// wait for interrupt
poll_fn(|cx| {
// quick check to avoid registration if already done.
let bits = T::regs().sr().read();
if bits.drdy() || bits.seis() || bits.ceis() {
return Poll::Ready(());
}
RNG_WAKER.register(cx.waker());
T::regs().cr().modify(|reg| reg.set_ie(true));
// Need to check condition **after** `register` to avoid a race
// condition that would result in lost notifications.
let bits = T::regs().sr().read();
if bits.drdy() || bits.seis() || bits.ceis() {
Poll::Ready(())
} else {
Poll::Pending
}
})
.await;
}
}
@ -129,57 +208,20 @@ pub(crate) mod sealed {
}
}
pub trait Instance: sealed::Instance + crate::rcc::RccPeripheral {}
pub trait Instance: sealed::Instance + Peripheral<P = Self> + crate::rcc::RccPeripheral + 'static + Send {
type Interrupt: interrupt::typelevel::Interrupt;
}
foreach_peripheral!(
(rng, $inst:ident) => {
impl Instance for peripherals::$inst {}
foreach_interrupt!(
($inst:ident, rng, RNG, GLOBAL, $irq:ident) => {
impl Instance for peripherals::$inst {
type Interrupt = crate::interrupt::typelevel::$irq;
}
impl sealed::Instance for peripherals::$inst {
fn regs() -> crate::pac::rng::Rng {
crate::pac::RNG
crate::pac::$inst
}
}
};
);
#[cfg(feature = "rt")]
macro_rules! irq {
($irq:ident) => {
mod rng_irq {
use crate::interrupt;
#[interrupt]
unsafe fn $irq() {
let bits = $crate::pac::RNG.sr().read();
if bits.drdy() || bits.seis() || bits.ceis() {
$crate::pac::RNG.cr().write(|reg| reg.set_ie(false));
$crate::rng::RNG_WAKER.wake();
}
}
}
};
}
#[cfg(feature = "rt")]
foreach_interrupt!(
(RNG) => {
irq!(RNG);
};
(RNG_LPUART1) => {
irq!(RNG_LPUART1);
};
(AES_RNG_LPUART1) => {
irq!(AES_RNG_LPUART1);
};
(AES_RNG) => {
irq!(AES_RNG);
};
(HASH_RNG) => {
irq!(HASH_RNG);
};
);

View File

@ -15,7 +15,7 @@ pub use self::datetime::{DateTime, DayOfWeek, Error as DateTimeError};
#[cfg_attr(any(rtc_v3, rtc_v3u5), path = "v3.rs")]
mod _version;
pub use _version::*;
use embassy_hal_common::Peripheral;
use embassy_hal_internal::Peripheral;
/// Errors that can occur on methods on [RtcClock]
#[derive(Clone, Debug, PartialEq, Eq)]

View File

@ -39,9 +39,8 @@ impl<'d, T: Instance> super::Rtc<'d, T> {
let rtcsel = reg.rtcsel().to_bits();
if !reg.rtcen() || rtcsel != clock_config {
#[cfg(not(any(rtc_v2l0, rtc_v2l1)))]
#[cfg(not(any(rtc_v2l0, rtc_v2l1, rtc_v2f2)))]
crate::pac::RCC.bdcr().modify(|w| w.set_bdrst(true));
#[cfg(not(any(rtc_v2l0, rtc_v2l1)))]
let cr = crate::pac::RCC.bdcr();
#[cfg(any(rtc_v2l0, rtc_v2l1))]
@ -201,6 +200,11 @@ impl sealed::Instance for crate::peripherals::RTC {
// read to allow the pwr clock to enable
crate::pac::PWR.cr1().read();
}
#[cfg(any(rtc_v2f2))]
{
crate::pac::RCC.apb1enr().modify(|w| w.set_pwren(true));
crate::pac::PWR.cr().read();
}
}
fn read_backup_register(rtc: &Rtc, register: usize) -> Option<u32> {

View File

@ -6,8 +6,8 @@ use core::marker::PhantomData;
use core::ops::{Deref, DerefMut};
use core::task::Poll;
use embassy_hal_common::drop::OnDrop;
use embassy_hal_common::{into_ref, PeripheralRef};
use embassy_hal_internal::drop::OnDrop;
use embassy_hal_internal::{into_ref, PeripheralRef};
use embassy_sync::waitqueue::AtomicWaker;
use sdio_host::{BusWidth, CardCapacity, CardStatus, CurrentState, SDStatus, CID, CSD, OCR, SCR};

View File

@ -4,7 +4,7 @@ use core::ptr;
use embassy_embedded_hal::SetConfig;
use embassy_futures::join::join;
use embassy_hal_common::{into_ref, PeripheralRef};
use embassy_hal_internal::{into_ref, PeripheralRef};
pub use embedded_hal_02::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3};
use crate::dma::{slice_ptr_parts, word, Transfer};
@ -36,6 +36,7 @@ pub enum BitOrder {
pub struct Config {
pub mode: Mode,
pub bit_order: BitOrder,
pub frequency: Hertz,
}
impl Default for Config {
@ -43,6 +44,7 @@ impl Default for Config {
Self {
mode: MODE_0,
bit_order: BitOrder::MsbFirst,
frequency: Hertz(1_000_000),
}
}
}
@ -88,7 +90,6 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
miso: impl Peripheral<P = impl MisoPin<T>> + 'd,
txdma: impl Peripheral<P = Tx> + 'd,
rxdma: impl Peripheral<P = Rx> + 'd,
freq: Hertz,
config: Config,
) -> Self {
into_ref!(peri, sck, mosi, miso);
@ -112,7 +113,6 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
Some(miso.map_into()),
txdma,
rxdma,
freq,
config,
)
}
@ -123,7 +123,6 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
miso: impl Peripheral<P = impl MisoPin<T>> + 'd,
txdma: impl Peripheral<P = Tx> + 'd, // TODO remove
rxdma: impl Peripheral<P = Rx> + 'd,
freq: Hertz,
config: Config,
) -> Self {
into_ref!(sck, miso);
@ -139,7 +138,6 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
Some(miso.map_into()),
txdma,
rxdma,
freq,
config,
)
}
@ -150,7 +148,6 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
mosi: impl Peripheral<P = impl MosiPin<T>> + 'd,
txdma: impl Peripheral<P = Tx> + 'd,
rxdma: impl Peripheral<P = Rx> + 'd, // TODO remove
freq: Hertz,
config: Config,
) -> Self {
into_ref!(sck, mosi);
@ -166,7 +163,6 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
None,
txdma,
rxdma,
freq,
config,
)
}
@ -176,14 +172,13 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
mosi: impl Peripheral<P = impl MosiPin<T>> + 'd,
txdma: impl Peripheral<P = Tx> + 'd,
rxdma: impl Peripheral<P = Rx> + 'd, // TODO: remove
freq: Hertz,
config: Config,
) -> Self {
into_ref!(mosi);
mosi.set_as_af_pull(mosi.af_num(), AFType::OutputPushPull, Pull::Down);
mosi.set_speed(crate::gpio::Speed::Medium);
Self::new_inner(peri, None, Some(mosi.map_into()), None, txdma, rxdma, freq, config)
Self::new_inner(peri, None, Some(mosi.map_into()), None, txdma, rxdma, config)
}
#[cfg(stm32wl)]
@ -201,7 +196,8 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
let mut config = Config::default();
config.mode = MODE_0;
config.bit_order = BitOrder::MsbFirst;
Self::new_inner(peri, None, None, None, txdma, rxdma, freq, config)
config.frequency = freq;
Self::new_inner(peri, None, None, None, txdma, rxdma, config)
}
#[allow(dead_code)]
@ -209,10 +205,9 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
peri: impl Peripheral<P = T> + 'd,
txdma: impl Peripheral<P = Tx> + 'd,
rxdma: impl Peripheral<P = Rx> + 'd,
freq: Hertz,
config: Config,
) -> Self {
Self::new_inner(peri, None, None, None, txdma, rxdma, freq, config)
Self::new_inner(peri, None, None, None, txdma, rxdma, config)
}
fn new_inner(
@ -222,12 +217,12 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
miso: Option<PeripheralRef<'d, AnyPin>>,
txdma: impl Peripheral<P = Tx> + 'd,
rxdma: impl Peripheral<P = Rx> + 'd,
freq: Hertz,
config: Config,
) -> Self {
into_ref!(peri, txdma, rxdma);
let pclk = T::frequency();
let freq = config.frequency;
let br = compute_baud_rate(pclk, freq.into());
let cpha = config.raw_phase();
@ -334,19 +329,29 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
let lsbfirst = config.raw_byte_order();
let pclk = T::frequency();
let freq = config.frequency;
let br = compute_baud_rate(pclk, freq.into());
#[cfg(any(spi_v1, spi_f1, spi_v2))]
T::REGS.cr1().modify(|w| {
w.set_cpha(cpha);
w.set_cpol(cpol);
w.set_br(br);
w.set_lsbfirst(lsbfirst);
});
#[cfg(any(spi_v3, spi_v4, spi_v5))]
T::REGS.cfg2().modify(|w| {
w.set_cpha(cpha);
w.set_cpol(cpol);
w.set_lsbfirst(lsbfirst);
});
{
T::REGS.cfg2().modify(|w| {
w.set_cpha(cpha);
w.set_cpol(cpol);
w.set_lsbfirst(lsbfirst);
});
T::REGS.cfg1().modify(|w| {
w.set_mbr(br);
});
}
}
pub fn get_current_config(&self) -> Config {
@ -354,6 +359,9 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
let cfg = T::REGS.cr1().read();
#[cfg(any(spi_v3, spi_v4, spi_v5))]
let cfg = T::REGS.cfg2().read();
#[cfg(any(spi_v3, spi_v4, spi_v5))]
let cfg1 = T::REGS.cfg1().read();
let polarity = if cfg.cpol() == vals::Cpol::IDLELOW {
Polarity::IdleLow
} else {
@ -371,9 +379,18 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
BitOrder::MsbFirst
};
#[cfg(any(spi_v1, spi_f1, spi_v2))]
let br = cfg.br();
#[cfg(any(spi_v3, spi_v4, spi_v5))]
let br = cfg1.mbr();
let pclk = T::frequency();
let frequency = compute_frequency(pclk, br);
Config {
mode: Mode { polarity, phase },
bit_order,
frequency,
}
}
@ -653,6 +670,21 @@ fn compute_baud_rate(clocks: Hertz, freq: Hertz) -> Br {
Br::from_bits(val)
}
fn compute_frequency(clocks: Hertz, br: Br) -> Hertz {
let div: u16 = match br {
Br::DIV2 => 2,
Br::DIV4 => 4,
Br::DIV8 => 8,
Br::DIV16 => 16,
Br::DIV32 => 32,
Br::DIV64 => 64,
Br::DIV128 => 128,
Br::DIV256 => 256,
};
clocks / div
}
trait RegsExt {
fn tx_ptr<W>(&self) -> *mut W;
fn rx_ptr<W>(&self) -> *mut W;

View File

@ -1,13 +1,13 @@
use core::marker::PhantomData;
use embassy_hal_common::{into_ref, PeripheralRef};
use embassy_hal_internal::{into_ref, PeripheralRef};
use stm32_metapac::timer::vals::Ckd;
use super::simple_pwm::*;
use super::*;
#[allow(unused_imports)]
use crate::gpio::sealed::{AFType, Pin};
use crate::gpio::AnyPin;
use crate::gpio::{AnyPin, OutputType};
use crate::time::Hertz;
use crate::Peripheral;
@ -17,13 +17,13 @@ pub struct ComplementaryPwmPin<'d, Perip, Channel> {
}
macro_rules! complementary_channel_impl {
($new_chx:ident, $channel:ident, $pin_trait:ident, $complementary_pin_trait:ident) => {
($new_chx:ident, $channel:ident, $pin_trait:ident) => {
impl<'d, Perip: CaptureCompare16bitInstance> ComplementaryPwmPin<'d, Perip, $channel> {
pub fn $new_chx(pin: impl Peripheral<P = impl $complementary_pin_trait<Perip>> + 'd) -> Self {
pub fn $new_chx(pin: impl Peripheral<P = impl $pin_trait<Perip>> + 'd, output_type: OutputType) -> Self {
into_ref!(pin);
critical_section::with(|_| {
pin.set_low();
pin.set_as_af(pin.af_num(), AFType::OutputPushPull);
pin.set_as_af(pin.af_num(), output_type.into());
#[cfg(gpio_v2)]
pin.set_speed(crate::gpio::Speed::VeryHigh);
});
@ -36,10 +36,10 @@ macro_rules! complementary_channel_impl {
};
}
complementary_channel_impl!(new_ch1, Ch1, Channel1Pin, Channel1ComplementaryPin);
complementary_channel_impl!(new_ch2, Ch2, Channel2Pin, Channel2ComplementaryPin);
complementary_channel_impl!(new_ch3, Ch3, Channel3Pin, Channel3ComplementaryPin);
complementary_channel_impl!(new_ch4, Ch4, Channel4Pin, Channel4ComplementaryPin);
complementary_channel_impl!(new_ch1, Ch1, Channel1ComplementaryPin);
complementary_channel_impl!(new_ch2, Ch2, Channel2ComplementaryPin);
complementary_channel_impl!(new_ch3, Ch3, Channel3ComplementaryPin);
complementary_channel_impl!(new_ch4, Ch4, Channel4ComplementaryPin);
pub struct ComplementaryPwm<'d, T> {
inner: PeripheralRef<'d, T>,

View File

@ -1,3 +1,6 @@
pub mod complementary_pwm;
pub mod simple_pwm;
use stm32_metapac::timer::vals;
use crate::interrupt;
@ -43,15 +46,123 @@ pub(crate) mod sealed {
pub trait AdvancedControlInstance: GeneralPurpose16bitInstance {
fn regs_advanced() -> crate::pac::timer::TimAdv;
}
pub trait CaptureCompare16bitInstance: GeneralPurpose16bitInstance {
/// Global output enable. Does not do anything on non-advanced timers.
fn enable_outputs(&mut self, enable: bool);
fn set_output_compare_mode(&mut self, channel: Channel, mode: OutputCompareMode);
fn enable_channel(&mut self, channel: Channel, enable: bool);
fn set_compare_value(&mut self, channel: Channel, value: u16);
fn get_max_compare_value(&self) -> u16;
}
pub trait ComplementaryCaptureCompare16bitInstance: CaptureCompare16bitInstance {
fn set_dead_time_clock_division(&mut self, value: vals::Ckd);
fn set_dead_time_value(&mut self, value: u8);
fn enable_complementary_channel(&mut self, channel: Channel, enable: bool);
}
pub trait CaptureCompare32bitInstance: GeneralPurpose32bitInstance {
fn set_output_compare_mode(&mut self, channel: Channel, mode: OutputCompareMode);
fn enable_channel(&mut self, channel: Channel, enable: bool);
fn set_compare_value(&mut self, channel: Channel, value: u32);
fn get_max_compare_value(&self) -> u32;
}
}
#[derive(Clone, Copy)]
pub enum Channel {
Ch1,
Ch2,
Ch3,
Ch4,
}
impl Channel {
pub fn raw(&self) -> usize {
match self {
Channel::Ch1 => 0,
Channel::Ch2 => 1,
Channel::Ch3 => 2,
Channel::Ch4 => 3,
}
}
}
#[derive(Clone, Copy)]
pub enum OutputCompareMode {
Frozen,
ActiveOnMatch,
InactiveOnMatch,
Toggle,
ForceInactive,
ForceActive,
PwmMode1,
PwmMode2,
}
impl From<OutputCompareMode> for stm32_metapac::timer::vals::Ocm {
fn from(mode: OutputCompareMode) -> Self {
match mode {
OutputCompareMode::Frozen => stm32_metapac::timer::vals::Ocm::FROZEN,
OutputCompareMode::ActiveOnMatch => stm32_metapac::timer::vals::Ocm::ACTIVEONMATCH,
OutputCompareMode::InactiveOnMatch => stm32_metapac::timer::vals::Ocm::INACTIVEONMATCH,
OutputCompareMode::Toggle => stm32_metapac::timer::vals::Ocm::TOGGLE,
OutputCompareMode::ForceInactive => stm32_metapac::timer::vals::Ocm::FORCEINACTIVE,
OutputCompareMode::ForceActive => stm32_metapac::timer::vals::Ocm::FORCEACTIVE,
OutputCompareMode::PwmMode1 => stm32_metapac::timer::vals::Ocm::PWMMODE1,
OutputCompareMode::PwmMode2 => stm32_metapac::timer::vals::Ocm::PWMMODE2,
}
}
}
pub trait Basic16bitInstance: sealed::Basic16bitInstance + 'static {}
pub trait GeneralPurpose16bitInstance: sealed::GeneralPurpose16bitInstance + 'static {}
pub trait GeneralPurpose32bitInstance: sealed::GeneralPurpose32bitInstance + 'static {}
pub trait AdvancedControlInstance: sealed::AdvancedControlInstance + 'static {}
pub trait Basic16bitInstance: sealed::Basic16bitInstance + 'static {}
pub trait CaptureCompare16bitInstance:
sealed::CaptureCompare16bitInstance + GeneralPurpose16bitInstance + 'static
{
}
pub trait ComplementaryCaptureCompare16bitInstance:
sealed::ComplementaryCaptureCompare16bitInstance + AdvancedControlInstance + 'static
{
}
pub trait CaptureCompare32bitInstance:
sealed::CaptureCompare32bitInstance + CaptureCompare16bitInstance + GeneralPurpose32bitInstance + 'static
{
}
pin_trait!(Channel1Pin, CaptureCompare16bitInstance);
pin_trait!(Channel1ComplementaryPin, CaptureCompare16bitInstance);
pin_trait!(Channel2Pin, CaptureCompare16bitInstance);
pin_trait!(Channel2ComplementaryPin, CaptureCompare16bitInstance);
pin_trait!(Channel3Pin, CaptureCompare16bitInstance);
pin_trait!(Channel3ComplementaryPin, CaptureCompare16bitInstance);
pin_trait!(Channel4Pin, CaptureCompare16bitInstance);
pin_trait!(Channel4ComplementaryPin, CaptureCompare16bitInstance);
pin_trait!(ExternalTriggerPin, CaptureCompare16bitInstance);
pin_trait!(BreakInputPin, CaptureCompare16bitInstance);
pin_trait!(BreakInputComparator1Pin, CaptureCompare16bitInstance);
pin_trait!(BreakInputComparator2Pin, CaptureCompare16bitInstance);
pin_trait!(BreakInput2Pin, CaptureCompare16bitInstance);
pin_trait!(BreakInput2Comparator1Pin, CaptureCompare16bitInstance);
pin_trait!(BreakInput2Comparator2Pin, CaptureCompare16bitInstance);
#[allow(unused)]
macro_rules! impl_basic_16bit_timer {
@ -140,33 +251,94 @@ macro_rules! impl_32bit_timer {
};
}
#[allow(unused)]
macro_rules! impl_compare_capable_16bit {
($inst:ident) => {
impl sealed::CaptureCompare16bitInstance for crate::peripherals::$inst {
fn enable_outputs(&mut self, _enable: bool) {}
fn set_output_compare_mode(&mut self, channel: Channel, mode: OutputCompareMode) {
use sealed::GeneralPurpose16bitInstance;
let r = Self::regs_gp16();
let raw_channel: usize = channel.raw();
r.ccmr_output(raw_channel / 2)
.modify(|w| w.set_ocm(raw_channel % 2, mode.into()));
}
fn enable_channel(&mut self, channel: Channel, enable: bool) {
use sealed::GeneralPurpose16bitInstance;
Self::regs_gp16()
.ccer()
.modify(|w| w.set_cce(channel.raw(), enable));
}
fn set_compare_value(&mut self, channel: Channel, value: u16) {
use sealed::GeneralPurpose16bitInstance;
Self::regs_gp16().ccr(channel.raw()).modify(|w| w.set_ccr(value));
}
fn get_max_compare_value(&self) -> u16 {
use sealed::GeneralPurpose16bitInstance;
Self::regs_gp16().arr().read().arr()
}
}
};
}
foreach_interrupt! {
($inst:ident, timer, TIM_BASIC, UP, $irq:ident) => {
impl_basic_16bit_timer!($inst, $irq);
impl Basic16bitInstance for crate::peripherals::$inst {
}
impl Basic16bitInstance for crate::peripherals::$inst {}
};
($inst:ident, timer, TIM_GP16, UP, $irq:ident) => {
impl_basic_16bit_timer!($inst, $irq);
impl Basic16bitInstance for crate::peripherals::$inst {
}
impl_compare_capable_16bit!($inst);
impl Basic16bitInstance for crate::peripherals::$inst {}
impl GeneralPurpose16bitInstance for crate::peripherals::$inst {}
impl CaptureCompare16bitInstance for crate::peripherals::$inst {}
impl sealed::GeneralPurpose16bitInstance for crate::peripherals::$inst {
fn regs_gp16() -> crate::pac::timer::TimGp16 {
crate::pac::$inst
}
}
impl GeneralPurpose16bitInstance for crate::peripherals::$inst {
}
};
($inst:ident, timer, TIM_GP32, UP, $irq:ident) => {
impl_basic_16bit_timer!($inst, $irq);
impl_32bit_timer!($inst);
impl_compare_capable_16bit!($inst);
impl Basic16bitInstance for crate::peripherals::$inst {}
impl CaptureCompare16bitInstance for crate::peripherals::$inst {}
impl CaptureCompare32bitInstance for crate::peripherals::$inst {}
impl GeneralPurpose16bitInstance for crate::peripherals::$inst {}
impl GeneralPurpose32bitInstance for crate::peripherals::$inst {}
impl Basic16bitInstance for crate::peripherals::$inst {
impl sealed::CaptureCompare32bitInstance for crate::peripherals::$inst {
fn set_output_compare_mode(
&mut self,
channel: Channel,
mode: OutputCompareMode,
) {
use crate::timer::sealed::GeneralPurpose32bitInstance;
let raw_channel = channel.raw();
Self::regs_gp32().ccmr_output(raw_channel / 2).modify(|w| w.set_ocm(raw_channel % 2, mode.into()));
}
fn enable_channel(&mut self, channel: Channel, enable: bool) {
use crate::timer::sealed::GeneralPurpose32bitInstance;
Self::regs_gp32().ccer().modify(|w| w.set_cce(channel.raw(), enable));
}
fn set_compare_value(&mut self, channel: Channel, value: u32) {
use crate::timer::sealed::GeneralPurpose32bitInstance;
Self::regs_gp32().ccr(channel.raw()).modify(|w| w.set_ccr(value));
}
fn get_max_compare_value(&self) -> u32 {
use crate::timer::sealed::GeneralPurpose32bitInstance;
Self::regs_gp32().arr().read().arr() as u32
}
}
impl sealed::GeneralPurpose16bitInstance for crate::peripherals::$inst {
@ -174,21 +346,16 @@ foreach_interrupt! {
unsafe { crate::pac::timer::TimGp16::from_ptr(crate::pac::$inst.as_ptr()) }
}
}
impl GeneralPurpose16bitInstance for crate::peripherals::$inst {
}
impl_32bit_timer!($inst);
impl GeneralPurpose32bitInstance for crate::peripherals::$inst {
}
};
($inst:ident, timer, TIM_ADV, UP, $irq:ident) => {
impl_basic_16bit_timer!($inst, $irq);
impl Basic16bitInstance for crate::peripherals::$inst {
}
impl Basic16bitInstance for crate::peripherals::$inst {}
impl GeneralPurpose16bitInstance for crate::peripherals::$inst {}
impl CaptureCompare16bitInstance for crate::peripherals::$inst {}
impl ComplementaryCaptureCompare16bitInstance for crate::peripherals::$inst {}
impl AdvancedControlInstance for crate::peripherals::$inst {}
impl sealed::GeneralPurpose16bitInstance for crate::peripherals::$inst {
fn regs_gp16() -> crate::pac::timer::TimGp16 {
@ -196,16 +363,70 @@ foreach_interrupt! {
}
}
impl GeneralPurpose16bitInstance for crate::peripherals::$inst {
}
impl sealed::AdvancedControlInstance for crate::peripherals::$inst {
fn regs_advanced() -> crate::pac::timer::TimAdv {
crate::pac::$inst
}
}
impl AdvancedControlInstance for crate::peripherals::$inst {
impl sealed::CaptureCompare16bitInstance for crate::peripherals::$inst {
fn enable_outputs(&mut self, enable: bool) {
use crate::timer::sealed::AdvancedControlInstance;
let r = Self::regs_advanced();
r.bdtr().modify(|w| w.set_moe(enable));
}
fn set_output_compare_mode(
&mut self,
channel: Channel,
mode: OutputCompareMode,
) {
use crate::timer::sealed::AdvancedControlInstance;
let r = Self::regs_advanced();
let raw_channel: usize = channel.raw();
r.ccmr_output(raw_channel / 2)
.modify(|w| w.set_ocm(raw_channel % 2, mode.into()));
}
fn enable_channel(&mut self, channel: Channel, enable: bool) {
use crate::timer::sealed::AdvancedControlInstance;
Self::regs_advanced()
.ccer()
.modify(|w| w.set_cce(channel.raw(), enable));
}
fn set_compare_value(&mut self, channel: Channel, value: u16) {
use crate::timer::sealed::AdvancedControlInstance;
Self::regs_advanced()
.ccr(channel.raw())
.modify(|w| w.set_ccr(value));
}
fn get_max_compare_value(&self) -> u16 {
use crate::timer::sealed::AdvancedControlInstance;
Self::regs_advanced().arr().read().arr()
}
}
impl sealed::ComplementaryCaptureCompare16bitInstance for crate::peripherals::$inst {
fn set_dead_time_clock_division(&mut self, value: vals::Ckd) {
use crate::timer::sealed::AdvancedControlInstance;
Self::regs_advanced().cr1().modify(|w| w.set_ckd(value));
}
fn set_dead_time_value(&mut self, value: u8) {
use crate::timer::sealed::AdvancedControlInstance;
Self::regs_advanced().bdtr().modify(|w| w.set_dtg(value));
}
fn enable_complementary_channel(&mut self, channel: Channel, enable: bool) {
use crate::timer::sealed::AdvancedControlInstance;
Self::regs_advanced()
.ccer()
.modify(|w| w.set_ccne(channel.raw(), enable));
}
}
};
}

View File

@ -1,11 +1,11 @@
use core::marker::PhantomData;
use embassy_hal_common::{into_ref, PeripheralRef};
use embassy_hal_internal::{into_ref, PeripheralRef};
use super::*;
#[allow(unused_imports)]
use crate::gpio::sealed::{AFType, Pin};
use crate::gpio::AnyPin;
use crate::gpio::{AnyPin, OutputType};
use crate::time::Hertz;
use crate::Peripheral;
@ -22,11 +22,11 @@ pub struct PwmPin<'d, Perip, Channel> {
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<P = impl $pin_trait<Perip>> + 'd) -> Self {
pub fn $new_chx(pin: impl Peripheral<P = impl $pin_trait<Perip>> + 'd, output_type: OutputType) -> Self {
into_ref!(pin);
critical_section::with(|_| {
pin.set_low();
pin.set_as_af(pin.af_num(), AFType::OutputPushPull);
pin.set_as_af(pin.af_num(), output_type.into());
#[cfg(gpio_v2)]
pin.set_speed(crate::gpio::Speed::VeryHigh);
});

View File

@ -2,7 +2,7 @@ use core::future::poll_fn;
use core::slice;
use core::task::Poll;
use embassy_hal_common::atomic_ring_buffer::RingBuffer;
use embassy_hal_internal::atomic_ring_buffer::RingBuffer;
use embassy_sync::waitqueue::AtomicWaker;
use super::*;

View File

@ -5,8 +5,8 @@ use core::marker::PhantomData;
use core::sync::atomic::{compiler_fence, Ordering};
use core::task::Poll;
use embassy_hal_common::drop::OnDrop;
use embassy_hal_common::{into_ref, PeripheralRef};
use embassy_hal_internal::drop::OnDrop;
use embassy_hal_internal::{into_ref, PeripheralRef};
use futures::future::{select, Either};
use crate::dma::{NoDma, Transfer};
@ -857,7 +857,7 @@ fn configure(r: Regs, config: &Config, pclk_freq: Hertz, kind: Kind, enable_rx:
"Using {} oversampling, desired baudrate: {}, actual baudrate: {}",
oversampling,
config.baudrate,
pclk_freq.0 / div
(pclk_freq.0 * mul as u32) / div
);
r.cr2().write(|w| {

View File

@ -2,7 +2,7 @@ use core::future::poll_fn;
use core::sync::atomic::{compiler_fence, Ordering};
use core::task::Poll;
use embassy_hal_common::PeripheralRef;
use embassy_hal_internal::PeripheralRef;
use futures::future::{select, Either};
use super::{clear_interrupt_flags, rdr, sr, BasicInstance, Error, UartRx};

View File

@ -5,7 +5,7 @@ use core::marker::PhantomData;
use core::sync::atomic::{AtomicBool, Ordering};
use core::task::Poll;
use embassy_hal_common::into_ref;
use embassy_hal_internal::into_ref;
use embassy_sync::waitqueue::AtomicWaker;
use embassy_usb_driver as driver;
use embassy_usb_driver::{

View File

@ -3,7 +3,7 @@ use core::marker::PhantomData;
use core::sync::atomic::{AtomicBool, AtomicU16, Ordering};
use core::task::Poll;
use embassy_hal_common::{into_ref, Peripheral};
use embassy_hal_internal::{into_ref, Peripheral};
use embassy_sync::waitqueue::AtomicWaker;
use embassy_usb_driver::{
self, Bus as _, Direction, EndpointAddress, EndpointAllocError, EndpointError, EndpointIn, EndpointInfo,

View File

@ -1,6 +1,6 @@
use core::marker::PhantomData;
use embassy_hal_common::{into_ref, Peripheral};
use embassy_hal_internal::{into_ref, Peripheral};
use stm32_metapac::iwdg::vals::{Key, Pr};
use crate::rcc::LSI_FREQ;