);
});
}
@@ -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)),
diff --git a/embassy-stm32/src/adc/f1.rs b/embassy-stm32/src/adc/f1.rs
index 2322204d5..e577ec289 100644
--- a/embassy-stm32/src/adc/f1.rs
+++ b/embassy-stm32/src/adc/f1.rs
@@ -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};
diff --git a/embassy-stm32/src/adc/v1.rs b/embassy-stm32/src/adc/v1.rs
index d9af0c55e..e8245884e 100644
--- a/embassy-stm32/src/adc/v1.rs
+++ b/embassy-stm32/src/adc/v1.rs
@@ -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};
diff --git a/embassy-stm32/src/adc/v2.rs b/embassy-stm32/src/adc/v2.rs
index 091c1d447..9a7acea53 100644
--- a/embassy-stm32/src/adc/v2.rs
+++ b/embassy-stm32/src/adc/v2.rs
@@ -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;
diff --git a/embassy-stm32/src/adc/v3.rs b/embassy-stm32/src/adc/v3.rs
index 3a6e58cf6..821cc7f6a 100644
--- a/embassy-stm32/src/adc/v3.rs
+++ b/embassy-stm32/src/adc/v3.rs
@@ -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};
diff --git a/embassy-stm32/src/adc/v4.rs b/embassy-stm32/src/adc/v4.rs
index c51c6840f..64d0f0c75 100644
--- a/embassy-stm32/src/adc/v4.rs
+++ b/embassy-stm32/src/adc/v4.rs
@@ -226,7 +226,7 @@ impl Prescaler {
impl<'d, T: Instance> Adc<'d, T> {
pub fn new(adc: impl Peripheral + 'd, delay: &mut impl DelayUs) -> Self {
- embassy_hal_common::into_ref!(adc);
+ embassy_hal_internal::into_ref!(adc);
T::enable();
T::reset();
diff --git a/embassy-stm32/src/can/bxcan.rs b/embassy-stm32/src/can/bxcan.rs
index 5a0153464..1d0fdd532 100644
--- a/embassy-stm32/src/can/bxcan.rs
+++ b/embassy-stm32/src/can/bxcan.rs
@@ -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 {
+ 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 {
- 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 {
+ 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 {
let err = { T::regs().esr().read() };
if err.boff() {
diff --git a/embassy-stm32/src/can/fdcan.rs b/embassy-stm32/src/can/fdcan.rs
index c31a7fc63..f77788db3 100644
--- a/embassy-stm32/src/can/fdcan.rs
+++ b/embassy-stm32/src/can/fdcan.rs
@@ -1,5 +1,5 @@
pub use bxcan;
-use embassy_hal_common::PeripheralRef;
+use embassy_hal_internal::PeripheralRef;
use crate::peripherals;
diff --git a/embassy-stm32/src/crc/v1.rs b/embassy-stm32/src/crc/v1.rs
index 3946a2d47..154f2eb91 100644
--- a/embassy-stm32/src/crc/v1.rs
+++ b/embassy-stm32/src/crc/v1.rs
@@ -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;
diff --git a/embassy-stm32/src/crc/v2v3.rs b/embassy-stm32/src/crc/v2v3.rs
index f337055a7..de0c08755 100644
--- a/embassy-stm32/src/crc/v2v3.rs
+++ b/embassy-stm32/src/crc/v2v3.rs
@@ -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;
diff --git a/embassy-stm32/src/dac/mod.rs b/embassy-stm32/src/dac/mod.rs
index 3d58914b3..a2040b857 100644
--- a/embassy-stm32/src/dac/mod.rs
+++ b/embassy-stm32/src/dac/mod.rs
@@ -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 {
}
/// 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 + 'd,
dma: impl Peripheral
+ 'd,
- _pin: impl Peripheral
> + 'd,
+ pin: impl Peripheral
> + 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,
@@ -327,8 +362,9 @@ impl<'d, T: Instance, Tx> DacCh2<'d, T, Tx> {
pub fn new(
_peri: impl Peripheral + 'd,
dma: impl Peripheral
+ 'd,
- _pin: impl Peripheral
> + 'd,
+ pin: impl Peripheral
> + 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,
@@ -442,9 +477,11 @@ impl<'d, T: Instance, TxCh1, TxCh2> Dac<'d, T, TxCh1, TxCh2> {
peri: impl Peripheral + 'd,
dma_ch1: impl Peripheral
+ 'd,
dma_ch2: impl Peripheral
+ 'd,
- _pin_ch1: impl Peripheral
> + 'd,
- _pin_ch2: impl Peripheral
> + 'd,
+ pin_ch1: impl Peripheral
> + crate::gpio::sealed::Pin + 'd,
+ pin_ch2: impl Peripheral
> + 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();
diff --git a/embassy-stm32/src/dcmi.rs b/embassy-stm32/src/dcmi.rs
index 78b026cb6..7497f4aaa 100644
--- a/embassy-stm32/src/dcmi.rs
+++ b/embassy-stm32/src/dcmi.rs
@@ -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;
diff --git a/embassy-stm32/src/dma/bdma.rs b/embassy-stm32/src/dma/bdma.rs
index 5a87888b7..d956047d5 100644
--- a/embassy-stm32/src/dma/bdma.rs
+++ b/embassy-stm32/src/dma/bdma.rs
@@ -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 {
+ 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()
diff --git a/embassy-stm32/src/dma/dma.rs b/embassy-stm32/src/dma/dma.rs
index 58d438af8..219ef2eb0 100644
--- a/embassy-stm32/src/dma/dma.rs
+++ b/embassy-stm32/src/dma/dma.rs
@@ -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,
+ /// 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 {
+ 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()
diff --git a/embassy-stm32/src/dma/gpdma.rs b/embassy-stm32/src/dma/gpdma.rs
index b7bcf7795..97cc200d7 100644
--- a/embassy-stm32/src/dma/gpdma.rs
+++ b/embassy-stm32/src/dma/gpdma.rs
@@ -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};
diff --git a/embassy-stm32/src/dma/mod.rs b/embassy-stm32/src/dma/mod.rs
index 0858587bd..4f1a58ae2 100644
--- a/embassy-stm32/src/dma/mod.rs
+++ b/embassy-stm32/src/dma/mod.rs
@@ -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::*;
diff --git a/embassy-stm32/src/dma/ringbuffer.rs b/embassy-stm32/src/dma/ringbuffer.rs
index a2bde986f..190793974 100644
--- a/embassy-stm32/src/dma/ringbuffer.rs
+++ b/embassy-stm32/src/dma/ringbuffer.rs
@@ -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 {
- // 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
diff --git a/embassy-stm32/src/eth/v1/mod.rs b/embassy-stm32/src/eth/v1/mod.rs
index 2a6ea35ff..a1e0240c8 100644
--- a/embassy-stm32/src/eth/v1/mod.rs
+++ b/embassy-stm32/src/eth/v1/mod.rs
@@ -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};
diff --git a/embassy-stm32/src/eth/v2/mod.rs b/embassy-stm32/src/eth/v2/mod.rs
index bb681c42b..ada495fdb 100644
--- a/embassy-stm32/src/eth/v2/mod.rs
+++ b/embassy-stm32/src/eth/v2/mod.rs
@@ -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::*;
diff --git a/embassy-stm32/src/exti.rs b/embassy-stm32/src/exti.rs
index 3ff92c9e6..925cf39be 100644
--- a/embassy-stm32/src/exti.rs
+++ b/embassy-stm32/src/exti.rs
@@ -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};
diff --git a/embassy-stm32/src/flash/asynch.rs b/embassy-stm32/src/flash/asynch.rs
index f175349cd..e966e2a77 100644
--- a/embassy-stm32/src/flash/asynch.rs
+++ b/embassy-stm32/src/flash/asynch.rs
@@ -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;
diff --git a/embassy-stm32/src/flash/common.rs b/embassy-stm32/src/flash/common.rs
index 2a374733d..16c511295 100644
--- a/embassy-stm32/src/flash/common.rs
+++ b/embassy-stm32/src/flash/common.rs
@@ -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::{
diff --git a/embassy-stm32/src/flash/f4.rs b/embassy-stm32/src/flash/f4.rs
index 4cb39e033..728f6d604 100644
--- a/embassy-stm32/src/flash/f4.rs
+++ b/embassy-stm32/src/flash/f4.rs
@@ -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};
diff --git a/embassy-stm32/src/fmc.rs b/embassy-stm32/src/fmc.rs
index 60d7a00ee..177e66a91 100644
--- a/embassy-stm32/src/fmc.rs
+++ b/embassy-stm32/src/fmc.rs
@@ -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};
diff --git a/embassy-stm32/src/gpio.rs b/embassy-stm32/src/gpio.rs
index af3a8eaca..cda597145 100644
--- a/embassy-stm32/src/gpio.rs
+++ b/embassy-stm32/src/gpio.rs
@@ -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};
diff --git a/embassy-stm32/src/i2c/v1.rs b/embassy-stm32/src/i2c/v1.rs
index aa485cd86..e5254a8cd 100644
--- a/embassy-stm32/src/i2c/v1.rs
+++ b/embassy-stm32/src/i2c/v1.rs
@@ -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;
diff --git a/embassy-stm32/src/i2c/v2.rs b/embassy-stm32/src/i2c/v2.rs
index 208d1527d..eaf980a4d 100644
--- a/embassy-stm32/src/i2c/v2.rs
+++ b/embassy-stm32/src/i2c/v2.rs
@@ -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};
diff --git a/embassy-stm32/src/i2s.rs b/embassy-stm32/src/i2s.rs
index 62dda69b4..1ccad7328 100644
--- a/embassy-stm32/src/i2s.rs
+++ b/embassy-stm32/src/i2s.rs
@@ -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;
diff --git a/embassy-stm32/src/ipcc.rs b/embassy-stm32/src/ipcc.rs
index a24cba9f0..e100ca5cc 100644
--- a/embassy-stm32/src/ipcc.rs
+++ b/embassy-stm32/src/ipcc.rs
@@ -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));
diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs
index 8c005bfed..34220fbf5 100644
--- a/embassy-stm32/src/lib.rs
+++ b/embassy-stm32/src/lib.rs
@@ -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#"{feature}"#)]
+
// 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"))]
diff --git a/embassy-stm32/src/pwm/mod.rs b/embassy-stm32/src/pwm/mod.rs
deleted file mode 100644
index 5aba2663e..000000000
--- a/embassy-stm32/src/pwm/mod.rs
+++ /dev/null
@@ -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 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);
diff --git a/embassy-stm32/src/qspi/mod.rs b/embassy-stm32/src/qspi/mod.rs
index 31b676088..32382fb28 100644
--- a/embassy-stm32/src/qspi/mod.rs
+++ b/embassy-stm32/src/qspi/mod.rs
@@ -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;
diff --git a/embassy-stm32/src/rcc/f4.rs b/embassy-stm32/src/rcc/f4.rs
index b84470440..7aa9f0fd2 100644
--- a/embassy-stm32/src/rcc/f4.rs
+++ b/embassy-stm32/src/rcc/f4.rs
@@ -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;
diff --git a/embassy-stm32/src/rcc/h7.rs b/embassy-stm32/src/rcc/h7.rs
index 7e5cd0d1a..bbc0e0831 100644
--- a/embassy-stm32/src/rcc/h7.rs
+++ b/embassy-stm32/src/rcc/h7.rs
@@ -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};
diff --git a/embassy-stm32/src/rcc/l4.rs b/embassy-stm32/src/rcc/l4.rs
index 8a9b4adbf..dc5f55d0c 100644
--- a/embassy-stm32/src/rcc/l4.rs
+++ b/embassy-stm32/src/rcc/l4.rs
@@ -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};
diff --git a/embassy-stm32/src/rcc/mod.rs b/embassy-stm32/src/rcc/mod.rs
index 886fc0b93..4ae65d3e6 100644
--- a/embassy-stm32/src/rcc/mod.rs
+++ b/embassy-stm32/src/rcc/mod.rs
@@ -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 = 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.
diff --git a/embassy-stm32/src/rcc/wb.rs b/embassy-stm32/src/rcc/wb.rs
index e6123821a..4322b950a 100644
--- a/embassy-stm32/src/rcc/wb.rs
+++ b/embassy-stm32/src/rcc/wb.rs
@@ -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 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 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 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,
+ /// PLL Q division factor. If None, PLL Q output is disabled. Must be between 1 and 128.
+ pub divq: Option,
+ /// PLL R division factor. If None, PLL R output is disabled. Must be between 1 and 128.
+ pub divr: Option,
}
/// AHB prescaler
@@ -84,86 +166,250 @@ impl Into for AHBPrescaler {
/// Clocks configutation
pub struct Config {
- pub mux: ClockSrc,
- pub ahb_pre: AHBPrescaler,
+ pub hse: Option,
+ pub lse: Option,
+ pub sys: Sysclk,
+ pub mux: Option,
+ pub pll48: Option,
+
+ pub pll: Option,
+ pub pllsai: Option,
+
+ 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());
});
}
diff --git a/embassy-stm32/src/rng.rs b/embassy-stm32/src/rng.rs
index b2faec53d..27415c2d7 100644
--- a/embassy-stm32/src/rng.rs
+++ b/embassy-stm32/src/rng.rs
@@ -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};
diff --git a/embassy-stm32/src/rtc/mod.rs b/embassy-stm32/src/rtc/mod.rs
index 12a2ac795..323be3187 100644
--- a/embassy-stm32/src/rtc/mod.rs
+++ b/embassy-stm32/src/rtc/mod.rs
@@ -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)]
diff --git a/embassy-stm32/src/sdmmc/mod.rs b/embassy-stm32/src/sdmmc/mod.rs
index 698292bff..6b532363c 100644
--- a/embassy-stm32/src/sdmmc/mod.rs
+++ b/embassy-stm32/src/sdmmc/mod.rs
@@ -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 {
diff --git a/embassy-stm32/src/spi/mod.rs b/embassy-stm32/src/spi/mod.rs
index d5f63f84e..bdf3c85b0 100644
--- a/embassy-stm32/src/spi/mod.rs
+++ b/embassy-stm32/src/spi/mod.rs
@@ -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};
diff --git a/embassy-stm32/src/pwm/complementary_pwm.rs b/embassy-stm32/src/timer/complementary_pwm.rs
similarity index 99%
rename from embassy-stm32/src/pwm/complementary_pwm.rs
rename to embassy-stm32/src/timer/complementary_pwm.rs
index 4d64d005c..64bb32c39 100644
--- a/embassy-stm32/src/pwm/complementary_pwm.rs
+++ b/embassy-stm32/src/timer/complementary_pwm.rs
@@ -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::*;
diff --git a/embassy-stm32/src/timer/mod.rs b/embassy-stm32/src/timer/mod.rs
index a92f854ec..286ab556f 100644
--- a/embassy-stm32/src/timer/mod.rs
+++ b/embassy-stm32/src/timer/mod.rs
@@ -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 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) => {
diff --git a/embassy-stm32/src/pwm/simple_pwm.rs b/embassy-stm32/src/timer/simple_pwm.rs
similarity index 98%
rename from embassy-stm32/src/pwm/simple_pwm.rs
rename to embassy-stm32/src/timer/simple_pwm.rs
index 995f59c23..514796930 100644
--- a/embassy-stm32/src/pwm/simple_pwm.rs
+++ b/embassy-stm32/src/timer/simple_pwm.rs
@@ -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)]
diff --git a/embassy-stm32/src/usart/buffered.rs b/embassy-stm32/src/usart/buffered.rs
index 433ad299c..ca117da82 100644
--- a/embassy-stm32/src/usart/buffered.rs
+++ b/embassy-stm32/src/usart/buffered.rs
@@ -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::*;
diff --git a/embassy-stm32/src/usart/mod.rs b/embassy-stm32/src/usart/mod.rs
index ea8e525ea..d99034bca 100644
--- a/embassy-stm32/src/usart/mod.rs
+++ b/embassy-stm32/src/usart/mod.rs
@@ -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| {
diff --git a/embassy-stm32/src/usart/ringbuffered.rs b/embassy-stm32/src/usart/ringbuffered.rs
index c74d7e092..80261d048 100644
--- a/embassy-stm32/src/usart/ringbuffered.rs
+++ b/embassy-stm32/src/usart/ringbuffered.rs
@@ -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};
diff --git a/embassy-stm32/src/usb/usb.rs b/embassy-stm32/src/usb/usb.rs
index ecdd1d0b8..cef196355 100644
--- a/embassy-stm32/src/usb/usb.rs
+++ b/embassy-stm32/src/usb/usb.rs
@@ -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::{
diff --git a/embassy-stm32/src/usb_otg/usb.rs b/embassy-stm32/src/usb_otg/usb.rs
index fd0e22adf..348f0f79d 100644
--- a/embassy-stm32/src/usb_otg/usb.rs
+++ b/embassy-stm32/src/usb_otg/usb.rs
@@ -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,
diff --git a/embassy-stm32/src/wdg/mod.rs b/embassy-stm32/src/wdg/mod.rs
index b03e81d6e..eafd03364 100644
--- a/embassy-stm32/src/wdg/mod.rs
+++ b/embassy-stm32/src/wdg/mod.rs
@@ -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;
diff --git a/examples/nrf-rtos-trace/Cargo.toml b/examples/nrf-rtos-trace/Cargo.toml
index 30b67b7b2..068474e7a 100644
--- a/examples/nrf-rtos-trace/Cargo.toml
+++ b/examples/nrf-rtos-trace/Cargo.toml
@@ -34,3 +34,6 @@ log = { version = "0.4.17", optional = true }
[[bin]]
name = "rtos_trace"
required-features = ["nightly"]
+
+[profile.release]
+debug = 2
diff --git a/examples/nrf52840-rtic/Cargo.toml b/examples/nrf52840-rtic/Cargo.toml
index ded3b7db8..715f1ecfe 100644
--- a/examples/nrf52840-rtic/Cargo.toml
+++ b/examples/nrf52840-rtic/Cargo.toml
@@ -19,3 +19,6 @@ cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-sing
cortex-m-rt = "0.7.0"
panic-probe = { version = "0.3", features = ["print-defmt"] }
futures = { version = "0.3.17", default-features = false, features = ["async-await"] }
+
+[profile.release]
+debug = 2
diff --git a/examples/nrf52840/Cargo.toml b/examples/nrf52840/Cargo.toml
index 9b41ec5ab..780aaeac2 100644
--- a/examples/nrf52840/Cargo.toml
+++ b/examples/nrf52840/Cargo.toml
@@ -57,5 +57,5 @@ embedded-hal-async = { version = "0.2.0-alpha.2", optional = true }
num-integer = { version = "0.1.45", default-features = false }
microfft = "0.5.0"
-[patch.crates-io]
-lora-phy = { git = "https://github.com/embassy-rs/lora-phy", rev = "ad289428fd44b02788e2fa2116445cc8f640a265" }
+[profile.release]
+debug = 2
diff --git a/examples/nrf5340/Cargo.toml b/examples/nrf5340/Cargo.toml
index f1d45f336..b0e51dcf4 100644
--- a/examples/nrf5340/Cargo.toml
+++ b/examples/nrf5340/Cargo.toml
@@ -53,3 +53,6 @@ rand = { version = "0.8.4", default-features = false }
embedded-storage = "0.3.0"
usbd-hid = "0.6.0"
serde = { version = "1.0.136", default-features = false }
+
+[profile.release]
+debug = 2
diff --git a/examples/rp/Cargo.toml b/examples/rp/Cargo.toml
index c812cb3ee..8c61dc5e1 100644
--- a/examples/rp/Cargo.toml
+++ b/examples/rp/Cargo.toml
@@ -53,7 +53,4 @@ pio = "0.2.1"
rand = { version = "0.8.5", default-features = false }
[profile.release]
-debug = true
-
-[patch.crates-io]
-lora-phy = { git = "https://github.com/embassy-rs/lora-phy", rev = "ad289428fd44b02788e2fa2116445cc8f640a265" }
+debug = 2
diff --git a/examples/rp/src/bin/pio_async.rs b/examples/rp/src/bin/pio_async.rs
index c001d6440..a6d6144be 100644
--- a/examples/rp/src/bin/pio_async.rs
+++ b/examples/rp/src/bin/pio_async.rs
@@ -8,7 +8,6 @@ use embassy_executor::Spawner;
use embassy_rp::bind_interrupts;
use embassy_rp::peripherals::PIO0;
use embassy_rp::pio::{Common, Config, InterruptHandler, Irq, Pio, PioPin, ShiftDirection, StateMachine};
-use embassy_rp::relocate::RelocatedProgram;
use fixed::traits::ToFixed;
use fixed_macro::types::U56F8;
use {defmt_rtt as _, panic_probe as _};
@@ -29,9 +28,8 @@ fn setup_pio_task_sm0<'a>(pio: &mut Common<'a, PIO0>, sm: &mut StateMachine<'a,
".wrap",
);
- let relocated = RelocatedProgram::new(&prg.program);
let mut cfg = Config::default();
- cfg.use_program(&pio.load_program(&relocated), &[]);
+ cfg.use_program(&pio.load_program(&prg.program), &[]);
let out_pin = pio.make_pio_pin(pin);
cfg.set_out_pins(&[&out_pin]);
cfg.set_set_pins(&[&out_pin]);
@@ -65,9 +63,8 @@ fn setup_pio_task_sm1<'a>(pio: &mut Common<'a, PIO0>, sm: &mut StateMachine<'a,
".wrap",
);
- let relocated = RelocatedProgram::new(&prg.program);
let mut cfg = Config::default();
- cfg.use_program(&pio.load_program(&relocated), &[]);
+ cfg.use_program(&pio.load_program(&prg.program), &[]);
cfg.clock_divider = (U56F8!(125_000_000) / 2000).to_fixed();
cfg.shift_in.auto_fill = true;
cfg.shift_in.direction = ShiftDirection::Right;
@@ -96,9 +93,8 @@ fn setup_pio_task_sm2<'a>(pio: &mut Common<'a, PIO0>, sm: &mut StateMachine<'a,
"irq 3 [15]",
".wrap",
);
- let relocated = RelocatedProgram::new(&prg.program);
let mut cfg = Config::default();
- cfg.use_program(&pio.load_program(&relocated), &[]);
+ cfg.use_program(&pio.load_program(&prg.program), &[]);
cfg.clock_divider = (U56F8!(125_000_000) / 2000).to_fixed();
sm.set_config(&cfg);
}
diff --git a/examples/rp/src/bin/pio_dma.rs b/examples/rp/src/bin/pio_dma.rs
index 9ab72e1f3..86e5017ac 100644
--- a/examples/rp/src/bin/pio_dma.rs
+++ b/examples/rp/src/bin/pio_dma.rs
@@ -8,7 +8,6 @@ use embassy_executor::Spawner;
use embassy_futures::join::join;
use embassy_rp::peripherals::PIO0;
use embassy_rp::pio::{Config, InterruptHandler, Pio, ShiftConfig, ShiftDirection};
-use embassy_rp::relocate::RelocatedProgram;
use embassy_rp::{bind_interrupts, Peripheral};
use fixed::traits::ToFixed;
use fixed_macro::types::U56F8;
@@ -46,9 +45,8 @@ async fn main(_spawner: Spawner) {
".wrap",
);
- let relocated = RelocatedProgram::new(&prg.program);
let mut cfg = Config::default();
- cfg.use_program(&common.load_program(&relocated), &[]);
+ cfg.use_program(&common.load_program(&prg.program), &[]);
cfg.clock_divider = (U56F8!(125_000_000) / U56F8!(10_000)).to_fixed();
cfg.shift_in = ShiftConfig {
auto_fill: true,
diff --git a/examples/rp/src/bin/pio_hd44780.rs b/examples/rp/src/bin/pio_hd44780.rs
index 8aedd24b6..d80c5c24b 100644
--- a/examples/rp/src/bin/pio_hd44780.rs
+++ b/examples/rp/src/bin/pio_hd44780.rs
@@ -14,7 +14,6 @@ use embassy_rp::pio::{
Config, Direction, FifoJoin, InterruptHandler, Pio, PioPin, ShiftConfig, ShiftDirection, StateMachine,
};
use embassy_rp::pwm::{self, Pwm};
-use embassy_rp::relocate::RelocatedProgram;
use embassy_rp::{bind_interrupts, into_ref, Peripheral, PeripheralRef};
use embassy_time::{Duration, Instant, Timer};
use {defmt_rtt as _, panic_probe as _};
@@ -127,9 +126,8 @@ impl<'l> HD44780<'l> {
sm0.set_pin_dirs(Direction::Out, &[&rs, &rw, &e, &db4, &db5, &db6, &db7]);
- let relocated = RelocatedProgram::new(&prg.program);
let mut cfg = Config::default();
- cfg.use_program(&common.load_program(&relocated), &[&e]);
+ cfg.use_program(&common.load_program(&prg.program), &[&e]);
cfg.clock_divider = 125u8.into();
cfg.set_out_pins(&[&db4, &db5, &db6, &db7]);
cfg.shift_out = ShiftConfig {
@@ -201,9 +199,8 @@ impl<'l> HD44780<'l> {
"#
);
- let relocated = RelocatedProgram::new(&prg.program);
let mut cfg = Config::default();
- cfg.use_program(&common.load_program(&relocated), &[&e]);
+ cfg.use_program(&common.load_program(&prg.program), &[&e]);
cfg.clock_divider = 8u8.into(); // ~64ns/insn
cfg.set_jmp_pin(&db7);
cfg.set_set_pins(&[&rs, &rw]);
diff --git a/examples/rp/src/bin/pio_uart.rs b/examples/rp/src/bin/pio_uart.rs
new file mode 100644
index 000000000..5fddbe292
--- /dev/null
+++ b/examples/rp/src/bin/pio_uart.rs
@@ -0,0 +1,392 @@
+//! This example shows how to use the PIO module in the RP2040 chip to implement a duplex UART.
+//! The PIO module is a very powerful peripheral that can be used to implement many different
+//! protocols. It is a very flexible state machine that can be programmed to do almost anything.
+//!
+//! This example opens up a USB device that implements a CDC ACM serial port. It then uses the
+//! PIO module to implement a UART that is connected to the USB serial port. This allows you to
+//! communicate with a device connected to the RP2040 over USB serial.
+
+#![no_std]
+#![no_main]
+#![feature(type_alias_impl_trait)]
+#![feature(async_fn_in_trait)]
+
+use defmt::{info, panic, trace};
+use embassy_executor::Spawner;
+use embassy_futures::join::{join, join3};
+use embassy_rp::bind_interrupts;
+use embassy_rp::peripherals::{PIO0, USB};
+use embassy_rp::pio::InterruptHandler as PioInterruptHandler;
+use embassy_rp::usb::{Driver, Instance, InterruptHandler};
+use embassy_sync::blocking_mutex::raw::NoopRawMutex;
+use embassy_sync::pipe::Pipe;
+use embassy_usb::class::cdc_acm::{CdcAcmClass, Receiver, Sender, State};
+use embassy_usb::driver::EndpointError;
+use embassy_usb::{Builder, Config};
+use embedded_io::asynch::{Read, Write};
+use {defmt_rtt as _, panic_probe as _};
+
+use crate::uart::PioUart;
+use crate::uart_rx::PioUartRx;
+use crate::uart_tx::PioUartTx;
+
+bind_interrupts!(struct Irqs {
+ USBCTRL_IRQ => InterruptHandler;
+ PIO0_IRQ_0 => PioInterruptHandler;
+});
+
+#[embassy_executor::main]
+async fn main(_spawner: Spawner) {
+ info!("Hello there!");
+
+ let p = embassy_rp::init(Default::default());
+
+ // Create the driver, from the HAL.
+ let driver = Driver::new(p.USB, Irqs);
+
+ // Create embassy-usb Config
+ let mut config = Config::new(0xc0de, 0xcafe);
+ config.manufacturer = Some("Embassy");
+ config.product = Some("PIO UART example");
+ config.serial_number = Some("12345678");
+ config.max_power = 100;
+ config.max_packet_size_0 = 64;
+
+ // Required for windows compatibility.
+ // https://developer.nordicsemi.com/nRF_Connect_SDK/doc/1.9.1/kconfig/CONFIG_CDC_ACM_IAD.html#help
+ config.device_class = 0xEF;
+ config.device_sub_class = 0x02;
+ config.device_protocol = 0x01;
+ config.composite_with_iads = true;
+
+ // Create embassy-usb DeviceBuilder using the driver and config.
+ // It needs some buffers for building the descriptors.
+ let mut device_descriptor = [0; 256];
+ let mut config_descriptor = [0; 256];
+ let mut bos_descriptor = [0; 256];
+ let mut control_buf = [0; 64];
+
+ let mut state = State::new();
+
+ let mut builder = Builder::new(
+ driver,
+ config,
+ &mut device_descriptor,
+ &mut config_descriptor,
+ &mut bos_descriptor,
+ &mut control_buf,
+ );
+
+ // Create classes on the builder.
+ let class = CdcAcmClass::new(&mut builder, &mut state, 64);
+
+ // Build the builder.
+ let mut usb = builder.build();
+
+ // Run the USB device.
+ let usb_fut = usb.run();
+
+ // PIO UART setup
+ let uart = PioUart::new(9600, p.PIO0, p.PIN_4, p.PIN_5);
+ let (mut uart_tx, mut uart_rx) = uart.split();
+
+ // Pipe setup
+ let usb_pipe: Pipe = Pipe::new();
+ let mut usb_pipe_writer = usb_pipe.writer();
+ let mut usb_pipe_reader = usb_pipe.reader();
+
+ let uart_pipe: Pipe = Pipe::new();
+ let mut uart_pipe_writer = uart_pipe.writer();
+ let mut uart_pipe_reader = uart_pipe.reader();
+
+ let (mut usb_tx, mut usb_rx) = class.split();
+
+ // Read + write from USB
+ let usb_future = async {
+ loop {
+ info!("Wait for USB connection");
+ usb_rx.wait_connection().await;
+ info!("Connected");
+ let _ = join(
+ usb_read(&mut usb_rx, &mut uart_pipe_writer),
+ usb_write(&mut usb_tx, &mut usb_pipe_reader),
+ )
+ .await;
+ info!("Disconnected");
+ }
+ };
+
+ // Read + write from UART
+ let uart_future = join(
+ uart_read(&mut uart_rx, &mut usb_pipe_writer),
+ uart_write(&mut uart_tx, &mut uart_pipe_reader),
+ );
+
+ // Run everything concurrently.
+ // If we had made everything `'static` above instead, we could do this using separate tasks instead.
+ join3(usb_fut, usb_future, uart_future).await;
+}
+
+struct Disconnected {}
+
+impl From for Disconnected {
+ fn from(val: EndpointError) -> Self {
+ match val {
+ EndpointError::BufferOverflow => panic!("Buffer overflow"),
+ EndpointError::Disabled => Disconnected {},
+ }
+ }
+}
+
+/// Read from the USB and write it to the UART TX pipe
+async fn usb_read<'d, T: Instance + 'd>(
+ usb_rx: &mut Receiver<'d, Driver<'d, T>>,
+ uart_pipe_writer: &mut embassy_sync::pipe::Writer<'_, NoopRawMutex, 20>,
+) -> Result<(), Disconnected> {
+ let mut buf = [0; 64];
+ loop {
+ let n = usb_rx.read_packet(&mut buf).await?;
+ let data = &buf[..n];
+ trace!("USB IN: {:x}", data);
+ uart_pipe_writer.write(data).await;
+ }
+}
+
+/// Read from the USB TX pipe and write it to the USB
+async fn usb_write<'d, T: Instance + 'd>(
+ usb_tx: &mut Sender<'d, Driver<'d, T>>,
+ usb_pipe_reader: &mut embassy_sync::pipe::Reader<'_, NoopRawMutex, 20>,
+) -> Result<(), Disconnected> {
+ let mut buf = [0; 64];
+ loop {
+ let n = usb_pipe_reader.read(&mut buf).await;
+ let data = &buf[..n];
+ trace!("USB OUT: {:x}", data);
+ usb_tx.write_packet(&data).await?;
+ }
+}
+
+/// Read from the UART and write it to the USB TX pipe
+async fn uart_read(
+ uart_rx: &mut PioUartRx<'_>,
+ usb_pipe_writer: &mut embassy_sync::pipe::Writer<'_, NoopRawMutex, 20>,
+) -> ! {
+ let mut buf = [0; 64];
+ loop {
+ let n = uart_rx.read(&mut buf).await.expect("UART read error");
+ if n == 0 {
+ continue;
+ }
+ let data = &buf[..n];
+ trace!("UART IN: {:x}", buf);
+ usb_pipe_writer.write(data).await;
+ }
+}
+
+/// Read from the UART TX pipe and write it to the UART
+async fn uart_write(
+ uart_tx: &mut PioUartTx<'_>,
+ uart_pipe_reader: &mut embassy_sync::pipe::Reader<'_, NoopRawMutex, 20>,
+) -> ! {
+ let mut buf = [0; 64];
+ loop {
+ let n = uart_pipe_reader.read(&mut buf).await;
+ let data = &buf[..n];
+ trace!("UART OUT: {:x}", data);
+ let _ = uart_tx.write(&data).await;
+ }
+}
+
+mod uart {
+ use embassy_rp::peripherals::PIO0;
+ use embassy_rp::pio::{Pio, PioPin};
+ use embassy_rp::Peripheral;
+
+ use crate::uart_rx::PioUartRx;
+ use crate::uart_tx::PioUartTx;
+ use crate::Irqs;
+
+ pub struct PioUart<'a> {
+ tx: PioUartTx<'a>,
+ rx: PioUartRx<'a>,
+ }
+
+ impl<'a> PioUart<'a> {
+ pub fn new(
+ baud: u64,
+ pio: impl Peripheral + 'a,
+ tx_pin: impl PioPin,
+ rx_pin: impl PioPin,
+ ) -> PioUart<'a> {
+ let Pio {
+ mut common, sm0, sm1, ..
+ } = Pio::new(pio, Irqs);
+
+ let tx = PioUartTx::new(&mut common, sm0, tx_pin, baud);
+ let rx = PioUartRx::new(&mut common, sm1, rx_pin, baud);
+
+ PioUart { tx, rx }
+ }
+
+ pub fn split(self) -> (PioUartTx<'a>, PioUartRx<'a>) {
+ (self.tx, self.rx)
+ }
+ }
+}
+
+mod uart_tx {
+ use core::convert::Infallible;
+
+ use embassy_rp::gpio::Level;
+ use embassy_rp::peripherals::PIO0;
+ use embassy_rp::pio::{Common, Config, Direction, FifoJoin, PioPin, ShiftDirection, StateMachine};
+ use embedded_io::asynch::Write;
+ use embedded_io::Io;
+ use fixed::traits::ToFixed;
+ use fixed_macro::types::U56F8;
+
+ pub struct PioUartTx<'a> {
+ sm_tx: StateMachine<'a, PIO0, 0>,
+ }
+
+ impl<'a> PioUartTx<'a> {
+ pub fn new(
+ common: &mut Common<'a, PIO0>,
+ mut sm_tx: StateMachine<'a, PIO0, 0>,
+ tx_pin: impl PioPin,
+ baud: u64,
+ ) -> Self {
+ let prg = pio_proc::pio_asm!(
+ r#"
+ .side_set 1 opt
+
+ ; An 8n1 UART transmit program.
+ ; OUT pin 0 and side-set pin 0 are both mapped to UART TX pin.
+
+ pull side 1 [7] ; Assert stop bit, or stall with line in idle state
+ set x, 7 side 0 [7] ; Preload bit counter, assert start bit for 8 clocks
+ bitloop: ; This loop will run 8 times (8n1 UART)
+ out pins, 1 ; Shift 1 bit from OSR to the first OUT pin
+ jmp x-- bitloop [6] ; Each loop iteration is 8 cycles.
+ "#
+ );
+ let tx_pin = common.make_pio_pin(tx_pin);
+ sm_tx.set_pins(Level::High, &[&tx_pin]);
+ sm_tx.set_pin_dirs(Direction::Out, &[&tx_pin]);
+
+ let mut cfg = Config::default();
+
+ cfg.set_out_pins(&[&tx_pin]);
+ cfg.use_program(&common.load_program(&prg.program), &[&tx_pin]);
+ cfg.shift_out.auto_fill = false;
+ cfg.shift_out.direction = ShiftDirection::Right;
+ cfg.fifo_join = FifoJoin::TxOnly;
+ cfg.clock_divider = (U56F8!(125_000_000) / (8 * baud)).to_fixed();
+ sm_tx.set_config(&cfg);
+ sm_tx.set_enable(true);
+
+ Self { sm_tx }
+ }
+
+ pub async fn write_u8(&mut self, data: u8) {
+ self.sm_tx.tx().wait_push(data as u32).await;
+ }
+ }
+
+ impl Io for PioUartTx<'_> {
+ type Error = Infallible;
+ }
+
+ impl Write for PioUartTx<'_> {
+ async fn write(&mut self, buf: &[u8]) -> Result {
+ for byte in buf {
+ self.write_u8(*byte).await;
+ }
+ Ok(buf.len())
+ }
+ }
+}
+
+mod uart_rx {
+ use core::convert::Infallible;
+
+ use embassy_rp::gpio::Level;
+ use embassy_rp::peripherals::PIO0;
+ use embassy_rp::pio::{Common, Config, Direction, FifoJoin, PioPin, ShiftDirection, StateMachine};
+ use embedded_io::asynch::Read;
+ use embedded_io::Io;
+ use fixed::traits::ToFixed;
+ use fixed_macro::types::U56F8;
+
+ pub struct PioUartRx<'a> {
+ sm_rx: StateMachine<'a, PIO0, 1>,
+ }
+
+ impl<'a> PioUartRx<'a> {
+ pub fn new(
+ common: &mut Common<'a, PIO0>,
+ mut sm_rx: StateMachine<'a, PIO0, 1>,
+ rx_pin: impl PioPin,
+ baud: u64,
+ ) -> Self {
+ let prg = pio_proc::pio_asm!(
+ r#"
+ ; Slightly more fleshed-out 8n1 UART receiver which handles framing errors and
+ ; break conditions more gracefully.
+ ; IN pin 0 and JMP pin are both mapped to the GPIO used as UART RX.
+
+ start:
+ wait 0 pin 0 ; Stall until start bit is asserted
+ set x, 7 [10] ; Preload bit counter, then delay until halfway through
+ rx_bitloop: ; the first data bit (12 cycles incl wait, set).
+ in pins, 1 ; Shift data bit into ISR
+ jmp x-- rx_bitloop [6] ; Loop 8 times, each loop iteration is 8 cycles
+ jmp pin good_rx_stop ; Check stop bit (should be high)
+
+ irq 4 rel ; Either a framing error or a break. Set a sticky flag,
+ wait 1 pin 0 ; and wait for line to return to idle state.
+ jmp start ; Don't push data if we didn't see good framing.
+
+ good_rx_stop: ; No delay before returning to start; a little slack is
+ push ; important in case the TX clock is slightly too fast.
+ "#
+ );
+ let mut cfg = Config::default();
+ cfg.use_program(&common.load_program(&prg.program), &[]);
+
+ let rx_pin = common.make_pio_pin(rx_pin);
+ sm_rx.set_pins(Level::High, &[&rx_pin]);
+ cfg.set_in_pins(&[&rx_pin]);
+ cfg.set_jmp_pin(&rx_pin);
+ sm_rx.set_pin_dirs(Direction::In, &[&rx_pin]);
+
+ cfg.clock_divider = (U56F8!(125_000_000) / (8 * baud)).to_fixed();
+ cfg.shift_out.auto_fill = false;
+ cfg.shift_out.direction = ShiftDirection::Right;
+ cfg.fifo_join = FifoJoin::RxOnly;
+ sm_rx.set_config(&cfg);
+ sm_rx.set_enable(true);
+
+ Self { sm_rx }
+ }
+
+ pub async fn read_u8(&mut self) -> u8 {
+ self.sm_rx.rx().wait_pull().await as u8
+ }
+ }
+
+ impl Io for PioUartRx<'_> {
+ type Error = Infallible;
+ }
+
+ impl Read for PioUartRx<'_> {
+ async fn read(&mut self, buf: &mut [u8]) -> Result {
+ let mut i = 0;
+ while i < buf.len() {
+ buf[i] = self.read_u8().await;
+ i += 1;
+ }
+ Ok(i)
+ }
+ }
+}
diff --git a/examples/rp/src/bin/pio_ws2812.rs b/examples/rp/src/bin/pio_ws2812.rs
index 3de2bd48d..bc87016ec 100644
--- a/examples/rp/src/bin/pio_ws2812.rs
+++ b/examples/rp/src/bin/pio_ws2812.rs
@@ -12,7 +12,6 @@ use embassy_rp::peripherals::PIO0;
use embassy_rp::pio::{
Common, Config, FifoJoin, Instance, InterruptHandler, Pio, PioPin, ShiftConfig, ShiftDirection, StateMachine,
};
-use embassy_rp::relocate::RelocatedProgram;
use embassy_rp::{bind_interrupts, clocks, into_ref, Peripheral, PeripheralRef};
use embassy_time::{Duration, Timer};
use fixed::types::U24F8;
@@ -73,8 +72,7 @@ impl<'d, P: Instance, const S: usize, const N: usize> Ws2812<'d, P, S, N> {
cfg.set_out_pins(&[&out_pin]);
cfg.set_set_pins(&[&out_pin]);
- let relocated = RelocatedProgram::new(&prg);
- cfg.use_program(&pio.load_program(&relocated), &[&out_pin]);
+ cfg.use_program(&pio.load_program(&prg), &[&out_pin]);
// Clock config, measured in kHz to avoid overflows
// TODO CLOCK_FREQ should come from embassy_rp
diff --git a/examples/std/Cargo.toml b/examples/std/Cargo.toml
index 92933ab50..42adede10 100644
--- a/examples/std/Cargo.toml
+++ b/examples/std/Cargo.toml
@@ -23,3 +23,6 @@ clap = { version = "3.0.0-beta.5", features = ["derive"] }
rand_core = { version = "0.6.3", features = ["std"] }
heapless = { version = "0.7.5", default-features = false }
static_cell = { version = "1.1", features = ["nightly"]}
+
+[profile.release]
+debug = 2
diff --git a/examples/stm32c0/Cargo.toml b/examples/stm32c0/Cargo.toml
index 26837abef..8534921ab 100644
--- a/examples/stm32c0/Cargo.toml
+++ b/examples/stm32c0/Cargo.toml
@@ -5,10 +5,11 @@ version = "0.1.0"
license = "MIT OR Apache-2.0"
[dependencies]
+# Change stm32c031c6 to your chip name, if necessary.
+embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "time-driver-any", "stm32c031c6", "memory-x", "unstable-pac", "exti"] }
embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] }
embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] }
embassy-time = { version = "0.1.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
-embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "time-driver-any", "stm32c031c6", "memory-x", "unstable-pac", "exti"] }
defmt = "0.3"
defmt-rtt = "0.4"
@@ -19,3 +20,6 @@ embedded-hal = "0.2.6"
panic-probe = { version = "0.3", features = ["print-defmt"] }
futures = { version = "0.3.17", default-features = false, features = ["async-await"] }
heapless = { version = "0.7.5", default-features = false }
+
+[profile.release]
+debug = 2
diff --git a/examples/stm32f0/Cargo.toml b/examples/stm32f0/Cargo.toml
index b7b5eaa99..46b6db45c 100644
--- a/examples/stm32f0/Cargo.toml
+++ b/examples/stm32f0/Cargo.toml
@@ -7,6 +7,8 @@ license = "MIT OR Apache-2.0"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
+# Change stm32f091rc to your chip name, if necessary.
+embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "memory-x", "stm32f091rc", "time-driver-any", "exti", "unstable-pac"] }
cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
cortex-m-rt = "0.7.0"
defmt = "0.3"
@@ -15,5 +17,7 @@ panic-probe = "0.3"
embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] }
embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] }
embassy-time = { version = "0.1.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
-embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "memory-x", "stm32f091rc", "time-driver-any", "exti", "unstable-pac"] }
static_cell = { version = "1.1", features = ["nightly"]}
+
+[profile.release]
+debug = 2
diff --git a/examples/stm32f1/Cargo.toml b/examples/stm32f1/Cargo.toml
index 29cad5b67..5d32992cd 100644
--- a/examples/stm32f1/Cargo.toml
+++ b/examples/stm32f1/Cargo.toml
@@ -5,10 +5,11 @@ version = "0.1.0"
license = "MIT OR Apache-2.0"
[dependencies]
+# Change stm32f103c8 to your chip name, if necessary.
+embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32f103c8", "unstable-pac", "memory-x", "time-driver-any", "unstable-traits" ] }
embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] }
embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] }
embassy-time = { version = "0.1.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
-embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32f103c8", "unstable-pac", "memory-x", "time-driver-any", "unstable-traits" ] }
embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] }
embassy-futures = { version = "0.1.0", path = "../../embassy-futures" }
@@ -25,3 +26,6 @@ nb = "1.0.0"
[profile.dev]
opt-level = "s"
+
+[profile.release]
+debug = 2
diff --git a/examples/stm32f2/Cargo.toml b/examples/stm32f2/Cargo.toml
index 652210c7f..9857fb631 100644
--- a/examples/stm32f2/Cargo.toml
+++ b/examples/stm32f2/Cargo.toml
@@ -5,10 +5,11 @@ version = "0.1.0"
license = "MIT OR Apache-2.0"
[dependencies]
+# Change stm32f207zg to your chip name, if necessary.
+embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32f207zg", "unstable-pac", "memory-x", "time-driver-any", "exti"] }
embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] }
embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] }
embassy-time = { version = "0.1.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
-embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32f207zg", "unstable-pac", "memory-x", "time-driver-any", "exti"] }
defmt = "0.3"
defmt-rtt = "0.4"
@@ -20,3 +21,6 @@ panic-probe = { version = "0.3", features = ["print-defmt"] }
futures = { version = "0.3.17", default-features = false, features = ["async-await"] }
heapless = { version = "0.7.5", default-features = false }
nb = "1.0.0"
+
+[profile.release]
+debug = 2
diff --git a/examples/stm32f3/Cargo.toml b/examples/stm32f3/Cargo.toml
index 489d0ff4c..bd594d16a 100644
--- a/examples/stm32f3/Cargo.toml
+++ b/examples/stm32f3/Cargo.toml
@@ -5,10 +5,11 @@ version = "0.1.0"
license = "MIT OR Apache-2.0"
[dependencies]
+# Change stm32f303ze to your chip name, if necessary.
+embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32f303ze", "unstable-pac", "memory-x", "time-driver-any", "exti"] }
embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] }
embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] }
embassy-time = { version = "0.1.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
-embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32f303ze", "unstable-pac", "memory-x", "time-driver-any", "exti"] }
embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] }
embassy-futures = { version = "0.1.0", path = "../../embassy-futures" }
@@ -24,3 +25,6 @@ heapless = { version = "0.7.5", default-features = false }
nb = "1.0.0"
embedded-storage = "0.3.0"
static_cell = { version = "1.1", features = ["nightly"]}
+
+[profile.release]
+debug = 2
diff --git a/examples/stm32f4/Cargo.toml b/examples/stm32f4/Cargo.toml
index c1c821364..fdd3b7d4f 100644
--- a/examples/stm32f4/Cargo.toml
+++ b/examples/stm32f4/Cargo.toml
@@ -5,10 +5,11 @@ version = "0.1.0"
license = "MIT OR Apache-2.0"
[dependencies]
-embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] }
-embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers", "arch-cortex-m", "executor-thread", "executor-interrupt"] }
-embassy-time = { version = "0.1.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "unstable-traits", "tick-hz-32_768"] }
+# Change stm32f429zi to your chip name, if necessary.
embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "unstable-traits", "defmt", "stm32f429zi", "unstable-pac", "memory-x", "time-driver-any", "exti", "embedded-sdmmc", "chrono"] }
+embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] }
+embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] }
+embassy-time = { version = "0.1.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "unstable-traits", "tick-hz-32_768"] }
embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] }
embassy-net = { version = "0.1.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "nightly"] }
diff --git a/examples/stm32f4/src/bin/can.rs b/examples/stm32f4/src/bin/can.rs
index 08bed88db..f84f74d30 100644
--- a/examples/stm32f4/src/bin/can.rs
+++ b/examples/stm32f4/src/bin/can.rs
@@ -40,10 +40,13 @@ async fn main(_spawner: Spawner) {
can.as_mut()
.modify_config()
- .set_bit_timing(0x001c0003) // http://www.bittiming.can-wiki.info/
.set_loopback(true) // Receive own frames
.set_silent(true)
- .enable();
+ .leave_disabled();
+
+ can.set_bitrate(1_000_000);
+
+ can.enable().await;
let mut i: u8 = 0;
loop {
diff --git a/examples/stm32f4/src/bin/dac.rs b/examples/stm32f4/src/bin/dac.rs
index 3a6216712..aaedcfecc 100644
--- a/examples/stm32f4/src/bin/dac.rs
+++ b/examples/stm32f4/src/bin/dac.rs
@@ -14,11 +14,11 @@ async fn main(_spawner: Spawner) -> ! {
info!("Hello World, dude!");
let mut dac = DacCh1::new(p.DAC, NoDma, p.PA4);
+ unwrap!(dac.set_trigger_enable(false));
loop {
for v in 0..=255 {
unwrap!(dac.set(Value::Bit8(to_sine_wave(v))));
- dac.trigger();
}
}
}
diff --git a/examples/stm32f4/src/bin/pwm.rs b/examples/stm32f4/src/bin/pwm.rs
index 7c5902052..4f130c26b 100644
--- a/examples/stm32f4/src/bin/pwm.rs
+++ b/examples/stm32f4/src/bin/pwm.rs
@@ -4,9 +4,9 @@
use defmt::*;
use embassy_executor::Spawner;
-use embassy_stm32::pwm::simple_pwm::{PwmPin, SimplePwm};
-use embassy_stm32::pwm::Channel;
use embassy_stm32::time::khz;
+use embassy_stm32::timer::simple_pwm::{PwmPin, SimplePwm};
+use embassy_stm32::timer::Channel;
use embassy_time::{Duration, Timer};
use {defmt_rtt as _, panic_probe as _};
diff --git a/examples/stm32f4/src/bin/pwm_complementary.rs b/examples/stm32f4/src/bin/pwm_complementary.rs
index a8a68ed6e..8cc2a4117 100644
--- a/examples/stm32f4/src/bin/pwm_complementary.rs
+++ b/examples/stm32f4/src/bin/pwm_complementary.rs
@@ -4,10 +4,10 @@
use defmt::*;
use embassy_executor::Spawner;
-use embassy_stm32::pwm::complementary_pwm::{ComplementaryPwm, ComplementaryPwmPin};
-use embassy_stm32::pwm::simple_pwm::PwmPin;
-use embassy_stm32::pwm::Channel;
use embassy_stm32::time::khz;
+use embassy_stm32::timer::complementary_pwm::{ComplementaryPwm, ComplementaryPwmPin};
+use embassy_stm32::timer::simple_pwm::PwmPin;
+use embassy_stm32::timer::Channel;
use embassy_time::{Duration, Timer};
use {defmt_rtt as _, panic_probe as _};
diff --git a/examples/stm32f7/Cargo.toml b/examples/stm32f7/Cargo.toml
index 84d7b79c5..a379cbbe3 100644
--- a/examples/stm32f7/Cargo.toml
+++ b/examples/stm32f7/Cargo.toml
@@ -5,10 +5,11 @@ version = "0.1.0"
license = "MIT OR Apache-2.0"
[dependencies]
+# Change stm32f767zi to your chip name, if necessary.
+embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32f767zi", "memory-x", "unstable-pac", "time-driver-any", "exti"] }
embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] }
embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] }
embassy-time = { version = "0.1.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
-embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32f767zi", "unstable-pac", "time-driver-any", "exti"] }
embassy-net = { path = "../../embassy-net", features = ["defmt", "nightly", "tcp", "dhcpv4", "medium-ethernet"] }
embedded-io = { version = "0.4.0", features = ["async"] }
embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] }
@@ -27,3 +28,6 @@ rand_core = "0.6.3"
critical-section = "1.1"
embedded-storage = "0.3.0"
static_cell = { version = "1.1", features = ["nightly"]}
+
+[profile.release]
+debug = 2
diff --git a/examples/stm32f7/build.rs b/examples/stm32f7/build.rs
index 2b5d412a9..8cd32d7ed 100644
--- a/examples/stm32f7/build.rs
+++ b/examples/stm32f7/build.rs
@@ -1,43 +1,5 @@
-//! adapted from https://github.com/stm32-rs/stm32f7xx-hal/blob/master/build.rs
-use std::fs::File;
-use std::io::prelude::*;
-use std::path::PathBuf;
-use std::{env, io};
-
-#[derive(Debug)]
-enum Error {
- Env(env::VarError),
- Io(io::Error),
-}
-
-impl From for Error {
- fn from(error: env::VarError) -> Self {
- Self::Env(error)
- }
-}
-
-impl From for Error {
- fn from(error: io::Error) -> Self {
- Self::Io(error)
- }
-}
-
-fn main() -> Result<(), Error> {
- println!("cargo:rerun-if-changed=build.rs");
- println!("cargo:rerun-if-changed=memory.x");
-
- let out_dir = env::var("OUT_DIR")?;
- let out_dir = PathBuf::from(out_dir);
-
- let memory_x = include_bytes!("memory.x").as_ref();
- File::create(out_dir.join("memory.x"))?.write_all(memory_x)?;
-
- // Tell Cargo where to find the file.
- println!("cargo:rustc-link-search={}", out_dir.display());
-
+fn main() {
println!("cargo:rustc-link-arg-bins=--nmagic");
println!("cargo:rustc-link-arg-bins=-Tlink.x");
println!("cargo:rustc-link-arg-bins=-Tdefmt.x");
-
- Ok(())
}
diff --git a/examples/stm32f7/memory.x b/examples/stm32f7/memory.x
deleted file mode 100644
index 899f7a4b8..000000000
--- a/examples/stm32f7/memory.x
+++ /dev/null
@@ -1,12 +0,0 @@
-/* For STM32F765,767,768,769,777,778,779 devices */
-MEMORY
-{
- /* NOTE K = KiBi = 1024 bytes */
- FLASH : ORIGIN = 0x08000000, LENGTH = 2M
- RAM : ORIGIN = 0x20000000, LENGTH = 368K + 16K
-}
-
-/* This is where the call stack will be allocated. */
-/* The stack is of the full descending type. */
-/* NOTE Do NOT modify `_stack_start` unless you know what you are doing */
-_stack_start = ORIGIN(RAM) + LENGTH(RAM);
diff --git a/examples/stm32g0/Cargo.toml b/examples/stm32g0/Cargo.toml
index c88282d91..b4dfe3c6b 100644
--- a/examples/stm32g0/Cargo.toml
+++ b/examples/stm32g0/Cargo.toml
@@ -5,10 +5,11 @@ version = "0.1.0"
license = "MIT OR Apache-2.0"
[dependencies]
+# Change stm32g071rb to your chip name, if necessary.
+embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "time-driver-any", "stm32g071rb", "memory-x", "unstable-pac", "exti"] }
embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] }
embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] }
embassy-time = { version = "0.1.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
-embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "time-driver-any", "stm32g071rb", "memory-x", "unstable-pac", "exti"] }
defmt = "0.3"
defmt-rtt = "0.4"
@@ -19,3 +20,6 @@ embedded-hal = "0.2.6"
panic-probe = { version = "0.3", features = ["print-defmt"] }
futures = { version = "0.3.17", default-features = false, features = ["async-await"] }
heapless = { version = "0.7.5", default-features = false }
+
+[profile.release]
+debug = 2
diff --git a/examples/stm32g4/Cargo.toml b/examples/stm32g4/Cargo.toml
index 18bd03c39..cf3e2ce9b 100644
--- a/examples/stm32g4/Cargo.toml
+++ b/examples/stm32g4/Cargo.toml
@@ -5,11 +5,11 @@ version = "0.1.0"
license = "MIT OR Apache-2.0"
[dependencies]
+# Change stm32g491re to your chip name, if necessary.
+embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "time-driver-any", "stm32g491re", "memory-x", "unstable-pac", "exti"] }
embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] }
embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] }
embassy-time = { version = "0.1.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
-embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "time-driver-any", "stm32g491re", "memory-x", "unstable-pac", "exti"] }
-embassy-hal-common = {version = "0.1.0", path = "../../embassy-hal-common" }
embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] }
defmt = "0.3"
@@ -21,3 +21,6 @@ embedded-hal = "0.2.6"
panic-probe = { version = "0.3", features = ["print-defmt"] }
futures = { version = "0.3.17", default-features = false, features = ["async-await"] }
heapless = { version = "0.7.5", default-features = false }
+
+[profile.release]
+debug = 2
diff --git a/examples/stm32g4/src/bin/pwm.rs b/examples/stm32g4/src/bin/pwm.rs
index 8f7842ed7..b5a9b9952 100644
--- a/examples/stm32g4/src/bin/pwm.rs
+++ b/examples/stm32g4/src/bin/pwm.rs
@@ -4,9 +4,9 @@
use defmt::*;
use embassy_executor::Spawner;
-use embassy_stm32::pwm::simple_pwm::{PwmPin, SimplePwm};
-use embassy_stm32::pwm::Channel;
use embassy_stm32::time::khz;
+use embassy_stm32::timer::simple_pwm::{PwmPin, SimplePwm};
+use embassy_stm32::timer::Channel;
use embassy_time::{Duration, Timer};
use {defmt_rtt as _, panic_probe as _};
diff --git a/examples/stm32h5/Cargo.toml b/examples/stm32h5/Cargo.toml
index 227bc28b4..51d3bad1f 100644
--- a/examples/stm32h5/Cargo.toml
+++ b/examples/stm32h5/Cargo.toml
@@ -5,10 +5,11 @@ version = "0.1.0"
license = "MIT OR Apache-2.0"
[dependencies]
+# Change stm32h563zi to your chip name, if necessary.
+embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32h563zi", "memory-x", "time-driver-any", "exti", "unstable-pac", "unstable-traits"] }
embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] }
embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] }
embassy-time = { version = "0.1.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "unstable-traits", "tick-hz-32_768"] }
-embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32h563zi", "time-driver-any", "exti", "unstable-pac", "unstable-traits"] }
embassy-net = { path = "../../embassy-net", features = ["defmt", "nightly", "tcp", "dhcpv4", "medium-ethernet", "unstable-traits", "proto-ipv6"] }
embedded-io = { version = "0.4.0", features = ["async"] }
embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] }
diff --git a/examples/stm32h5/memory.x b/examples/stm32h5/memory.x
deleted file mode 100644
index 456061509..000000000
--- a/examples/stm32h5/memory.x
+++ /dev/null
@@ -1,5 +0,0 @@
-MEMORY
-{
- FLASH : ORIGIN = 0x08000000, LENGTH = 0x200000
- RAM : ORIGIN = 0x20000000, LENGTH = 0x50000
-}
diff --git a/examples/stm32h7/.cargo/config.toml b/examples/stm32h7/.cargo/config.toml
index 5f680dbce..4160bf855 100644
--- a/examples/stm32h7/.cargo/config.toml
+++ b/examples/stm32h7/.cargo/config.toml
@@ -1,5 +1,5 @@
[target.thumbv7em-none-eabihf]
-runner = 'probe-rs run --chip STM32H743ZITx'
+runner = 'probe-rs run --chip STM32H7A3ZITxQ'
[build]
target = "thumbv7em-none-eabihf" # Cortex-M4F and Cortex-M7F (with FPU)
diff --git a/examples/stm32h7/Cargo.toml b/examples/stm32h7/Cargo.toml
index 768702fa9..3c1232e67 100644
--- a/examples/stm32h7/Cargo.toml
+++ b/examples/stm32h7/Cargo.toml
@@ -5,10 +5,11 @@ version = "0.1.0"
license = "MIT OR Apache-2.0"
[dependencies]
+# Change stm32h743bi to your chip name, if necessary.
+embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32h743bi", "time-driver-any", "exti", "memory-x", "unstable-pac", "unstable-traits"] }
embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] }
embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] }
embassy-time = { version = "0.1.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "unstable-traits", "tick-hz-32_768"] }
-embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32h743bi", "time-driver-any", "exti", "unstable-pac", "unstable-traits"] }
embassy-net = { path = "../../embassy-net", features = ["defmt", "nightly", "tcp", "dhcpv4", "medium-ethernet", "unstable-traits", "proto-ipv6"] }
embedded-io = { version = "0.4.0", features = ["async"] }
embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] }
diff --git a/examples/stm32h7/memory.x b/examples/stm32h7/memory.x
deleted file mode 100644
index 026b14b9b..000000000
--- a/examples/stm32h7/memory.x
+++ /dev/null
@@ -1,5 +0,0 @@
-MEMORY
-{
- FLASH : ORIGIN = 0x8000000, LENGTH = 1024K
- RAM : ORIGIN = 0x24000000, LENGTH = 384K
-}
diff --git a/examples/stm32h7/src/bin/dac.rs b/examples/stm32h7/src/bin/dac.rs
index 586b4154b..ee078286b 100644
--- a/examples/stm32h7/src/bin/dac.rs
+++ b/examples/stm32h7/src/bin/dac.rs
@@ -21,11 +21,11 @@ fn main() -> ! {
let p = embassy_stm32::init(config);
let mut dac = DacCh1::new(p.DAC1, NoDma, p.PA4);
+ unwrap!(dac.set_trigger_enable(false));
loop {
for v in 0..=255 {
unwrap!(dac.set(Value::Bit8(to_sine_wave(v))));
- dac.trigger();
}
}
}
diff --git a/examples/stm32h7/src/bin/dac_dma.rs b/examples/stm32h7/src/bin/dac_dma.rs
new file mode 100644
index 000000000..a9cb5d1ed
--- /dev/null
+++ b/examples/stm32h7/src/bin/dac_dma.rs
@@ -0,0 +1,140 @@
+#![no_std]
+#![no_main]
+#![feature(type_alias_impl_trait)]
+
+use defmt::*;
+use embassy_executor::Spawner;
+use embassy_stm32::dac::{DacChannel, ValueArray};
+use embassy_stm32::pac::timer::vals::{Mms, Opm};
+use embassy_stm32::peripherals::{TIM6, TIM7};
+use embassy_stm32::rcc::low_level::RccPeripheral;
+use embassy_stm32::time::{mhz, Hertz};
+use embassy_stm32::timer::low_level::Basic16bitInstance;
+use micromath::F32Ext;
+use {defmt_rtt as _, panic_probe as _};
+
+pub type Dac1Type =
+ embassy_stm32::dac::DacCh1<'static, embassy_stm32::peripherals::DAC1, embassy_stm32::peripherals::DMA1_CH3>;
+
+pub type Dac2Type =
+ embassy_stm32::dac::DacCh2<'static, embassy_stm32::peripherals::DAC1, embassy_stm32::peripherals::DMA1_CH4>;
+
+#[embassy_executor::main]
+async fn main(spawner: Spawner) {
+ let mut config = embassy_stm32::Config::default();
+ config.rcc.sys_ck = Some(mhz(400));
+ config.rcc.hclk = Some(mhz(100));
+ config.rcc.pll1.q_ck = Some(mhz(100));
+
+ // Initialize the board and obtain a Peripherals instance
+ let p: embassy_stm32::Peripherals = embassy_stm32::init(config);
+
+ // Obtain two independent channels (p.DAC1 can only be consumed once, though!)
+ let (dac_ch1, dac_ch2) = embassy_stm32::dac::Dac::new(p.DAC1, p.DMA1_CH3, p.DMA1_CH4, p.PA4, p.PA5).split();
+
+ spawner.spawn(dac_task1(dac_ch1)).ok();
+ spawner.spawn(dac_task2(dac_ch2)).ok();
+}
+
+#[embassy_executor::task]
+async fn dac_task1(mut dac: Dac1Type) {
+ let data: &[u8; 256] = &calculate_array::<256>();
+
+ info!("TIM6 frequency is {}", TIM6::frequency());
+ const FREQUENCY: Hertz = Hertz::hz(200);
+
+ // Compute the reload value such that we obtain the FREQUENCY for the sine
+ let reload: u32 = (TIM6::frequency().0 / FREQUENCY.0) / data.len() as u32;
+
+ // Depends on your clock and on the specific chip used, you may need higher or lower values here
+ if reload < 10 {
+ error!("Reload value {} below threshold!", reload);
+ }
+
+ dac.select_trigger(embassy_stm32::dac::Ch1Trigger::Tim6).unwrap();
+ dac.enable_channel().unwrap();
+
+ TIM6::enable();
+ TIM6::regs().arr().modify(|w| w.set_arr(reload as u16 - 1));
+ TIM6::regs().cr2().modify(|w| w.set_mms(Mms::UPDATE));
+ TIM6::regs().cr1().modify(|w| {
+ w.set_opm(Opm::DISABLED);
+ w.set_cen(true);
+ });
+
+ debug!(
+ "TIM6 Frequency {}, Target Frequency {}, Reload {}, Reload as u16 {}, Samples {}",
+ TIM6::frequency(),
+ FREQUENCY,
+ reload,
+ reload as u16,
+ data.len()
+ );
+
+ // Loop technically not necessary if DMA circular mode is enabled
+ loop {
+ info!("Loop DAC1");
+ if let Err(e) = dac.write(ValueArray::Bit8(data), true).await {
+ error!("Could not write to dac: {}", e);
+ }
+ }
+}
+
+#[embassy_executor::task]
+async fn dac_task2(mut dac: Dac2Type) {
+ let data: &[u8; 256] = &calculate_array::<256>();
+
+ info!("TIM7 frequency is {}", TIM7::frequency());
+
+ const FREQUENCY: Hertz = Hertz::hz(600);
+ let reload: u32 = (TIM7::frequency().0 / FREQUENCY.0) / data.len() as u32;
+
+ if reload < 10 {
+ error!("Reload value {} below threshold!", reload);
+ }
+
+ TIM7::enable();
+ TIM7::regs().arr().modify(|w| w.set_arr(reload as u16 - 1));
+ TIM7::regs().cr2().modify(|w| w.set_mms(Mms::UPDATE));
+ TIM7::regs().cr1().modify(|w| {
+ w.set_opm(Opm::DISABLED);
+ w.set_cen(true);
+ });
+
+ dac.select_trigger(embassy_stm32::dac::Ch2Trigger::Tim7).unwrap();
+
+ debug!(
+ "TIM7 Frequency {}, Target Frequency {}, Reload {}, Reload as u16 {}, Samples {}",
+ TIM7::frequency(),
+ FREQUENCY,
+ reload,
+ reload as u16,
+ data.len()
+ );
+
+ if let Err(e) = dac.write(ValueArray::Bit8(data), true).await {
+ error!("Could not write to dac: {}", e);
+ }
+}
+
+fn to_sine_wave(v: u8) -> u8 {
+ if v >= 128 {
+ // top half
+ let r = 3.14 * ((v - 128) as f32 / 128.0);
+ (r.sin() * 128.0 + 127.0) as u8
+ } else {
+ // bottom half
+ let r = 3.14 + 3.14 * (v as f32 / 128.0);
+ (r.sin() * 128.0 + 127.0) as u8
+ }
+}
+
+fn calculate_array() -> [u8; N] {
+ let mut res = [0; N];
+ let mut i = 0;
+ while i < N {
+ res[i] = to_sine_wave(i as u8);
+ i += 1;
+ }
+ res
+}
diff --git a/examples/stm32h7/src/bin/low_level_timer_api.rs b/examples/stm32h7/src/bin/low_level_timer_api.rs
index d360df085..45b0872b5 100644
--- a/examples/stm32h7/src/bin/low_level_timer_api.rs
+++ b/examples/stm32h7/src/bin/low_level_timer_api.rs
@@ -6,8 +6,8 @@ use defmt::*;
use embassy_executor::Spawner;
use embassy_stm32::gpio::low_level::AFType;
use embassy_stm32::gpio::Speed;
-use embassy_stm32::pwm::*;
use embassy_stm32::time::{khz, mhz, Hertz};
+use embassy_stm32::timer::*;
use embassy_stm32::{into_ref, Config, Peripheral, PeripheralRef};
use embassy_time::{Duration, Timer};
use {defmt_rtt as _, panic_probe as _};
diff --git a/examples/stm32h7/src/bin/pwm.rs b/examples/stm32h7/src/bin/pwm.rs
index c5c0dd290..adf2ea9ce 100644
--- a/examples/stm32h7/src/bin/pwm.rs
+++ b/examples/stm32h7/src/bin/pwm.rs
@@ -4,9 +4,9 @@
use defmt::*;
use embassy_executor::Spawner;
-use embassy_stm32::pwm::simple_pwm::{PwmPin, SimplePwm};
-use embassy_stm32::pwm::Channel;
use embassy_stm32::time::{khz, mhz};
+use embassy_stm32::timer::simple_pwm::{PwmPin, SimplePwm};
+use embassy_stm32::timer::Channel;
use embassy_stm32::Config;
use embassy_time::{Duration, Timer};
use {defmt_rtt as _, panic_probe as _};
diff --git a/examples/stm32l0/Cargo.toml b/examples/stm32l0/Cargo.toml
index 747cec7bf..c325751c6 100644
--- a/examples/stm32l0/Cargo.toml
+++ b/examples/stm32l0/Cargo.toml
@@ -10,10 +10,11 @@ nightly = ["embassy-stm32/nightly", "embassy-time/nightly", "embassy-time/unstab
"embassy-lora", "lora-phy", "lorawan-device", "lorawan", "embedded-io/async"]
[dependencies]
+# Change stm32l072cz to your chip name, if necessary.
+embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["defmt", "stm32l072cz", "time-driver-any", "exti", "unstable-traits", "memory-x"] }
embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] }
embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] }
embassy-time = { version = "0.1.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
-embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["defmt", "stm32l072cz", "time-driver-any", "exti", "unstable-traits", "memory-x"] }
embassy-lora = { version = "0.1.0", path = "../../embassy-lora", features = ["time", "defmt"], optional = true }
lora-phy = { version = "1", optional = true }
lorawan-device = { version = "0.10.0", default-features = false, features = ["async", "external-lora-phy"], optional = true }
@@ -33,5 +34,5 @@ heapless = { version = "0.7.5", default-features = false }
embedded-hal = "0.2.6"
static_cell = "1.1"
-[patch.crates-io]
-lora-phy = { git = "https://github.com/embassy-rs/lora-phy", rev = "ad289428fd44b02788e2fa2116445cc8f640a265" }
+[profile.release]
+debug = 2
diff --git a/examples/stm32l1/Cargo.toml b/examples/stm32l1/Cargo.toml
index dcca1cc3d..329d44cac 100644
--- a/examples/stm32l1/Cargo.toml
+++ b/examples/stm32l1/Cargo.toml
@@ -20,3 +20,6 @@ panic-probe = { version = "0.3", features = ["print-defmt"] }
futures = { version = "0.3.17", default-features = false, features = ["async-await"] }
heapless = { version = "0.7.5", default-features = false }
embedded-storage = "0.3.0"
+
+[profile.release]
+debug = 2
diff --git a/examples/stm32l4/Cargo.toml b/examples/stm32l4/Cargo.toml
index c55558518..3b27d8e81 100644
--- a/examples/stm32l4/Cargo.toml
+++ b/examples/stm32l4/Cargo.toml
@@ -5,11 +5,12 @@ version = "0.1.0"
license = "MIT OR Apache-2.0"
[dependencies]
+# Change stm32l4s5vi to your chip name, if necessary.
+embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "unstable-pac", "stm32l4s5vi", "memory-x", "time-driver-any", "exti", "unstable-traits", "chrono"] }
embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] }
embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] }
embassy-time = { version = "0.1.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
embassy-embedded-hal = { version = "0.1.0", path = "../../embassy-embedded-hal" }
-embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "unstable-pac", "stm32l4s5vi", "time-driver-any", "exti", "unstable-traits", "chrono"] }
embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] }
defmt = "0.3"
@@ -26,3 +27,6 @@ heapless = { version = "0.7.5", default-features = false }
chrono = { version = "^0.4", default-features = false }
micromath = "2.0.0"
+
+[profile.release]
+debug = 2
diff --git a/examples/stm32l4/build.rs b/examples/stm32l4/build.rs
index 30691aa97..8cd32d7ed 100644
--- a/examples/stm32l4/build.rs
+++ b/examples/stm32l4/build.rs
@@ -1,34 +1,4 @@
-//! This build script copies the `memory.x` file from the crate root into
-//! a directory where the linker can always find it at build time.
-//! For many projects this is optional, as the linker always searches the
-//! project root directory -- wherever `Cargo.toml` is. However, if you
-//! are using a workspace or have a more complicated build setup, this
-//! build script becomes required. Additionally, by requesting that
-//! Cargo re-run the build script whenever `memory.x` is changed,
-//! updating `memory.x` ensures a rebuild of the application with the
-//! new memory settings.
-
-use std::env;
-use std::fs::File;
-use std::io::Write;
-use std::path::PathBuf;
-
fn main() {
- // Put `memory.x` in our output directory and ensure it's
- // on the linker search path.
- let out = &PathBuf::from(env::var_os("OUT_DIR").unwrap());
- File::create(out.join("memory.x"))
- .unwrap()
- .write_all(include_bytes!("memory.x"))
- .unwrap();
- println!("cargo:rustc-link-search={}", out.display());
-
- // By default, Cargo will re-run a build script whenever
- // any file in the project changes. By specifying `memory.x`
- // here, we ensure the build script is only re-run when
- // `memory.x` is changed.
- println!("cargo:rerun-if-changed=memory.x");
-
println!("cargo:rustc-link-arg-bins=--nmagic");
println!("cargo:rustc-link-arg-bins=-Tlink.x");
println!("cargo:rustc-link-arg-bins=-Tdefmt.x");
diff --git a/examples/stm32l4/memory.x b/examples/stm32l4/memory.x
deleted file mode 100644
index eb87d1b54..000000000
--- a/examples/stm32l4/memory.x
+++ /dev/null
@@ -1,7 +0,0 @@
-MEMORY
-{
- /* NOTE 1 K = 1 KiBi = 1024 bytes */
- /* These values correspond to the STM32L4S5 */
- FLASH : ORIGIN = 0x08000000, LENGTH = 1024K
- RAM : ORIGIN = 0x20000000, LENGTH = 128K
-}
diff --git a/examples/stm32l4/src/bin/dac.rs b/examples/stm32l4/src/bin/dac.rs
index ade43eb35..0193a248e 100644
--- a/examples/stm32l4/src/bin/dac.rs
+++ b/examples/stm32l4/src/bin/dac.rs
@@ -13,11 +13,11 @@ fn main() -> ! {
info!("Hello World!");
let mut dac = DacCh1::new(p.DAC1, NoDma, p.PA4);
+ unwrap!(dac.set_trigger_enable(false));
loop {
for v in 0..=255 {
unwrap!(dac.set(Value::Bit8(to_sine_wave(v))));
- dac.trigger();
}
}
}
diff --git a/examples/stm32l5/Cargo.toml b/examples/stm32l5/Cargo.toml
index 54911482e..1afd00398 100644
--- a/examples/stm32l5/Cargo.toml
+++ b/examples/stm32l5/Cargo.toml
@@ -5,10 +5,11 @@ version = "0.1.0"
license = "MIT OR Apache-2.0"
[dependencies]
+# Change stm32l552ze to your chip name, if necessary.
+embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "unstable-pac", "stm32l552ze", "time-driver-any", "exti", "unstable-traits", "memory-x"] }
embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] }
embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] }
embassy-time = { version = "0.1.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
-embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "unstable-pac", "stm32l552ze", "time-driver-any", "exti", "unstable-traits", "memory-x"] }
embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] }
embassy-net = { version = "0.1.0", path = "../../embassy-net", features = ["defmt", "nightly", "tcp", "dhcpv4", "medium-ethernet"] }
embassy-futures = { version = "0.1.0", path = "../../embassy-futures" }
@@ -26,3 +27,6 @@ heapless = { version = "0.7.5", default-features = false }
rand_core = { version = "0.6.3", default-features = false }
embedded-io = { version = "0.4.0", features = ["async"] }
static_cell = { version = "1.1", features = ["nightly"]}
+
+[profile.release]
+debug = 2
diff --git a/examples/stm32u5/Cargo.toml b/examples/stm32u5/Cargo.toml
index 835e32940..db251eafe 100644
--- a/examples/stm32u5/Cargo.toml
+++ b/examples/stm32u5/Cargo.toml
@@ -5,10 +5,11 @@ version = "0.1.0"
license = "MIT OR Apache-2.0"
[dependencies]
+# Change stm32u585ai to your chip name, if necessary.
+embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "unstable-pac", "stm32u585ai", "time-driver-any", "memory-x" ] }
embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] }
embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] }
embassy-time = { version = "0.1.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
-embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "unstable-pac", "stm32u585ai", "time-driver-any", "memory-x" ] }
embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] }
defmt = "0.3"
@@ -22,3 +23,6 @@ futures = { version = "0.3.17", default-features = false, features = ["async-awa
heapless = { version = "0.7.5", default-features = false }
micromath = "2.0.0"
+
+[profile.release]
+debug = 2
diff --git a/examples/stm32wb/Cargo.toml b/examples/stm32wb/Cargo.toml
index 7c0b83e65..1a5aff352 100644
--- a/examples/stm32wb/Cargo.toml
+++ b/examples/stm32wb/Cargo.toml
@@ -5,11 +5,12 @@ version = "0.1.0"
license = "MIT OR Apache-2.0"
[dependencies]
+# Change stm32wb55rg to your chip name in both dependencies, if necessary.
+embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32wb55rg", "time-driver-any", "memory-x", "exti"] }
+embassy-stm32-wpan = { version = "0.1.0", path = "../../embassy-stm32-wpan", features = ["defmt", "stm32wb55rg"] }
embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] }
embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] }
embassy-time = { version = "0.1.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
-embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32wb55rg", "time-driver-any", "memory-x", "exti"] }
-embassy-stm32-wpan = { version = "0.1.0", path = "../../embassy-stm32-wpan", features = ["defmt", "stm32wb55rg"] }
embassy-net = { version = "0.1.0", path = "../../embassy-net", features = ["defmt", "udp", "medium-ieee802154", "nightly"], optional=true }
defmt = "0.3"
@@ -50,4 +51,7 @@ required-features = ["ble"]
[[bin]]
name = "gatt_server"
-required-features = ["ble"]
\ No newline at end of file
+required-features = ["ble"]
+
+[profile.release]
+debug = 2
diff --git a/examples/stm32wl/Cargo.toml b/examples/stm32wl/Cargo.toml
index e2c66f456..48b69c8d0 100644
--- a/examples/stm32wl/Cargo.toml
+++ b/examples/stm32wl/Cargo.toml
@@ -5,10 +5,11 @@ version = "0.1.0"
license = "MIT OR Apache-2.0"
[dependencies]
+# Change stm32wl55jc-cm4 to your chip name, if necessary.
+embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "unstable-traits", "defmt", "stm32wl55jc-cm4", "time-driver-any", "memory-x", "unstable-pac", "exti", "chrono"] }
embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] }
embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] }
embassy-time = { version = "0.1.2", path = "../../embassy-time", features = ["nightly", "unstable-traits", "defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
-embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "unstable-traits", "defmt", "stm32wl55jc-cm4", "time-driver-any", "memory-x", "unstable-pac", "exti", "chrono"] }
embassy-embedded-hal = { version = "0.1.0", path = "../../embassy-embedded-hal" }
embassy-lora = { version = "0.1.0", path = "../../embassy-lora", features = ["stm32wl", "time", "defmt"] }
lora-phy = { version = "1" }
@@ -27,5 +28,5 @@ futures = { version = "0.3.17", default-features = false, features = ["async-awa
heapless = { version = "0.7.5", default-features = false }
chrono = { version = "^0.4", default-features = false }
-[patch.crates-io]
-lora-phy = { git = "https://github.com/embassy-rs/lora-phy", rev = "ad289428fd44b02788e2fa2116445cc8f640a265" }
+[profile.release]
+debug = 2
diff --git a/examples/wasm/Cargo.toml b/examples/wasm/Cargo.toml
index 3679e3857..2791cc341 100644
--- a/examples/wasm/Cargo.toml
+++ b/examples/wasm/Cargo.toml
@@ -17,3 +17,6 @@ wasm-bindgen = "0.2"
web-sys = { version = "0.3", features = ["Document", "Element", "HtmlElement", "Node", "Window" ] }
log = "0.4.11"
critical-section = { version = "1.1", features = ["std"] }
+
+[profile.release]
+debug = 2
diff --git a/tests/nrf/src/bin/wifi_esp_hosted_perf.rs b/tests/nrf/src/bin/wifi_esp_hosted_perf.rs
index 398ab9d27..e2adfe0be 100644
--- a/tests/nrf/src/bin/wifi_esp_hosted_perf.rs
+++ b/tests/nrf/src/bin/wifi_esp_hosted_perf.rs
@@ -118,9 +118,9 @@ const WIFI_NETWORK: &str = "EmbassyTest";
const WIFI_PASSWORD: &str = "V8YxhKt5CdIAJFud";
const TEST_DURATION: usize = 10;
-const TEST_EXPECTED_DOWNLOAD_KBPS: usize = 150;
-const TEST_EXPECTED_UPLOAD_KBPS: usize = 150;
-const TEST_EXPECTED_UPLOAD_DOWNLOAD_KBPS: usize = 150;
+const TEST_EXPECTED_DOWNLOAD_KBPS: usize = 50;
+const TEST_EXPECTED_UPLOAD_KBPS: usize = 50;
+const TEST_EXPECTED_UPLOAD_DOWNLOAD_KBPS: usize = 50;
const RX_BUFFER_SIZE: usize = 4096;
const TX_BUFFER_SIZE: usize = 4096;
const SERVER_ADDRESS: Ipv4Address = Ipv4Address::new(192, 168, 2, 2);
diff --git a/tests/rp/src/bin/cyw43-perf.rs b/tests/rp/src/bin/cyw43-perf.rs
index bc127e2e5..fffdabc9b 100644
--- a/tests/rp/src/bin/cyw43-perf.rs
+++ b/tests/rp/src/bin/cyw43-perf.rs
@@ -48,9 +48,9 @@ async fn main(spawner: Spawner) {
}
// cyw43 firmware needs to be flashed manually:
- // probe-rs download 43439A0.bin --format bin --chip RP2040 --base-address 0x101c0000
+ // probe-rs download 43439A0.bin --format bin --chip RP2040 --base-address 0x101b0000
// probe-rs download 43439A0_clm.bin --format bin --chip RP2040 --base-address 0x101f8000
- let fw = unsafe { core::slice::from_raw_parts(0x101c0000 as *const u8, 224190) };
+ let fw = unsafe { core::slice::from_raw_parts(0x101b0000 as *const u8, 230321) };
let clm = unsafe { core::slice::from_raw_parts(0x101f8000 as *const u8, 4752) };
let pwr = Output::new(p.PIN_23, Level::Low);
diff --git a/tests/rp/src/bin/pio_irq.rs b/tests/rp/src/bin/pio_irq.rs
index 45004424a..bdea63eaa 100644
--- a/tests/rp/src/bin/pio_irq.rs
+++ b/tests/rp/src/bin/pio_irq.rs
@@ -9,7 +9,6 @@ use embassy_executor::Spawner;
use embassy_rp::bind_interrupts;
use embassy_rp::peripherals::PIO0;
use embassy_rp::pio::{Config, InterruptHandler, Pio};
-use embassy_rp::relocate::RelocatedProgram;
use {defmt_rtt as _, panic_probe as _};
bind_interrupts!(struct Irqs {
@@ -35,9 +34,8 @@ async fn main(_spawner: Spawner) {
"irq wait 1",
);
- let relocated = RelocatedProgram::new(&prg.program);
let mut cfg = Config::default();
- cfg.use_program(&common.load_program(&relocated), &[]);
+ cfg.use_program(&common.load_program(&prg.program), &[]);
sm.set_config(&cfg);
sm.set_enable(true);
diff --git a/tests/rp/src/bin/pio_multi_load.rs b/tests/rp/src/bin/pio_multi_load.rs
new file mode 100644
index 000000000..356f16795
--- /dev/null
+++ b/tests/rp/src/bin/pio_multi_load.rs
@@ -0,0 +1,126 @@
+#![no_std]
+#![no_main]
+#![feature(type_alias_impl_trait)]
+#[path = "../common.rs"]
+mod common;
+
+use defmt::info;
+use embassy_executor::Spawner;
+use embassy_rp::bind_interrupts;
+use embassy_rp::peripherals::PIO0;
+use embassy_rp::pio::{Config, InterruptHandler, LoadError, Pio};
+use {defmt_rtt as _, panic_probe as _};
+
+bind_interrupts!(struct Irqs {
+ PIO0_IRQ_0 => InterruptHandler;
+});
+
+#[embassy_executor::main]
+async fn main(_spawner: Spawner) {
+ let p = embassy_rp::init(Default::default());
+ let pio = p.PIO0;
+ let Pio {
+ mut common,
+ mut sm0,
+ mut sm1,
+ mut sm2,
+ irq_flags,
+ ..
+ } = Pio::new(pio, Irqs);
+
+ // load with explicit origin works
+ let prg1 = pio_proc::pio_asm!(
+ ".origin 4"
+ "nop",
+ "nop",
+ "nop",
+ "nop",
+ "nop",
+ "nop",
+ "nop",
+ "irq 0",
+ "nop",
+ "nop",
+ );
+ let loaded1 = common.load_program(&prg1.program);
+ assert_eq!(loaded1.origin, 4);
+ assert_eq!(loaded1.wrap.source, 13);
+ assert_eq!(loaded1.wrap.target, 4);
+
+ // load without origin chooses a free space
+ let prg2 = pio_proc::pio_asm!("nop", "nop", "nop", "nop", "nop", "nop", "nop", "irq 1", "nop", "nop",);
+ let loaded2 = common.load_program(&prg2.program);
+ assert_eq!(loaded2.origin, 14);
+ assert_eq!(loaded2.wrap.source, 23);
+ assert_eq!(loaded2.wrap.target, 14);
+
+ // wrapping around the end of program space automatically works
+ let prg3 =
+ pio_proc::pio_asm!("nop", "nop", "nop", "nop", "nop", "nop", "nop", "nop", "nop", "nop", "nop", "irq 2",);
+ let loaded3 = common.load_program(&prg3.program);
+ assert_eq!(loaded3.origin, 24);
+ assert_eq!(loaded3.wrap.source, 3);
+ assert_eq!(loaded3.wrap.target, 24);
+
+ // check that the programs actually work
+ {
+ let mut cfg = Config::default();
+ cfg.use_program(&loaded1, &[]);
+ sm0.set_config(&cfg);
+ sm0.set_enable(true);
+ while !irq_flags.check(0) {}
+ sm0.set_enable(false);
+ }
+ {
+ let mut cfg = Config::default();
+ cfg.use_program(&loaded2, &[]);
+ sm1.set_config(&cfg);
+ sm1.set_enable(true);
+ while !irq_flags.check(1) {}
+ sm1.set_enable(false);
+ }
+ {
+ let mut cfg = Config::default();
+ cfg.use_program(&loaded3, &[]);
+ sm2.set_config(&cfg);
+ sm2.set_enable(true);
+ while !irq_flags.check(2) {}
+ sm2.set_enable(false);
+ }
+
+ // instruction memory is full now. all loads should fail.
+ {
+ let prg = pio_proc::pio_asm!(".origin 0", "nop");
+ match common.try_load_program(&prg.program) {
+ Err(LoadError::AddressInUse(0)) => (),
+ _ => panic!("program loaded when it shouldn't"),
+ };
+
+ let prg = pio_proc::pio_asm!("nop");
+ match common.try_load_program(&prg.program) {
+ Err(LoadError::InsufficientSpace) => (),
+ _ => panic!("program loaded when it shouldn't"),
+ };
+ }
+
+ // freeing some memory should allow further loads though.
+ unsafe {
+ common.free_instr(loaded3.used_memory);
+ }
+ {
+ let prg = pio_proc::pio_asm!(".origin 0", "nop");
+ match common.try_load_program(&prg.program) {
+ Ok(_) => (),
+ _ => panic!("program didn't loaded when it shouldn"),
+ };
+
+ let prg = pio_proc::pio_asm!("nop");
+ match common.try_load_program(&prg.program) {
+ Ok(_) => (),
+ _ => panic!("program didn't loaded when it shouldn"),
+ };
+ }
+
+ info!("Test OK");
+ cortex_m::asm::bkpt();
+}
diff --git a/tests/stm32/Cargo.toml b/tests/stm32/Cargo.toml
index 3007cd1e6..17320649e 100644
--- a/tests/stm32/Cargo.toml
+++ b/tests/stm32/Cargo.toml
@@ -7,11 +7,11 @@ autobins = false
[features]
stm32f103c8 = ["embassy-stm32/stm32f103c8", "not-gpdma"] # Blue Pill
-stm32f429zi = ["embassy-stm32/stm32f429zi", "chrono", "can", "not-gpdma"] # Nucleo "sdmmc"
-stm32g071rb = ["embassy-stm32/stm32g071rb", "not-gpdma"] # Nucleo
+stm32f429zi = ["embassy-stm32/stm32f429zi", "chrono", "can", "not-gpdma", "dac-adc-pin"] # Nucleo "sdmmc"
+stm32g071rb = ["embassy-stm32/stm32g071rb", "not-gpdma", "dac-adc-pin"] # Nucleo
stm32c031c6 = ["embassy-stm32/stm32c031c6", "not-gpdma"] # Nucleo
stm32g491re = ["embassy-stm32/stm32g491re", "not-gpdma"] # Nucleo
-stm32h755zi = ["embassy-stm32/stm32h755zi-cm7", "not-gpdma"] # Nucleo
+stm32h755zi = ["embassy-stm32/stm32h755zi-cm7", "not-gpdma", "dac-adc-pin"] # Nucleo
stm32wb55rg = ["embassy-stm32/stm32wb55rg", "not-gpdma", "ble", "mac" ] # Nucleo
stm32h563zi = ["embassy-stm32/stm32h563zi"] # Nucleo
stm32u585ai = ["embassy-stm32/stm32u585ai"] # IoT board
@@ -23,6 +23,7 @@ ble = ["dep:embassy-stm32-wpan", "embassy-stm32-wpan/ble"]
mac = ["dep:embassy-stm32-wpan", "embassy-stm32-wpan/mac"]
embassy-stm32-wpan = []
not-gpdma = []
+dac-adc-pin = []
[dependencies]
teleprobe-meta = "1"
@@ -42,6 +43,7 @@ cortex-m-rt = "0.7.0"
embedded-hal = "0.2.6"
embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.11" }
embedded-hal-async = { version = "=0.2.0-alpha.2" }
+micromath = "2.0.0"
panic-probe = { version = "0.3.0", features = ["print-defmt"] }
rand_core = { version = "0.6", default-features = false }
rand_chacha = { version = "0.3", default-features = false }
@@ -55,6 +57,11 @@ name = "can"
path = "src/bin/can.rs"
required-features = [ "can",]
+[[bin]]
+name = "dac"
+path = "src/bin/dac.rs"
+required-features = [ "dac-adc-pin",]
+
[[bin]]
name = "gpio"
path = "src/bin/gpio.rs"
diff --git a/tests/stm32/src/bin/dac.rs b/tests/stm32/src/bin/dac.rs
new file mode 100644
index 000000000..67a7d5b59
--- /dev/null
+++ b/tests/stm32/src/bin/dac.rs
@@ -0,0 +1,81 @@
+#![no_std]
+#![no_main]
+#![feature(type_alias_impl_trait)]
+
+// required-features: dac-adc-pin
+
+#[path = "../common.rs"]
+mod common;
+use common::*;
+use defmt::assert;
+use embassy_executor::Spawner;
+use embassy_stm32::adc::Adc;
+use embassy_stm32::dac::{DacCh1, DacChannel, Value};
+use embassy_stm32::dma::NoDma;
+use embassy_time::{Delay, Duration, Timer};
+use {defmt_rtt as _, panic_probe as _};
+
+#[embassy_executor::main]
+async fn main(_spawner: Spawner) {
+ // Initialize the board and obtain a Peripherals instance
+ let p: embassy_stm32::Peripherals = embassy_stm32::init(config());
+
+ #[cfg(feature = "stm32f429zi")]
+ let dac_peripheral = p.DAC;
+
+ #[cfg(any(feature = "stm32h755zi", feature = "stm32g071rb"))]
+ let dac_peripheral = p.DAC1;
+
+ let mut dac: DacCh1<'_, _, NoDma> = DacCh1::new(dac_peripheral, NoDma, p.PA4);
+ unwrap!(dac.set_trigger_enable(false));
+
+ let mut adc = Adc::new(p.ADC1, &mut Delay);
+
+ #[cfg(feature = "stm32h755zi")]
+ let normalization_factor = 256;
+ #[cfg(any(feature = "stm32f429zi", feature = "stm32g071rb"))]
+ let normalization_factor: i32 = 16;
+
+ unwrap!(dac.set(Value::Bit8(0)));
+ // Now wait a little to obtain a stable value
+ Timer::after(Duration::from_millis(30)).await;
+ let offset = adc.read(&mut unsafe { embassy_stm32::Peripherals::steal() }.PA4);
+
+ for v in 0..=255 {
+ // First set the DAC output value
+ let dac_output_val = to_sine_wave(v);
+ unwrap!(dac.set(Value::Bit8(dac_output_val)));
+
+ // Now wait a little to obtain a stable value
+ Timer::after(Duration::from_millis(30)).await;
+
+ // Need to steal the peripherals here because PA4 is obviously in use already
+ let measured = adc.read(&mut unsafe { embassy_stm32::Peripherals::steal() }.PA4);
+ // Calibrate and normalize the measurement to get close to the dac_output_val
+ let measured_normalized = ((measured as i32 - offset as i32) / normalization_factor) as i16;
+
+ info!("value / measured: {} / {}", dac_output_val, measured_normalized);
+
+ // The deviations are quite enormous but that does not matter since this is only a quick test
+ assert!((dac_output_val as i16 - measured_normalized).abs() < 15);
+ }
+
+ info!("Test OK");
+ cortex_m::asm::bkpt();
+}
+
+use core::f32::consts::PI;
+
+use micromath::F32Ext;
+
+fn to_sine_wave(v: u8) -> u8 {
+ if v >= 128 {
+ // top half
+ let r = PI * ((v - 128) as f32 / 128.0);
+ (r.sin() * 128.0 + 127.0) as u8
+ } else {
+ // bottom half
+ let r = PI + PI * (v as f32 / 128.0);
+ (r.sin() * 128.0 + 127.0) as u8
+ }
+}
diff --git a/tests/stm32/src/bin/wpan_ble.rs b/tests/stm32/src/bin/wpan_ble.rs
index 3ad8aca4e..452da77a4 100644
--- a/tests/stm32/src/bin/wpan_ble.rs
+++ b/tests/stm32/src/bin/wpan_ble.rs
@@ -12,6 +12,7 @@ use common::*;
use embassy_executor::Spawner;
use embassy_stm32::bind_interrupts;
use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler};
+use embassy_stm32::rcc::WPAN_DEFAULT;
use embassy_stm32_wpan::hci::host::uart::UartHci;
use embassy_stm32_wpan::hci::host::{AdvertisingFilterPolicy, EncryptionKey, HostHci, OwnAddressType};
use embassy_stm32_wpan::hci::types::AdvertisingType;
@@ -40,7 +41,10 @@ async fn run_mm_queue(memory_manager: mm::MemoryManager) {
#[embassy_executor::main]
async fn main(spawner: Spawner) {
- let p = embassy_stm32::init(config());
+ let mut config = config();
+ config.rcc = WPAN_DEFAULT;
+
+ let p = embassy_stm32::init(config);
info!("Hello World!");
let config = Config::default();
diff --git a/tests/stm32/src/bin/wpan_mac.rs b/tests/stm32/src/bin/wpan_mac.rs
index b04a19ee9..7eab2fd38 100644
--- a/tests/stm32/src/bin/wpan_mac.rs
+++ b/tests/stm32/src/bin/wpan_mac.rs
@@ -10,6 +10,7 @@ use common::*;
use embassy_executor::Spawner;
use embassy_stm32::bind_interrupts;
use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler};
+use embassy_stm32::rcc::WPAN_DEFAULT;
use embassy_stm32_wpan::mac::commands::{AssociateRequest, GetRequest, ResetRequest, SetRequest};
use embassy_stm32_wpan::mac::event::MacEvent;
use embassy_stm32_wpan::mac::typedefs::{
@@ -31,7 +32,10 @@ async fn run_mm_queue(memory_manager: mm::MemoryManager) {
#[embassy_executor::main]
async fn main(spawner: Spawner) {
- let p = embassy_stm32::init(config());
+ let mut config = config();
+ config.rcc = WPAN_DEFAULT;
+
+ let p = embassy_stm32::init(config);
info!("Hello World!");
let config = Config::default();
diff --git a/tests/stm32/src/common.rs b/tests/stm32/src/common.rs
index 3d2a9b8ef..ca5cb43ac 100644
--- a/tests/stm32/src/common.rs
+++ b/tests/stm32/src/common.rs
@@ -33,6 +33,7 @@ pub fn config() -> Config {
{
config.rcc.sys_ck = Some(Hertz(400_000_000));
config.rcc.pll1.q_ck = Some(Hertz(100_000_000));
+ config.rcc.adc_clock_source = embassy_stm32::rcc::AdcClockSource::PerCk;
}
#[cfg(feature = "stm32u585ai")]