Merge branch 'main' of https://github.com/embassy-rs/embassy into hrtim

This commit is contained in:
xoviat
2023-07-28 17:18:22 -05:00
181 changed files with 2109 additions and 893 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 }
@ -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"] }
@ -78,40 +79,63 @@ stm32-metapac = { version = "13", default-features = false, features = ["metadat
[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"]
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"]
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" ]
@ -1445,4 +1469,4 @@ stm32wle5cb = [ "stm32-metapac/stm32wle5cb" ]
stm32wle5cc = [ "stm32-metapac/stm32wle5cc" ]
stm32wle5j8 = [ "stm32-metapac/stm32wle5j8" ]
stm32wle5jb = [ "stm32-metapac/stm32wle5jb" ]
stm32wle5jc = [ "stm32-metapac/stm32wle5jc" ]
stm32wle5jc = [ "stm32-metapac/stm32wle5jc" ]

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,21 @@ 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)),

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;
@ -77,6 +77,7 @@ pub struct Can<'d, T: Instance> {
}
#[derive(Debug)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum BusError {
Stuff,
Form,
@ -90,6 +91,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.
@ -161,58 +178,60 @@ impl<'d, T: Instance> Can<'d, T> {
.leave_disabled();
}
/// 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
/// Enables the peripheral and synchronizes with the bus.
///
/// This will wait for 11 consecutive recessive bits (bus idle state).
/// Contrary to enable method from bxcan library, this will not freeze the executor while waiting.
pub async fn enable(&mut self) {
while self.borrow_mut().enable_non_blocking().is_err() {
// SCE interrupt is only generated for entering sleep mode, but not leaving.
// Yield to allow other tasks to execute while can bus is initializing.
embassy_futures::yield_now().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(());
}
/// Queues the message to be sent but exerts backpressure
pub async fn write(&mut self, frame: &Frame) -> bxcan::TransmitStatus {
CanTx { can: &self.can }.write(frame).await
}
Poll::Pending
})
.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> {
CanTx { can: &self.can }.try_write(frame)
}
/// 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<(u16, bxcan::Frame), BusError> {
poll_fn(|cx| {
T::state().err_waker.register(cx.waker());
if let Poll::Ready((time, frame)) = T::state().rx_queue.recv().poll_unpin(cx) {
return Poll::Ready(Ok((time, frame)));
} 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<(u16, bxcan::Frame), 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) {
@ -374,6 +393,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());
@ -385,6 +412,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)]
@ -407,6 +470,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<(u16, bxcan::Frame), 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;
@ -38,11 +38,30 @@ impl Channel {
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
/// Trigger sources for CH1
pub enum Ch1Trigger {
Tim6,
Tim3,
Tim7,
Tim15,
#[cfg(dac_v3)]
Tim1,
Tim2,
#[cfg(not(dac_v3))]
Tim3,
#[cfg(dac_v3)]
Tim4,
#[cfg(dac_v3)]
Tim5,
Tim6,
Tim7,
#[cfg(dac_v3)]
Tim8,
Tim15,
#[cfg(dac_v3)]
Hrtim1Dactrg1,
#[cfg(dac_v3)]
Hrtim1Dactrg2,
#[cfg(dac_v3)]
Lptim1,
#[cfg(dac_v3)]
Lptim2,
#[cfg(dac_v3)]
Lptim3,
Exti9,
Software,
}
@ -50,14 +69,30 @@ pub enum Ch1Trigger {
impl Ch1Trigger {
fn tsel(&self) -> dac::vals::Tsel1 {
match self {
Ch1Trigger::Tim6 => dac::vals::Tsel1::TIM6_TRGO,
#[cfg(dac_v3)]
Ch1Trigger::Tim1 => dac::vals::Tsel1::TIM1_TRGO,
Ch1Trigger::Tim2 => dac::vals::Tsel1::TIM2_TRGO,
#[cfg(not(dac_v3))]
Ch1Trigger::Tim3 => dac::vals::Tsel1::TIM3_TRGO,
#[cfg(dac_v3)]
Ch1Trigger::Tim3 => dac::vals::Tsel1::TIM1_TRGO,
Ch1Trigger::Tim4 => dac::vals::Tsel1::TIM4_TRGO,
#[cfg(dac_v3)]
Ch1Trigger::Tim5 => dac::vals::Tsel1::TIM5_TRGO,
Ch1Trigger::Tim6 => dac::vals::Tsel1::TIM6_TRGO,
Ch1Trigger::Tim7 => dac::vals::Tsel1::TIM7_TRGO,
#[cfg(dac_v3)]
Ch1Trigger::Tim8 => dac::vals::Tsel1::TIM8_TRGO,
Ch1Trigger::Tim15 => dac::vals::Tsel1::TIM15_TRGO,
Ch1Trigger::Tim2 => dac::vals::Tsel1::TIM2_TRGO,
#[cfg(dac_v3)]
Ch1Trigger::Hrtim1Dactrg1 => dac::vals::Tsel1::HRTIM1_DACTRG1,
#[cfg(dac_v3)]
Ch1Trigger::Hrtim1Dactrg2 => dac::vals::Tsel1::HRTIM1_DACTRG2,
#[cfg(dac_v3)]
Ch1Trigger::Lptim1 => dac::vals::Tsel1::LPTIM1_OUT,
#[cfg(dac_v3)]
Ch1Trigger::Lptim2 => dac::vals::Tsel1::LPTIM2_OUT,
#[cfg(dac_v3)]
Ch1Trigger::Lptim3 => dac::vals::Tsel1::LPTIM3_OUT,
Ch1Trigger::Exti9 => dac::vals::Tsel1::EXTI9,
Ch1Trigger::Software => dac::vals::Tsel1::SOFTWARE,
}
@ -129,7 +164,7 @@ pub trait DacChannel<T: Instance, Tx> {
}
/// Set mode register of the given channel
#[cfg(dac_v2)]
#[cfg(any(dac_v2, dac_v3))]
fn set_channel_mode(&mut self, val: u8) -> Result<(), Error> {
T::regs().mcr().modify(|reg| {
reg.set_mode(Self::CHANNEL.index(), val);
@ -216,8 +251,9 @@ impl<'d, T: Instance, Tx> DacCh1<'d, T, Tx> {
pub fn new(
peri: impl Peripheral<P = T> + 'd,
dma: impl Peripheral<P = Tx> + 'd,
_pin: impl Peripheral<P = impl DacPin<T, 1>> + 'd,
pin: impl Peripheral<P = impl DacPin<T, 1>> + crate::gpio::sealed::Pin + 'd,
) -> Self {
pin.set_as_analog();
into_ref!(peri, dma);
T::enable();
T::reset();
@ -226,7 +262,7 @@ impl<'d, T: Instance, Tx> DacCh1<'d, T, Tx> {
// Configure each activated channel. All results can be `unwrap`ed since they
// will only error if the channel is not configured (i.e. ch1, ch2 are false)
#[cfg(dac_v2)]
#[cfg(any(dac_v2, dac_v3))]
dac.set_channel_mode(0).unwrap();
dac.enable_channel().unwrap();
dac.set_trigger_enable(true).unwrap();
@ -252,7 +288,6 @@ impl<'d, T: Instance, Tx> DacCh1<'d, T, Tx> {
/// Note that for performance reasons in circular mode the transfer complete interrupt is disabled.
///
/// **Important:** Channel 1 has to be configured for the DAC instance!
#[cfg(all(bdma, not(dma)))] // It currently only works with BDMA-only chips (DMA should theoretically work though)
pub async fn write(&mut self, data: ValueArray<'_>, circular: bool) -> Result<(), Error>
where
Tx: DmaCh1<T>,
@ -327,8 +362,9 @@ impl<'d, T: Instance, Tx> DacCh2<'d, T, Tx> {
pub fn new(
_peri: impl Peripheral<P = T> + 'd,
dma: impl Peripheral<P = Tx> + 'd,
_pin: impl Peripheral<P = impl DacPin<T, 2>> + 'd,
pin: impl Peripheral<P = impl DacPin<T, 2>> + crate::gpio::sealed::Pin + 'd,
) -> Self {
pin.set_as_analog();
into_ref!(_peri, dma);
T::enable();
T::reset();
@ -340,7 +376,7 @@ impl<'d, T: Instance, Tx> DacCh2<'d, T, Tx> {
// Configure each activated channel. All results can be `unwrap`ed since they
// will only error if the channel is not configured (i.e. ch1, ch2 are false)
#[cfg(dac_v2)]
#[cfg(any(dac_v2, dac_v3))]
dac.set_channel_mode(0).unwrap();
dac.enable_channel().unwrap();
dac.set_trigger_enable(true).unwrap();
@ -364,7 +400,6 @@ impl<'d, T: Instance, Tx> DacCh2<'d, T, Tx> {
/// Note that for performance reasons in circular mode the transfer complete interrupt is disabled.
///
/// **Important:** Channel 2 has to be configured for the DAC instance!
#[cfg(all(bdma, not(dma)))] // It currently only works with BDMA-only chips (DMA should theoretically work though)
pub async fn write(&mut self, data: ValueArray<'_>, circular: bool) -> Result<(), Error>
where
Tx: DmaCh2<T>,
@ -442,9 +477,11 @@ impl<'d, T: Instance, TxCh1, TxCh2> Dac<'d, T, TxCh1, TxCh2> {
peri: impl Peripheral<P = T> + 'd,
dma_ch1: impl Peripheral<P = TxCh1> + 'd,
dma_ch2: impl Peripheral<P = TxCh2> + 'd,
_pin_ch1: impl Peripheral<P = impl DacPin<T, 1>> + 'd,
_pin_ch2: impl Peripheral<P = impl DacPin<T, 2>> + 'd,
pin_ch1: impl Peripheral<P = impl DacPin<T, 1>> + crate::gpio::sealed::Pin + 'd,
pin_ch2: impl Peripheral<P = impl DacPin<T, 2>> + crate::gpio::sealed::Pin + 'd,
) -> Self {
pin_ch1.set_as_analog();
pin_ch2.set_as_analog();
into_ref!(peri, dma_ch1, dma_ch2);
T::enable();
T::reset();
@ -461,12 +498,12 @@ impl<'d, T: Instance, TxCh1, TxCh2> Dac<'d, T, TxCh1, TxCh2> {
// Configure each activated channel. All results can be `unwrap`ed since they
// will only error if the channel is not configured (i.e. ch1, ch2 are false)
#[cfg(dac_v2)]
#[cfg(any(dac_v2, dac_v3))]
dac_ch1.set_channel_mode(0).unwrap();
dac_ch1.enable_channel().unwrap();
dac_ch1.set_trigger_enable(true).unwrap();
#[cfg(dac_v2)]
#[cfg(any(dac_v2, dac_v3))]
dac_ch2.set_channel_mode(0).unwrap();
dac_ch2.enable_channel().unwrap();
dac_ch2.set_trigger_enable(true).unwrap();

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};
@ -28,6 +28,12 @@ pub struct TransferOptions {
pub flow_ctrl: FlowControl,
/// FIFO threshold for DMA FIFO mode. If none, direct mode is used.
pub fifo_threshold: Option<FifoThreshold>,
/// Enable circular DMA
pub circular: bool,
/// Enable half transfer interrupt
pub half_transfer_ir: bool,
/// Enable transfer complete interrupt
pub complete_transfer_ir: bool,
}
impl Default for TransferOptions {
@ -37,6 +43,9 @@ impl Default for TransferOptions {
mburst: Burst::Single,
flow_ctrl: FlowControl::Dma,
fifo_threshold: None,
circular: false,
half_transfer_ir: false,
complete_transfer_ir: true,
}
}
}
@ -365,7 +374,13 @@ impl<'a, C: Channel> Transfer<'a, C> {
});
w.set_pinc(vals::Inc::FIXED);
w.set_teie(true);
w.set_tcie(true);
w.set_tcie(options.complete_transfer_ir);
if options.circular {
w.set_circ(vals::Circ::ENABLED);
debug!("Setting circular mode");
} else {
w.set_circ(vals::Circ::DISABLED);
}
#[cfg(dma_v1)]
w.set_trbuff(true);
@ -646,7 +661,7 @@ impl<'a, C: Channel, W: Word> RingBuffer<'a, C, W> {
w.set_minc(vals::Inc::INCREMENTED);
w.set_pinc(vals::Inc::FIXED);
w.set_teie(true);
w.set_htie(true);
w.set_htie(options.half_transfer_ir);
w.set_tcie(true);
w.set_circ(vals::Circ::ENABLED);
#[cfg(dma_v1)]
@ -696,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};

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;

View File

@ -265,63 +265,9 @@ pub(crate) mod sealed {
}
fn _configure_pwr() {
// TODO: move this to RCC
let pwr = crate::pac::PWR;
// TODO: move the rest of this to rcc
let rcc = crate::pac::RCC;
rcc.cfgr().modify(|w| w.set_stopwuck(true));
pwr.cr1().modify(|w| w.set_dbp(true));
pwr.cr1().modify(|w| w.set_dbp(true));
// configure LSE
rcc.bdcr().modify(|w| w.set_lseon(true));
// select system clock source = PLL
// set PLL coefficients
// m: 2,
// n: 12,
// r: 3,
// q: 4,
// p: 3,
let src_bits = 0b11;
let pllp = (3 - 1) & 0b11111;
let pllq = (4 - 1) & 0b111;
let pllr = (3 - 1) & 0b111;
let plln = 12 & 0b1111111;
let pllm = (2 - 1) & 0b111;
rcc.pllcfgr().modify(|w| {
w.set_pllsrc(src_bits);
w.set_pllm(pllm);
w.set_plln(plln);
w.set_pllr(pllr);
w.set_pllp(pllp);
w.set_pllpen(true);
w.set_pllq(pllq);
w.set_pllqen(true);
});
// enable PLL
rcc.cr().modify(|w| w.set_pllon(true));
rcc.cr().write(|w| w.set_hsion(false));
// while !rcc.cr().read().pllrdy() {}
// configure SYSCLK mux to use PLL clocl
rcc.cfgr().modify(|w| w.set_sw(0b11));
// configure CPU1 & CPU2 dividers
rcc.cfgr().modify(|w| w.set_hpre(0)); // not divided
rcc.extcfgr().modify(|w| {
w.set_c2hpre(0b1000); // div2
w.set_shdhpre(0); // not divided
});
// apply APB1 / APB2 values
rcc.cfgr().modify(|w| {
w.set_ppre1(0b000); // not divided
w.set_ppre2(0b000); // not divided
});
// TODO: required
// set RF wake-up clock = LSE
rcc.csr().modify(|w| w.set_rfwkpsel(0b01));

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"));
@ -44,7 +47,6 @@ pub mod i2c;
pub mod i2s;
#[cfg(stm32wb)]
pub mod ipcc;
pub mod pwm;
#[cfg(quadspi)]
pub mod qspi;
#[cfg(rng)]
@ -80,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),*;)* }) => {
@ -104,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,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,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};

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::regs::Cfgr;
use stm32_metapac::rcc::vals::{Lsedrv, Mcopre, Mcosel};

View File

@ -78,6 +78,14 @@ pub struct Clocks {
/// The existence of this value indicates that the clock configuration can no longer be changed
static mut CLOCK_FREQS: MaybeUninit<Clocks> = MaybeUninit::uninit();
#[cfg(stm32wb)]
/// RCC initialization function
pub(crate) unsafe fn init(config: Config) {
set_freqs(compute_clocks(&config));
configure_clocks(&config);
}
/// Sets the clock frequencies
///
/// Safety: Sets a mutable global.

View File

@ -1,6 +1,5 @@
use crate::pac::RCC;
use crate::rcc::{set_freqs, Clocks};
use crate::time::Hertz;
use crate::rcc::Clocks;
use crate::time::{khz, mhz, Hertz};
/// Most of clock setup is copied from stm32l0xx-hal, and adopted to the generated PAC,
/// and with the addition of the init function to configure a system clock.
@ -13,11 +12,94 @@ pub const HSI_FREQ: Hertz = Hertz(16_000_000);
/// LSI speed
pub const LSI_FREQ: Hertz = Hertz(32_000);
/// System clock mux source
#[derive(Clone, Copy)]
pub enum ClockSrc {
HSE(Hertz),
HSI16,
pub enum HsePrescaler {
NotDivided,
Div2,
}
impl From<HsePrescaler> for bool {
fn from(value: HsePrescaler) -> Self {
match value {
HsePrescaler::NotDivided => false,
HsePrescaler::Div2 => true,
}
}
}
pub struct Hse {
pub prediv: HsePrescaler,
pub frequency: Hertz,
}
/// System clock mux source
#[derive(Clone, Copy, PartialEq)]
pub enum Sysclk {
/// MSI selected as sysclk
MSI,
/// HSI selected as sysclk
HSI,
/// HSE selected as sysclk
HSE,
/// PLL selected as sysclk
Pll,
}
impl From<Sysclk> for u8 {
fn from(value: Sysclk) -> Self {
match value {
Sysclk::MSI => 0b00,
Sysclk::HSI => 0b01,
Sysclk::HSE => 0b10,
Sysclk::Pll => 0b11,
}
}
}
#[derive(Clone, Copy, PartialEq)]
pub enum PllSource {
Hsi,
Msi,
Hse,
}
impl From<PllSource> for u8 {
fn from(value: PllSource) -> Self {
match value {
PllSource::Msi => 0b01,
PllSource::Hsi => 0b10,
PllSource::Hse => 0b11,
}
}
}
pub enum Pll48Source {
PllSai,
Pll,
Msi,
Hsi48,
}
pub struct PllMux {
/// Source clock selection.
pub source: PllSource,
/// PLL pre-divider (DIVM). Must be between 1 and 63.
pub prediv: u8,
}
pub struct Pll {
/// PLL multiplication factor. Must be between 4 and 512.
pub mul: u16,
/// PLL P division factor. If None, PLL P output is disabled. Must be between 1 and 128.
/// On PLL1, it must be even (in particular, it cannot be 1.)
pub divp: Option<u16>,
/// PLL Q division factor. If None, PLL Q output is disabled. Must be between 1 and 128.
pub divq: Option<u16>,
/// PLL R division factor. If None, PLL R output is disabled. Must be between 1 and 128.
pub divr: Option<u16>,
}
/// AHB prescaler
@ -84,86 +166,250 @@ impl Into<u8> for AHBPrescaler {
/// Clocks configutation
pub struct Config {
pub mux: ClockSrc,
pub ahb_pre: AHBPrescaler,
pub hse: Option<Hse>,
pub lse: Option<Hertz>,
pub sys: Sysclk,
pub mux: Option<PllMux>,
pub pll48: Option<Pll48Source>,
pub pll: Option<Pll>,
pub pllsai: Option<Pll>,
pub ahb1_pre: AHBPrescaler,
pub ahb2_pre: AHBPrescaler,
pub ahb3_pre: AHBPrescaler,
pub apb1_pre: APBPrescaler,
pub apb2_pre: APBPrescaler,
}
pub const WPAN_DEFAULT: Config = Config {
hse: Some(Hse {
frequency: mhz(32),
prediv: HsePrescaler::NotDivided,
}),
lse: Some(khz(32)),
sys: Sysclk::Pll,
mux: Some(PllMux {
source: PllSource::Hse,
prediv: 2,
}),
pll48: None,
pll: Some(Pll {
mul: 12,
divp: Some(3),
divq: Some(4),
divr: Some(3),
}),
pllsai: None,
ahb1_pre: AHBPrescaler::NotDivided,
ahb2_pre: AHBPrescaler::Div2,
ahb3_pre: AHBPrescaler::NotDivided,
apb1_pre: APBPrescaler::NotDivided,
apb2_pre: APBPrescaler::NotDivided,
};
impl Default for Config {
#[inline]
fn default() -> Config {
Config {
mux: ClockSrc::HSI16,
ahb_pre: AHBPrescaler::NotDivided,
hse: None,
lse: None,
sys: Sysclk::HSI,
mux: None,
pll48: None,
pll: None,
pllsai: None,
ahb1_pre: AHBPrescaler::NotDivided,
ahb2_pre: AHBPrescaler::NotDivided,
ahb3_pre: AHBPrescaler::NotDivided,
apb1_pre: APBPrescaler::NotDivided,
apb2_pre: APBPrescaler::NotDivided,
}
}
}
pub(crate) unsafe fn init(config: Config) {
let (sys_clk, sw) = match config.mux {
ClockSrc::HSI16 => {
// Enable HSI16
RCC.cr().write(|w| w.set_hsion(true));
while !RCC.cr().read().hsirdy() {}
(HSI_FREQ.0, 0x01)
}
ClockSrc::HSE(freq) => {
// Enable HSE
RCC.cr().write(|w| w.set_hseon(true));
while !RCC.cr().read().hserdy() {}
(freq.0, 0x02)
}
};
RCC.cfgr().modify(|w| {
w.set_sw(sw.into());
w.set_hpre(config.ahb_pre.into());
w.set_ppre1(config.apb1_pre.into());
w.set_ppre2(config.apb2_pre.into());
pub(crate) fn compute_clocks(config: &Config) -> Clocks {
let hse_clk = config.hse.as_ref().map(|hse| match hse.prediv {
HsePrescaler::NotDivided => hse.frequency,
HsePrescaler::Div2 => hse.frequency / 2u32,
});
let ahb_freq: u32 = match config.ahb_pre {
let mux_clk = config.mux.as_ref().map(|pll_mux| {
(match pll_mux.source {
PllSource::Hse => hse_clk.unwrap(),
PllSource::Hsi => HSI_FREQ,
_ => unreachable!(),
} / pll_mux.prediv)
});
let (pll_r, _pll_q, _pll_p) = match &config.pll {
Some(pll) => {
let pll_vco = mux_clk.unwrap() * pll.mul as u32;
(
pll.divr.map(|divr| pll_vco / divr),
pll.divq.map(|divq| pll_vco / divq),
pll.divp.map(|divp| pll_vco / divp),
)
}
None => (None, None, None),
};
let sys_clk = match config.sys {
Sysclk::HSE => hse_clk.unwrap(),
Sysclk::HSI => HSI_FREQ,
Sysclk::Pll => pll_r.unwrap(),
_ => unreachable!(),
};
let ahb1_clk = match config.ahb1_pre {
AHBPrescaler::NotDivided => sys_clk,
pre => {
let pre: u8 = pre.into();
let pre = 1 << (pre as u32 - 7);
let pre = 1u32 << (pre as u32 - 7);
sys_clk / pre
}
};
let (apb1_freq, apb1_tim_freq) = match config.apb1_pre {
APBPrescaler::NotDivided => (ahb_freq, ahb_freq),
let ahb2_clk = match config.ahb2_pre {
AHBPrescaler::NotDivided => sys_clk,
pre => {
let pre: u8 = pre.into();
let pre: u8 = 1 << (pre - 3);
let freq = ahb_freq / pre as u32;
(freq, freq * 2)
let pre = 1u32 << (pre as u32 - 7);
sys_clk / pre
}
};
let (apb2_freq, apb2_tim_freq) = match config.apb2_pre {
APBPrescaler::NotDivided => (ahb_freq, ahb_freq),
let ahb3_clk = match config.ahb3_pre {
AHBPrescaler::NotDivided => sys_clk,
pre => {
let pre: u8 = pre.into();
let pre: u8 = 1 << (pre - 3);
let freq = ahb_freq / pre as u32;
(freq, freq * 2)
let pre = 1u32 << (pre as u32 - 7);
sys_clk / pre
}
};
set_freqs(Clocks {
sys: Hertz(sys_clk),
ahb1: Hertz(ahb_freq),
ahb2: Hertz(ahb_freq),
ahb3: Hertz(ahb_freq),
apb1: Hertz(apb1_freq),
apb2: Hertz(apb2_freq),
apb1_tim: Hertz(apb1_tim_freq),
apb2_tim: Hertz(apb2_tim_freq),
let (apb1_clk, apb1_tim_clk) = match config.apb1_pre {
APBPrescaler::NotDivided => (ahb1_clk, ahb1_clk),
pre => {
let pre: u8 = pre.into();
let pre: u8 = 1 << (pre - 3);
let freq = ahb1_clk / pre as u32;
(freq, freq * 2u32)
}
};
let (apb2_clk, apb2_tim_clk) = match config.apb2_pre {
APBPrescaler::NotDivided => (ahb1_clk, ahb1_clk),
pre => {
let pre: u8 = pre.into();
let pre: u8 = 1 << (pre - 3);
let freq = ahb1_clk / pre as u32;
(freq, freq * 2u32)
}
};
Clocks {
sys: sys_clk,
ahb1: ahb1_clk,
ahb2: ahb2_clk,
ahb3: ahb3_clk,
apb1: apb1_clk,
apb2: apb2_clk,
apb1_tim: apb1_tim_clk,
apb2_tim: apb2_tim_clk,
}
}
pub(crate) fn configure_clocks(config: &Config) {
let pwr = crate::pac::PWR;
let rcc = crate::pac::RCC;
let needs_hsi = if let Some(pll_mux) = &config.mux {
pll_mux.source == PllSource::Hsi
} else {
false
};
if needs_hsi || config.sys == Sysclk::HSI {
rcc.cr().modify(|w| {
w.set_hsion(true);
});
while !rcc.cr().read().hsirdy() {}
}
match &config.lse {
Some(_) => {
rcc.cfgr().modify(|w| w.set_stopwuck(true));
pwr.cr1().modify(|w| w.set_dbp(true));
pwr.cr1().modify(|w| w.set_dbp(true));
rcc.bdcr().modify(|w| w.set_lseon(true));
}
_ => {}
}
match &config.hse {
Some(hse) => {
rcc.cr().modify(|w| {
w.set_hsepre(hse.prediv.into());
w.set_hseon(true);
});
while !rcc.cr().read().hserdy() {}
}
_ => {}
}
match &config.mux {
Some(pll_mux) => {
rcc.pllcfgr().modify(|w| {
w.set_pllm(pll_mux.prediv);
w.set_pllsrc(pll_mux.source.into());
});
}
_ => {}
};
match &config.pll {
Some(pll) => {
rcc.pllcfgr().modify(|w| {
w.set_plln(pll.mul as u8);
pll.divp.map(|divp| {
w.set_pllpen(true);
w.set_pllp((divp - 1) as u8)
});
pll.divq.map(|divq| {
w.set_pllqen(true);
w.set_pllq((divq - 1) as u8)
});
pll.divr.map(|divr| {
// w.set_pllren(true);
w.set_pllr((divr - 1) as u8);
});
});
rcc.cr().modify(|w| w.set_pllon(true));
while !rcc.cr().read().pllrdy() {}
}
_ => {}
}
rcc.cfgr().modify(|w| {
w.set_sw(config.sys.into());
w.set_hpre(config.ahb1_pre.into());
w.set_ppre1(config.apb1_pre.into());
w.set_ppre2(config.apb2_pre.into());
});
rcc.extcfgr().modify(|w| {
w.set_c2hpre(config.ahb2_pre.into());
w.set_shdhpre(config.ahb3_pre.into());
});
}

View File

@ -3,7 +3,7 @@
use core::future::poll_fn;
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};

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

@ -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};
@ -225,6 +225,9 @@ const DMA_TRANSFER_OPTIONS: crate::dma::TransferOptions = crate::dma::TransferOp
mburst: crate::dma::Burst::Incr4,
flow_ctrl: crate::dma::FlowControl::Peripheral,
fifo_threshold: Some(crate::dma::FifoThreshold::Full),
circular: false,
half_transfer_ir: false,
complete_transfer_ir: true,
};
#[cfg(all(sdmmc_v1, not(dma)))]
const DMA_TRANSFER_OPTIONS: crate::dma::TransferOptions = crate::dma::TransferOptions {

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

View File

@ -1,6 +1,6 @@
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::*;

View File

@ -1,3 +1,6 @@
pub mod complementary_pwm;
pub mod simple_pwm;
use stm32_metapac::timer::vals;
use crate::interrupt;
@ -44,24 +47,122 @@ pub(crate) mod sealed {
fn regs_advanced() -> crate::pac::timer::TimAdv;
}
#[cfg(hrtim_v1)]
pub trait HighResolutionControlInstance: RccPeripheral {
type Interrupt: interrupt::typelevel::Interrupt;
pub trait CaptureCompare16bitInstance: GeneralPurpose16bitInstance {
/// Global output enable. Does not do anything on non-advanced timers.
fn enable_outputs(&mut self, enable: bool);
fn regs() -> crate::pac::hrtim::Hrtim;
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 {}
#[cfg(hrtim_v1)]
pub trait HighResolutionControlInstance: sealed::HighResolutionControlInstance + 'static {}
pub trait CaptureCompare16bitInstance:
sealed::CaptureCompare16bitInstance + GeneralPurpose16bitInstance + 'static
{
}
pub trait Basic16bitInstance: sealed::Basic16bitInstance + '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 {
@ -150,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 {
@ -184,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 {
@ -206,17 +363,71 @@ 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));
}
}
};
($inst:ident, hrtim, HRTIM, MASTER, $irq:ident) => {

View File

@ -1,6 +1,6 @@
use core::marker::PhantomData;
use embassy_hal_common::{into_ref, PeripheralRef};
use embassy_hal_internal::{into_ref, PeripheralRef};
use super::*;
#[allow(unused_imports)]

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;