Merge branch 'main' of https://github.com/embassy-rs/embassy into hrtim
This commit is contained in:
@ -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" ]
|
||||
|
@ -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)),
|
||||
|
@ -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};
|
||||
|
@ -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};
|
||||
|
@ -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;
|
||||
|
@ -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};
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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() {
|
||||
|
@ -1,5 +1,5 @@
|
||||
pub use bxcan;
|
||||
use embassy_hal_common::PeripheralRef;
|
||||
use embassy_hal_internal::PeripheralRef;
|
||||
|
||||
use crate::peripherals;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
@ -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()
|
||||
|
@ -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()
|
||||
|
@ -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};
|
||||
|
@ -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::*;
|
||||
|
@ -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
|
||||
|
@ -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};
|
||||
|
@ -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::*;
|
||||
|
@ -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};
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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::{
|
||||
|
@ -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};
|
||||
|
@ -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};
|
||||
|
@ -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};
|
||||
|
@ -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;
|
||||
|
@ -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};
|
||||
|
@ -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;
|
||||
|
@ -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));
|
||||
|
@ -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"))]
|
||||
|
@ -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);
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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};
|
||||
|
||||
|
@ -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};
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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());
|
||||
});
|
||||
}
|
||||
|
@ -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};
|
||||
|
||||
|
@ -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)]
|
||||
|
@ -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 {
|
||||
|
@ -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};
|
||||
|
@ -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::*;
|
@ -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) => {
|
||||
|
@ -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)]
|
@ -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::*;
|
||||
|
@ -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| {
|
||||
|
@ -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};
|
||||
|
@ -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::{
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
Reference in New Issue
Block a user