From 0705152105287a4c03ffdc21a460d1a26e67c9f6 Mon Sep 17 00:00:00 2001 From: xoviat Date: Wed, 9 Aug 2023 20:15:14 -0500 Subject: [PATCH 001/106] stm32/rtc: add start/stop wakeup --- embassy-stm32/src/rtc/v2.rs | 67 +++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/embassy-stm32/src/rtc/v2.rs b/embassy-stm32/src/rtc/v2.rs index 5b896069..f15ab806 100644 --- a/embassy-stm32/src/rtc/v2.rs +++ b/embassy-stm32/src/rtc/v2.rs @@ -22,6 +22,73 @@ impl super::Rtc { } } + #[allow(dead_code)] + #[cfg(all(feature = "time", stm32wb))] + // start the wakeup alarm with the given duration + pub(crate) fn start_wakeup_alarm(duration: embassy_time::Duration) { + use embassy_time::TICK_HZ; + use stm32_metapac::rtc::vals::Wucksel; + + use crate::interrupt::typelevel::Interrupt; + use crate::rcc::get_freqs; + + let rtc_hz = unsafe { get_freqs() }.rtc.unwrap().0 as u64; + + // Choose the lowest prescaler available + #[cfg(stm32wb)] + let rtc_hz = rtc_hz / 2; + + let rtc_ticks = duration.as_ticks() * rtc_hz / TICK_HZ; + let rtc_ticks = if rtc_ticks > u16::MAX as u64 { + u16::MAX + } else { + rtc_ticks as u16 + }; + + while !RTC::regs().isr().read().wutf() {} + + RTC::regs().isr().modify(|w| w.set_wutf(false)); + + RTC::regs().wutr().modify(|w| w.set_wut(rtc_ticks)); + + crate::interrupt::typelevel::RTC_WKUP::unpend(); + unsafe { crate::interrupt::typelevel::RTC_WKUP::enable() }; + + RTC::regs().cr().modify(|w| { + // Choose the lowest prescaler available + #[cfg(stm32wb)] + w.set_wucksel(Wucksel::DIV2); + + w.set_wutie(true); + w.set_wute(true); + }); + } + + #[allow(dead_code)] + #[cfg(all(feature = "time", stm32wb))] + // stop the wakeup alarm and return the time remaining + pub(crate) fn stop_wakeup_alarm() -> embassy_time::Duration { + use embassy_time::{Duration, TICK_HZ}; + + use crate::interrupt::typelevel::Interrupt; + use crate::rcc::get_freqs; + + crate::interrupt::typelevel::RTC_WKUP::disable(); + + RTC::regs().cr().modify(|w| { + w.set_wute(false); + }); + + let rtc_hz = unsafe { get_freqs() }.rtc.unwrap().0 as u64; + + // Choose the lowest prescaler available + #[cfg(stm32wb)] + let rtc_hz = rtc_hz / 2; + let rtc_ticks = RTC::regs().wutr().read().wut(); + + Duration::from_ticks(rtc_ticks as u64 * TICK_HZ / rtc_hz) + } + #[allow(dead_code)] pub(crate) fn set_clock_source(clock_source: RtcClockSource) { #[cfg(not(rtc_v2wb))] From a0c69ffe024588aab3c4cca70a73275851967616 Mon Sep 17 00:00:00 2001 From: xoviat Date: Thu, 10 Aug 2023 18:59:18 -0500 Subject: [PATCH 002/106] stm32/rtc: autocompute wakeup psc. --- embassy-stm32/src/rtc/v2.rs | 96 ++++++++++++++++++++++++++++++------- 1 file changed, 80 insertions(+), 16 deletions(-) diff --git a/embassy-stm32/src/rtc/v2.rs b/embassy-stm32/src/rtc/v2.rs index f15ab806..32ccb845 100644 --- a/embassy-stm32/src/rtc/v2.rs +++ b/embassy-stm32/src/rtc/v2.rs @@ -5,6 +5,69 @@ use crate::pac::rtc::Rtc; use crate::peripherals::RTC; use crate::rtc::sealed::Instance; +#[derive(Clone, Copy)] +pub(crate) enum WakeupPrescaler { + Div2, + Div4, + Div8, + Div16, +} + +#[cfg(stm32wb)] +impl From for crate::pac::rtc::vals::Wucksel { + fn from(val: WakeupPrescaler) -> Self { + use crate::pac::rtc::vals::Wucksel; + + match val { + WakeupPrescaler::Div2 => Wucksel::DIV2, + WakeupPrescaler::Div4 => Wucksel::DIV4, + WakeupPrescaler::Div8 => Wucksel::DIV8, + WakeupPrescaler::Div16 => Wucksel::DIV16, + } + } +} + +#[cfg(stm32wb)] +impl From for WakeupPrescaler { + fn from(val: crate::pac::rtc::vals::Wucksel) -> Self { + use crate::pac::rtc::vals::Wucksel; + + match val { + Wucksel::DIV2 => WakeupPrescaler::Div2, + Wucksel::DIV4 => WakeupPrescaler::Div4, + Wucksel::DIV8 => WakeupPrescaler::Div8, + Wucksel::DIV16 => WakeupPrescaler::Div16, + _ => unreachable!(), + } + } +} + +impl From for u32 { + fn from(val: WakeupPrescaler) -> Self { + match val { + WakeupPrescaler::Div2 => 2, + WakeupPrescaler::Div4 => 4, + WakeupPrescaler::Div8 => 8, + WakeupPrescaler::Div16 => 16, + } + } +} + +impl WakeupPrescaler { + pub fn compute_min(val: u32) -> Self { + *[ + WakeupPrescaler::Div2, + WakeupPrescaler::Div4, + WakeupPrescaler::Div8, + WakeupPrescaler::Div16, + ] + .iter() + .skip_while(|psc| >::into(**psc) <= val) + .next() + .unwrap_or(&WakeupPrescaler::Div16) + } +} + impl super::Rtc { fn unlock_registers() { #[cfg(any(rtc_v2f2, rtc_v2f3, rtc_v2l1))] @@ -24,44 +87,45 @@ impl super::Rtc { #[allow(dead_code)] #[cfg(all(feature = "time", stm32wb))] - // start the wakeup alarm with the given duration - pub(crate) fn start_wakeup_alarm(duration: embassy_time::Duration) { - use embassy_time::TICK_HZ; - use stm32_metapac::rtc::vals::Wucksel; + /// start the wakeup alarm and return the actual duration of the alarm + /// the actual duration will be the closest value possible that is less + /// than the requested duration. + pub(crate) fn start_wakeup_alarm(requested_duration: embassy_time::Duration) -> embassy_time::Duration { + use embassy_time::{Duration, TICK_HZ}; use crate::interrupt::typelevel::Interrupt; use crate::rcc::get_freqs; let rtc_hz = unsafe { get_freqs() }.rtc.unwrap().0 as u64; - // Choose the lowest prescaler available - #[cfg(stm32wb)] - let rtc_hz = rtc_hz / 2; + let rtc_ticks = requested_duration.as_ticks() * rtc_hz / TICK_HZ; + let prescaler = WakeupPrescaler::compute_min((rtc_ticks / u16::MAX as u64) as u32); - let rtc_ticks = duration.as_ticks() * rtc_hz / TICK_HZ; + // adjust the rtc ticks to the prescaler + let rtc_ticks = rtc_ticks / (>::into(prescaler) as u64); let rtc_ticks = if rtc_ticks > u16::MAX as u64 { u16::MAX } else { rtc_ticks as u16 }; - while !RTC::regs().isr().read().wutf() {} - - RTC::regs().isr().modify(|w| w.set_wutf(false)); - - RTC::regs().wutr().modify(|w| w.set_wut(rtc_ticks)); + let duration = Duration::from_ticks( + rtc_ticks as u64 * TICK_HZ * (>::into(prescaler) as u64) / rtc_hz, + ); crate::interrupt::typelevel::RTC_WKUP::unpend(); unsafe { crate::interrupt::typelevel::RTC_WKUP::enable() }; + RTC::regs().wutr().modify(|w| w.set_wut(rtc_ticks)); + RTC::regs().cr().modify(|w| { - // Choose the lowest prescaler available - #[cfg(stm32wb)] - w.set_wucksel(Wucksel::DIV2); + w.set_wucksel(prescaler.into()); w.set_wutie(true); w.set_wute(true); }); + + duration } #[allow(dead_code)] From b69861013aaacad913d99268fa6da634ab7e0c10 Mon Sep 17 00:00:00 2001 From: xoviat Date: Thu, 10 Aug 2023 19:13:48 -0500 Subject: [PATCH 003/106] stm32/rtc: implement stop_wakeup_alarm --- embassy-stm32/src/rtc/v2.rs | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/embassy-stm32/src/rtc/v2.rs b/embassy-stm32/src/rtc/v2.rs index 32ccb845..5cd5adef 100644 --- a/embassy-stm32/src/rtc/v2.rs +++ b/embassy-stm32/src/rtc/v2.rs @@ -137,20 +137,24 @@ impl super::Rtc { use crate::interrupt::typelevel::Interrupt; use crate::rcc::get_freqs; - crate::interrupt::typelevel::RTC_WKUP::disable(); - RTC::regs().cr().modify(|w| { w.set_wute(false); }); - let rtc_hz = unsafe { get_freqs() }.rtc.unwrap().0 as u64; + // Wait for the wakeup timer to stop + while !RTC::regs().isr().read().wutf() {} - // Choose the lowest prescaler available - #[cfg(stm32wb)] - let rtc_hz = rtc_hz / 2; + RTC::regs().isr().modify(|w| w.set_wutf(false)); + + crate::interrupt::typelevel::RTC_WKUP::disable(); + + let rtc_hz = unsafe { get_freqs() }.rtc.unwrap().0 as u64; + let prescaler: WakeupPrescaler = RTC::regs().cr().read().wucksel().into(); let rtc_ticks = RTC::regs().wutr().read().wut(); - Duration::from_ticks(rtc_ticks as u64 * TICK_HZ / rtc_hz) + Duration::from_ticks( + rtc_ticks as u64 * TICK_HZ * (>::into(prescaler) as u64) / rtc_hz, + ) } #[allow(dead_code)] From 3a3f3b492f95ac54b3cae2ea1ba9f61d2ab6496d Mon Sep 17 00:00:00 2001 From: xoviat Date: Thu, 10 Aug 2023 19:14:55 -0500 Subject: [PATCH 004/106] rustfmt --- embassy-stm32/src/rtc/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/embassy-stm32/src/rtc/mod.rs b/embassy-stm32/src/rtc/mod.rs index 945bfafd..a6102077 100644 --- a/embassy-stm32/src/rtc/mod.rs +++ b/embassy-stm32/src/rtc/mod.rs @@ -13,6 +13,7 @@ pub use self::datetime::{DateTime, DayOfWeek, Error as DateTimeError}; )] #[cfg_attr(any(rtc_v3, rtc_v3u5), path = "v3.rs")] mod _version; +#[allow(unused_imports)] pub use _version::*; use embassy_hal_internal::Peripheral; From b658f10db9a963d85b8465759692b0aa7973a1d1 Mon Sep 17 00:00:00 2001 From: Ruben De Smet Date: Wed, 9 Aug 2023 11:50:26 +0200 Subject: [PATCH 005/106] Expose poll_ready_to_{send,receive} in Sender/Receiver --- embassy-sync/src/channel.rs | 39 +++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/embassy-sync/src/channel.rs b/embassy-sync/src/channel.rs index d6f36f53..3896f70a 100644 --- a/embassy-sync/src/channel.rs +++ b/embassy-sync/src/channel.rs @@ -65,6 +65,13 @@ where pub fn try_send(&self, message: T) -> Result<(), TrySendError> { self.channel.try_send(message) } + + /// Allows a poll_fn to poll until the channel is ready to send + /// + /// See [`Channel::poll_ready_to_send()`] + pub fn poll_ready_to_send(&self, cx: &mut Context<'_>) -> bool { + self.channel.poll_ready_to_send(cx) + } } /// Send-only access to a [`Channel`] without knowing channel size. @@ -106,6 +113,13 @@ impl<'ch, T> DynamicSender<'ch, T> { pub fn try_send(&self, message: T) -> Result<(), TrySendError> { self.channel.try_send_with_context(message, None) } + + /// Allows a poll_fn to poll until the channel is ready to send + /// + /// See [`Channel::poll_ready_to_send()`] + pub fn poll_ready_to_send(&self, cx: &mut Context<'_>) -> bool { + self.channel.poll_ready_to_send(cx) + } } /// Receive-only access to a [`Channel`]. @@ -144,6 +158,13 @@ where pub fn try_recv(&self) -> Result { self.channel.try_recv() } + + /// Allows a poll_fn to poll until the channel is ready to receive + /// + /// See [`Channel::poll_ready_to_receive()`] + pub fn poll_ready_to_receive(&self, cx: &mut Context<'_>) -> bool { + self.channel.poll_ready_to_receive(cx) + } } /// Receive-only access to a [`Channel`] without knowing channel size. @@ -173,6 +194,13 @@ impl<'ch, T> DynamicReceiver<'ch, T> { pub fn try_recv(&self) -> Result { self.channel.try_recv_with_context(None) } + + /// Allows a poll_fn to poll until the channel is ready to receive + /// + /// See [`Channel::poll_ready_to_receive()`] + pub fn poll_ready_to_receive(&self, cx: &mut Context<'_>) -> bool { + self.channel.poll_ready_to_receive(cx) + } } impl<'ch, M, T, const N: usize> From> for DynamicReceiver<'ch, T> @@ -286,6 +314,9 @@ trait DynamicChannel { fn try_send_with_context(&self, message: T, cx: Option<&mut Context<'_>>) -> Result<(), TrySendError>; fn try_recv_with_context(&self, cx: Option<&mut Context<'_>>) -> Result; + + fn poll_ready_to_send(&self, cx: &mut Context<'_>) -> bool; + fn poll_ready_to_receive(&self, cx: &mut Context<'_>) -> bool; } /// Error returned by [`try_recv`](Channel::try_recv). @@ -492,6 +523,14 @@ where fn try_recv_with_context(&self, cx: Option<&mut Context<'_>>) -> Result { Channel::try_recv_with_context(self, cx) } + + fn poll_ready_to_send(&self, cx: &mut Context<'_>) -> bool { + Channel::poll_ready_to_send(self, cx) + } + + fn poll_ready_to_receive(&self, cx: &mut Context<'_>) -> bool { + Channel::poll_ready_to_receive(self, cx) + } } #[cfg(test)] From f9d251cd5cd9c84718cd66e7697a8502c4d61a0a Mon Sep 17 00:00:00 2001 From: Ruben De Smet Date: Fri, 11 Aug 2023 11:15:17 +0200 Subject: [PATCH 006/106] Channel poll methods return Poll instead of bool --- embassy-stm32-wpan/src/mac/driver.rs | 4 +++- embassy-stm32/src/can/bxcan.rs | 9 +------ embassy-sync/src/channel.rs | 36 +++++++++++++++++----------- 3 files changed, 26 insertions(+), 23 deletions(-) diff --git a/embassy-stm32-wpan/src/mac/driver.rs b/embassy-stm32-wpan/src/mac/driver.rs index f8e3a2b0..a58ee231 100644 --- a/embassy-stm32-wpan/src/mac/driver.rs +++ b/embassy-stm32-wpan/src/mac/driver.rs @@ -28,7 +28,9 @@ impl<'d> embassy_net_driver::Driver for Driver<'d> { type TxToken<'a> = TxToken<'d> where Self: 'a; fn receive(&mut self, cx: &mut Context) -> Option<(Self::RxToken<'_>, Self::TxToken<'_>)> { - if self.runner.rx_channel.poll_ready_to_receive(cx) && self.runner.tx_buf_channel.poll_ready_to_receive(cx) { + if self.runner.rx_channel.poll_ready_to_receive(cx).is_ready() + && self.runner.tx_buf_channel.poll_ready_to_receive(cx).is_ready() + { Some(( RxToken { rx: &self.runner.rx_channel, diff --git a/embassy-stm32/src/can/bxcan.rs b/embassy-stm32/src/can/bxcan.rs index fb223e4a..e439207e 100644 --- a/embassy-stm32/src/can/bxcan.rs +++ b/embassy-stm32/src/can/bxcan.rs @@ -506,14 +506,7 @@ impl<'c, 'd, T: Instance> CanRx<'c, 'd, T> { /// 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 + poll_fn(|cx| T::state().rx_queue.poll_ready_to_receive(cx)).await } fn curr_error(&self) -> Option { diff --git a/embassy-sync/src/channel.rs b/embassy-sync/src/channel.rs index 3896f70a..e7224856 100644 --- a/embassy-sync/src/channel.rs +++ b/embassy-sync/src/channel.rs @@ -69,7 +69,7 @@ where /// Allows a poll_fn to poll until the channel is ready to send /// /// See [`Channel::poll_ready_to_send()`] - pub fn poll_ready_to_send(&self, cx: &mut Context<'_>) -> bool { + pub fn poll_ready_to_send(&self, cx: &mut Context<'_>) -> Poll<()> { self.channel.poll_ready_to_send(cx) } } @@ -117,7 +117,7 @@ impl<'ch, T> DynamicSender<'ch, T> { /// Allows a poll_fn to poll until the channel is ready to send /// /// See [`Channel::poll_ready_to_send()`] - pub fn poll_ready_to_send(&self, cx: &mut Context<'_>) -> bool { + pub fn poll_ready_to_send(&self, cx: &mut Context<'_>) -> Poll<()> { self.channel.poll_ready_to_send(cx) } } @@ -162,7 +162,7 @@ where /// Allows a poll_fn to poll until the channel is ready to receive /// /// See [`Channel::poll_ready_to_receive()`] - pub fn poll_ready_to_receive(&self, cx: &mut Context<'_>) -> bool { + pub fn poll_ready_to_receive(&self, cx: &mut Context<'_>) -> Poll<()> { self.channel.poll_ready_to_receive(cx) } } @@ -198,7 +198,7 @@ impl<'ch, T> DynamicReceiver<'ch, T> { /// Allows a poll_fn to poll until the channel is ready to receive /// /// See [`Channel::poll_ready_to_receive()`] - pub fn poll_ready_to_receive(&self, cx: &mut Context<'_>) -> bool { + pub fn poll_ready_to_receive(&self, cx: &mut Context<'_>) -> Poll<()> { self.channel.poll_ready_to_receive(cx) } } @@ -315,8 +315,8 @@ trait DynamicChannel { fn try_recv_with_context(&self, cx: Option<&mut Context<'_>>) -> Result; - fn poll_ready_to_send(&self, cx: &mut Context<'_>) -> bool; - fn poll_ready_to_receive(&self, cx: &mut Context<'_>) -> bool; + fn poll_ready_to_send(&self, cx: &mut Context<'_>) -> Poll<()>; + fn poll_ready_to_receive(&self, cx: &mut Context<'_>) -> Poll<()>; } /// Error returned by [`try_recv`](Channel::try_recv). @@ -370,10 +370,14 @@ impl ChannelState { } } - fn poll_ready_to_receive(&mut self, cx: &mut Context<'_>) -> bool { + fn poll_ready_to_receive(&mut self, cx: &mut Context<'_>) -> Poll<()> { self.receiver_waker.register(cx.waker()); - !self.queue.is_empty() + if !self.queue.is_empty() { + Poll::Ready(()) + } else { + Poll::Pending + } } fn try_send(&mut self, message: T) -> Result<(), TrySendError> { @@ -395,10 +399,14 @@ impl ChannelState { } } - fn poll_ready_to_send(&mut self, cx: &mut Context<'_>) -> bool { + fn poll_ready_to_send(&mut self, cx: &mut Context<'_>) -> Poll<()> { self.senders_waker.register(cx.waker()); - !self.queue.is_full() + if !self.queue.is_full() { + Poll::Ready(()) + } else { + Poll::Pending + } } } @@ -449,12 +457,12 @@ where } /// Allows a poll_fn to poll until the channel is ready to receive - pub fn poll_ready_to_receive(&self, cx: &mut Context<'_>) -> bool { + pub fn poll_ready_to_receive(&self, cx: &mut Context<'_>) -> Poll<()> { self.lock(|c| c.poll_ready_to_receive(cx)) } /// Allows a poll_fn to poll until the channel is ready to send - pub fn poll_ready_to_send(&self, cx: &mut Context<'_>) -> bool { + pub fn poll_ready_to_send(&self, cx: &mut Context<'_>) -> Poll<()> { self.lock(|c| c.poll_ready_to_send(cx)) } @@ -524,11 +532,11 @@ where Channel::try_recv_with_context(self, cx) } - fn poll_ready_to_send(&self, cx: &mut Context<'_>) -> bool { + fn poll_ready_to_send(&self, cx: &mut Context<'_>) -> Poll<()> { Channel::poll_ready_to_send(self, cx) } - fn poll_ready_to_receive(&self, cx: &mut Context<'_>) -> bool { + fn poll_ready_to_receive(&self, cx: &mut Context<'_>) -> Poll<()> { Channel::poll_ready_to_receive(self, cx) } } From b1ec460b9af131ef80fcafd79a7f63aa326aaf94 Mon Sep 17 00:00:00 2001 From: Ruben De Smet Date: Fri, 11 Aug 2023 11:30:29 +0200 Subject: [PATCH 007/106] Implement Channel::poll_receive(..) -> Poll --- embassy-stm32-wpan/src/mac/driver.rs | 2 +- embassy-sync/src/channel.rs | 43 +++++++++++++++++++++++++--- 2 files changed, 40 insertions(+), 5 deletions(-) diff --git a/embassy-stm32-wpan/src/mac/driver.rs b/embassy-stm32-wpan/src/mac/driver.rs index a58ee231..93898d88 100644 --- a/embassy-stm32-wpan/src/mac/driver.rs +++ b/embassy-stm32-wpan/src/mac/driver.rs @@ -46,7 +46,7 @@ impl<'d> embassy_net_driver::Driver for Driver<'d> { } fn transmit(&mut self, cx: &mut Context) -> Option> { - if self.runner.tx_buf_channel.poll_ready_to_receive(cx) { + if self.runner.tx_buf_channel.poll_ready_to_receive(cx).is_ready() { Some(TxToken { tx: &self.runner.tx_channel, tx_buf: &self.runner.tx_buf_channel, diff --git a/embassy-sync/src/channel.rs b/embassy-sync/src/channel.rs index e7224856..dc727fb1 100644 --- a/embassy-sync/src/channel.rs +++ b/embassy-sync/src/channel.rs @@ -165,6 +165,13 @@ where pub fn poll_ready_to_receive(&self, cx: &mut Context<'_>) -> Poll<()> { self.channel.poll_ready_to_receive(cx) } + + /// Poll the channel for the next item + /// + /// See [`Channel::poll_receive()`] + pub fn poll_receive(&self, cx: &mut Context<'_>) -> Poll { + self.channel.poll_receive(cx) + } } /// Receive-only access to a [`Channel`] without knowing channel size. @@ -201,6 +208,13 @@ impl<'ch, T> DynamicReceiver<'ch, T> { pub fn poll_ready_to_receive(&self, cx: &mut Context<'_>) -> Poll<()> { self.channel.poll_ready_to_receive(cx) } + + /// Poll the channel for the next item + /// + /// See [`Channel::poll_receive()`] + pub fn poll_receive(&self, cx: &mut Context<'_>) -> Poll { + self.channel.poll_receive(cx) + } } impl<'ch, M, T, const N: usize> From> for DynamicReceiver<'ch, T> @@ -228,10 +242,7 @@ where type Output = T; fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { - match self.channel.try_recv_with_context(Some(cx)) { - Ok(v) => Poll::Ready(v), - Err(TryRecvError::Empty) => Poll::Pending, - } + self.channel.poll_receive(cx) } } @@ -317,6 +328,8 @@ trait DynamicChannel { fn poll_ready_to_send(&self, cx: &mut Context<'_>) -> Poll<()>; fn poll_ready_to_receive(&self, cx: &mut Context<'_>) -> Poll<()>; + + fn poll_receive(&self, cx: &mut Context<'_>) -> Poll; } /// Error returned by [`try_recv`](Channel::try_recv). @@ -370,6 +383,19 @@ impl ChannelState { } } + fn poll_receive(&mut self, cx: &mut Context<'_>) -> Poll { + if self.queue.is_full() { + self.senders_waker.wake(); + } + + if let Some(message) = self.queue.pop_front() { + Poll::Ready(message) + } else { + self.receiver_waker.register(cx.waker()); + Poll::Pending + } + } + fn poll_ready_to_receive(&mut self, cx: &mut Context<'_>) -> Poll<()> { self.receiver_waker.register(cx.waker()); @@ -452,6 +478,11 @@ where self.lock(|c| c.try_recv_with_context(cx)) } + /// Poll the channel for the next message + pub fn poll_receive(&self, cx: &mut Context<'_>) -> Poll { + self.lock(|c| c.poll_receive(cx)) + } + fn try_send_with_context(&self, m: T, cx: Option<&mut Context<'_>>) -> Result<(), TrySendError> { self.lock(|c| c.try_send_with_context(m, cx)) } @@ -539,6 +570,10 @@ where fn poll_ready_to_receive(&self, cx: &mut Context<'_>) -> Poll<()> { Channel::poll_ready_to_receive(self, cx) } + + fn poll_receive(&self, cx: &mut Context<'_>) -> Poll { + Channel::poll_receive(self, cx) + } } #[cfg(test)] From 2d980068c09aa8fcc6bb4fd4d2e46107ef0e997f Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Sat, 19 Aug 2023 19:31:49 +0200 Subject: [PATCH 008/106] Update Nightly. --- rust-toolchain.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 179ed1d6..7b34afa2 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,7 +1,7 @@ # Before upgrading check that everything is available on all tier1 targets here: # https://rust-lang.github.io/rustup-components-history [toolchain] -channel = "nightly-2023-06-28" +channel = "nightly-2023-08-19" components = [ "rust-src", "rustfmt", "llvm-tools-preview" ] targets = [ "thumbv7em-none-eabi", From 0032f8a2ec05ed61b17dc1992f907f23f1b37f92 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Sat, 19 Aug 2023 19:35:10 +0200 Subject: [PATCH 009/106] rustfmt. --- embassy-net-esp-hosted/src/control.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/embassy-net-esp-hosted/src/control.rs b/embassy-net-esp-hosted/src/control.rs index 6cd57f68..b8026611 100644 --- a/embassy-net-esp-hosted/src/control.rs +++ b/embassy-net-esp-hosted/src/control.rs @@ -35,9 +35,9 @@ macro_rules! ioctl { }; $self.ioctl(&mut msg).await?; let Some(proto::CtrlMsgPayload::$resp_variant($resp)) = msg.payload else { - warn!("unexpected response variant"); - return Err(Error::Internal); - }; + warn!("unexpected response variant"); + return Err(Error::Internal); + }; if $resp.resp != 0 { return Err(Error::Failed($resp.resp)); } From 17e9a8ebe13a254417d323b0f634d18eb81caa3d Mon Sep 17 00:00:00 2001 From: Isaikin Roman Date: Sun, 20 Aug 2023 07:42:54 +0200 Subject: [PATCH 010/106] Fix hardcoded buffer length in USB NCM causing broken link on USB 2.0. --- embassy-usb/src/class/cdc_ncm/mod.rs | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/embassy-usb/src/class/cdc_ncm/mod.rs b/embassy-usb/src/class/cdc_ncm/mod.rs index fcfa0bfc..830e9b76 100644 --- a/embassy-usb/src/class/cdc_ncm/mod.rs +++ b/embassy-usb/src/class/cdc_ncm/mod.rs @@ -248,6 +248,8 @@ pub struct CdcNcmClass<'d, D: Driver<'d>> { write_ep: D::EndpointIn, _control: &'d ControlShared, + + max_packet_size: usize, } impl<'d, D: Driver<'d>> CdcNcmClass<'d, D> { @@ -338,6 +340,7 @@ impl<'d, D: Driver<'d>> CdcNcmClass<'d, D> { read_ep, write_ep, _control: &state.shared, + max_packet_size: max_packet_size as usize, } } @@ -349,6 +352,7 @@ impl<'d, D: Driver<'d>> CdcNcmClass<'d, D> { Sender { write_ep: self.write_ep, seq: 0, + max_packet_size: self.max_packet_size, }, Receiver { data_if: self.data_if, @@ -365,6 +369,7 @@ impl<'d, D: Driver<'d>> CdcNcmClass<'d, D> { pub struct Sender<'d, D: Driver<'d>> { write_ep: D::EndpointIn, seq: u16, + max_packet_size: usize, } impl<'d, D: Driver<'d>> Sender<'d, D> { @@ -375,8 +380,8 @@ impl<'d, D: Driver<'d>> Sender<'d, D> { let seq = self.seq; self.seq = self.seq.wrapping_add(1); - const MAX_PACKET_SIZE: usize = 64; // TODO unhardcode const OUT_HEADER_LEN: usize = 28; + const ABS_MAX_PACKET_SIZE: usize = 512; let header = NtbOutHeader { nth_sig: SIG_NTH, @@ -395,27 +400,27 @@ impl<'d, D: Driver<'d>> Sender<'d, D> { }; // Build first packet on a buffer, send next packets straight from `data`. - let mut buf = [0; MAX_PACKET_SIZE]; + let mut buf = [0; ABS_MAX_PACKET_SIZE]; let n = byteify(&mut buf, header); assert_eq!(n.len(), OUT_HEADER_LEN); - if OUT_HEADER_LEN + data.len() < MAX_PACKET_SIZE { + if OUT_HEADER_LEN + data.len() < self.max_packet_size { // First packet is not full, just send it. // No need to send ZLP because it's short for sure. buf[OUT_HEADER_LEN..][..data.len()].copy_from_slice(data); self.write_ep.write(&buf[..OUT_HEADER_LEN + data.len()]).await?; } else { - let (d1, d2) = data.split_at(MAX_PACKET_SIZE - OUT_HEADER_LEN); + let (d1, d2) = data.split_at(self.max_packet_size - OUT_HEADER_LEN); - buf[OUT_HEADER_LEN..].copy_from_slice(d1); - self.write_ep.write(&buf).await?; + buf[OUT_HEADER_LEN..self.max_packet_size].copy_from_slice(d1); + self.write_ep.write(&buf[..self.max_packet_size]).await?; - for chunk in d2.chunks(MAX_PACKET_SIZE) { + for chunk in d2.chunks(self.max_packet_size) { self.write_ep.write(&chunk).await?; } // Send ZLP if needed. - if d2.len() % MAX_PACKET_SIZE == 0 { + if d2.len() % self.max_packet_size == 0 { self.write_ep.write(&[]).await?; } } From 67ca88d5a031369f9bae99c55243625644c93a71 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Sun, 20 Aug 2023 10:57:28 +0200 Subject: [PATCH 011/106] stm32/can: make latency assertion more lenient. --- tests/stm32/src/bin/can.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/stm32/src/bin/can.rs b/tests/stm32/src/bin/can.rs index 8737ca8e..acf54521 100644 --- a/tests/stm32/src/bin/can.rs +++ b/tests/stm32/src/bin/can.rs @@ -80,8 +80,8 @@ async fn main(_spawner: Spawner) { const MIN_LATENCY: Duration = Duration::from_micros(50); const MAX_LATENCY: Duration = Duration::from_micros(150); assert!( - MIN_LATENCY < latency && latency < MAX_LATENCY, - "{} < {} < {}", + MIN_LATENCY <= latency && latency <= MAX_LATENCY, + "{} <= {} <= {}", MIN_LATENCY, latency, MAX_LATENCY From 977ae5e3e46b5b3ffe06b53d58147338f74f9473 Mon Sep 17 00:00:00 2001 From: soypat Date: Sun, 20 Aug 2023 20:01:47 -0300 Subject: [PATCH 012/106] don't pay for what you don't use --- cyw43/src/bus.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cyw43/src/bus.rs b/cyw43/src/bus.rs index e26f1112..0b5632cf 100644 --- a/cyw43/src/bus.rs +++ b/cyw43/src/bus.rs @@ -102,7 +102,7 @@ where cmd_buf[0] = cmd; cmd_buf[1..][..buf.len()].copy_from_slice(buf); - self.status = self.spi.cmd_write(&cmd_buf).await; + self.status = self.spi.cmd_write(&cmd_buf[..buf.len() + 1]).await; } #[allow(unused)] From 0a73c84df0936facecb3e1a97cf6f4795d321b87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Buga?= Date: Mon, 21 Aug 2023 13:55:30 +0200 Subject: [PATCH 013/106] Make AvailableTask public, deduplicate --- embassy-executor/CHANGELOG.md | 2 + embassy-executor/src/raw/mod.rs | 119 ++++++++++++++++++-------------- embassy-executor/src/spawner.rs | 3 +- 3 files changed, 70 insertions(+), 54 deletions(-) diff --git a/embassy-executor/CHANGELOG.md b/embassy-executor/CHANGELOG.md index e2e7bce3..43d94e54 100644 --- a/embassy-executor/CHANGELOG.md +++ b/embassy-executor/CHANGELOG.md @@ -8,6 +8,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased - Replaced Pender. Implementations now must define an extern function called `__pender`. +- Made `raw::AvailableTask` public +- Made `SpawnToken::new_failed` public ## 0.2.1 - 2023-08-10 diff --git a/embassy-executor/src/raw/mod.rs b/embassy-executor/src/raw/mod.rs index 7caa3302..c1d82e18 100644 --- a/embassy-executor/src/raw/mod.rs +++ b/embassy-executor/src/raw/mod.rs @@ -147,10 +147,7 @@ impl TaskStorage { pub fn spawn(&'static self, future: impl FnOnce() -> F) -> SpawnToken { let task = AvailableTask::claim(self); match task { - Some(task) => { - let task = task.initialize(future); - unsafe { SpawnToken::::new(task) } - } + Some(task) => task.initialize(future), None => SpawnToken::new_failed(), } } @@ -186,12 +183,16 @@ impl TaskStorage { } } -struct AvailableTask { +/// An uninitialized [`TaskStorage`]. +pub struct AvailableTask { task: &'static TaskStorage, } impl AvailableTask { - fn claim(task: &'static TaskStorage) -> Option { + /// Try to claim a [`TaskStorage`]. + /// + /// This function returns `None` if a task has already been spawned and has not finished running. + pub fn claim(task: &'static TaskStorage) -> Option { task.raw .state .compare_exchange(0, STATE_SPAWNED | STATE_RUN_QUEUED, Ordering::AcqRel, Ordering::Acquire) @@ -199,61 +200,30 @@ impl AvailableTask { .map(|_| Self { task }) } - fn initialize(self, future: impl FnOnce() -> F) -> TaskRef { + fn initialize_impl(self, future: impl FnOnce() -> F) -> SpawnToken { unsafe { self.task.raw.poll_fn.set(Some(TaskStorage::::poll)); self.task.future.write(future()); - } - TaskRef::new(self.task) - } -} -/// Raw storage that can hold up to N tasks of the same type. -/// -/// This is essentially a `[TaskStorage; N]`. -pub struct TaskPool { - pool: [TaskStorage; N], -} + let task = TaskRef::new(self.task); -impl TaskPool { - /// Create a new TaskPool, with all tasks in non-spawned state. - pub const fn new() -> Self { - Self { - pool: [TaskStorage::NEW; N], + SpawnToken::new(task) } } - /// Try to spawn a task in the pool. - /// - /// See [`TaskStorage::spawn()`] for details. - /// - /// This will loop over the pool and spawn the task in the first storage that - /// is currently free. If none is free, a "poisoned" SpawnToken is returned, - /// which will cause [`Spawner::spawn()`](super::Spawner::spawn) to return the error. - pub fn spawn(&'static self, future: impl FnOnce() -> F) -> SpawnToken { - let task = self.pool.iter().find_map(AvailableTask::claim); - match task { - Some(task) => { - let task = task.initialize(future); - unsafe { SpawnToken::::new(task) } - } - None => SpawnToken::new_failed(), - } + /// Initialize the [`TaskStorage`] to run the given future. + pub fn initialize(self, future: impl FnOnce() -> F) -> SpawnToken { + self.initialize_impl::(future) } - /// Like spawn(), but allows the task to be send-spawned if the args are Send even if - /// the future is !Send. + /// Initialize the [`TaskStorage`] to run the given future. /// - /// Not covered by semver guarantees. DO NOT call this directly. Intended to be used - /// by the Embassy macros ONLY. + /// # Safety /// - /// SAFETY: `future` must be a closure of the form `move || my_async_fn(args)`, where `my_async_fn` + /// `future` must be a closure of the form `move || my_async_fn(args)`, where `my_async_fn` /// is an `async fn`, NOT a hand-written `Future`. #[doc(hidden)] - pub unsafe fn _spawn_async_fn(&'static self, future: FutFn) -> SpawnToken - where - FutFn: FnOnce() -> F, - { + pub unsafe fn __initialize_async_fn(self, future: impl FnOnce() -> F) -> SpawnToken { // When send-spawning a task, we construct the future in this thread, and effectively // "send" it to the executor thread by enqueuing it in its queue. Therefore, in theory, // send-spawning should require the future `F` to be `Send`. @@ -279,16 +249,59 @@ impl TaskPool { // // This ONLY holds for `async fn` futures. The other `spawn` methods can be called directly // by the user, with arbitrary hand-implemented futures. This is why these return `SpawnToken`. + self.initialize_impl::(future) + } +} - let task = self.pool.iter().find_map(AvailableTask::claim); - match task { - Some(task) => { - let task = task.initialize(future); - unsafe { SpawnToken::::new(task) } - } +/// Raw storage that can hold up to N tasks of the same type. +/// +/// This is essentially a `[TaskStorage; N]`. +pub struct TaskPool { + pool: [TaskStorage; N], +} + +impl TaskPool { + /// Create a new TaskPool, with all tasks in non-spawned state. + pub const fn new() -> Self { + Self { + pool: [TaskStorage::NEW; N], + } + } + + fn spawn_impl(&'static self, future: impl FnOnce() -> F) -> SpawnToken { + match self.pool.iter().find_map(AvailableTask::claim) { + Some(task) => task.initialize_impl::(future), None => SpawnToken::new_failed(), } } + + /// Try to spawn a task in the pool. + /// + /// See [`TaskStorage::spawn()`] for details. + /// + /// This will loop over the pool and spawn the task in the first storage that + /// is currently free. If none is free, a "poisoned" SpawnToken is returned, + /// which will cause [`Spawner::spawn()`](super::Spawner::spawn) to return the error. + pub fn spawn(&'static self, future: impl FnOnce() -> F) -> SpawnToken { + self.spawn_impl::(future) + } + + /// Like spawn(), but allows the task to be send-spawned if the args are Send even if + /// the future is !Send. + /// + /// Not covered by semver guarantees. DO NOT call this directly. Intended to be used + /// by the Embassy macros ONLY. + /// + /// SAFETY: `future` must be a closure of the form `move || my_async_fn(args)`, where `my_async_fn` + /// is an `async fn`, NOT a hand-written `Future`. + #[doc(hidden)] + pub unsafe fn _spawn_async_fn(&'static self, future: FutFn) -> SpawnToken + where + FutFn: FnOnce() -> F, + { + // See the comment in AvailableTask::__initialize_async_fn for explanation. + self.spawn_impl::(future) + } } #[derive(Clone, Copy)] diff --git a/embassy-executor/src/spawner.rs b/embassy-executor/src/spawner.rs index 2b622404..5a3a0dee 100644 --- a/embassy-executor/src/spawner.rs +++ b/embassy-executor/src/spawner.rs @@ -33,7 +33,8 @@ impl SpawnToken { } } - pub(crate) fn new_failed() -> Self { + /// Return a SpawnToken that represents a failed spawn. + pub fn new_failed() -> Self { Self { raw_task: None, phantom: PhantomData, From f723982beccc1306a74560e6455f38834ea95689 Mon Sep 17 00:00:00 2001 From: xoviat Date: Mon, 21 Aug 2023 17:44:38 -0500 Subject: [PATCH 014/106] rtc: impl. draft rtcinstant api --- embassy-stm32/src/rtc/v2.rs | 123 ++++++++++++++++++++++++++++-------- 1 file changed, 97 insertions(+), 26 deletions(-) diff --git a/embassy-stm32/src/rtc/v2.rs b/embassy-stm32/src/rtc/v2.rs index 5cd5adef..ba881e3f 100644 --- a/embassy-stm32/src/rtc/v2.rs +++ b/embassy-stm32/src/rtc/v2.rs @@ -5,6 +5,63 @@ use crate::pac::rtc::Rtc; use crate::peripherals::RTC; use crate::rtc::sealed::Instance; +#[cfg(all(feature = "time", any(stm32wb, stm32f4)))] +pub struct RtcInstant { + ssr: u16, + st: u8, +} + +#[cfg(all(feature = "time", any(stm32wb, stm32f4)))] +impl RtcInstant { + pub fn now() -> Self { + // TODO: read value twice + use crate::rtc::bcd2_to_byte; + + let tr = RTC::regs().tr().read(); + let ssr = RTC::regs().ssr().read().ss(); + + let st = bcd2_to_byte((tr.st(), tr.su())); + + let _ = RTC::regs().dr().read(); + + trace!("ssr: {}", ssr); + trace!("st: {}", st); + + Self { ssr, st } + } +} + +#[cfg(all(feature = "time", any(stm32wb, stm32f4)))] +impl core::ops::Sub for RtcInstant { + type Output = embassy_time::Duration; + + fn sub(self, rhs: Self) -> Self::Output { + use embassy_time::{Duration, TICK_HZ}; + + trace!("self st: {}", self.st); + trace!("other st: {}", rhs.st); + + let st = if self.st < rhs.st { self.st + 60 } else { self.st }; + + trace!("self st: {}", st); + + let self_ticks = (st as u32 * 256 + self.ssr as u32); + let other_ticks = (rhs.st as u32 * 256 + rhs.ssr as u32); + let rtc_ticks = self_ticks - other_ticks; + + trace!("self ticks: {}", self_ticks); + trace!("other ticks: {}", other_ticks); + trace!("rtc ticks: {}", rtc_ticks); + + // TODO: read prescaler + + Duration::from_ticks( + ((((st as u32 * 256 + self.ssr as u32) - (rhs.st as u32 * 256 + rhs.ssr as u32)) * TICK_HZ as u32) as u32 + / 256u32) as u64, + ) + } +} + #[derive(Clone, Copy)] pub(crate) enum WakeupPrescaler { Div2, @@ -13,7 +70,7 @@ pub(crate) enum WakeupPrescaler { Div16, } -#[cfg(stm32wb)] +#[cfg(any(stm32wb, stm32f4))] impl From for crate::pac::rtc::vals::Wucksel { fn from(val: WakeupPrescaler) -> Self { use crate::pac::rtc::vals::Wucksel; @@ -27,7 +84,7 @@ impl From for crate::pac::rtc::vals::Wucksel { } } -#[cfg(stm32wb)] +#[cfg(any(stm32wb, stm32f4))] impl From for WakeupPrescaler { fn from(val: crate::pac::rtc::vals::Wucksel) -> Self { use crate::pac::rtc::vals::Wucksel; @@ -86,11 +143,14 @@ impl super::Rtc { } #[allow(dead_code)] - #[cfg(all(feature = "time", stm32wb))] + #[cfg(all(feature = "time", any(stm32wb, stm32f4)))] /// start the wakeup alarm and return the actual duration of the alarm /// the actual duration will be the closest value possible that is less /// than the requested duration. - pub(crate) fn start_wakeup_alarm(requested_duration: embassy_time::Duration) -> embassy_time::Duration { + /// + /// note: this api is exposed for testing purposes until low power is implemented. + /// it is not intended to be public + pub fn start_wakeup_alarm(requested_duration: embassy_time::Duration) -> RtcInstant { use embassy_time::{Duration, TICK_HZ}; use crate::interrupt::typelevel::Interrupt; @@ -103,8 +163,8 @@ impl super::Rtc { // adjust the rtc ticks to the prescaler let rtc_ticks = rtc_ticks / (>::into(prescaler) as u64); - let rtc_ticks = if rtc_ticks > u16::MAX as u64 { - u16::MAX + let rtc_ticks = if rtc_ticks >= u16::MAX as u64 { + u16::MAX - 1 } else { rtc_ticks as u16 }; @@ -113,8 +173,10 @@ impl super::Rtc { rtc_ticks as u64 * TICK_HZ * (>::into(prescaler) as u64) / rtc_hz, ); - crate::interrupt::typelevel::RTC_WKUP::unpend(); - unsafe { crate::interrupt::typelevel::RTC_WKUP::enable() }; + trace!("set wakeup timer for {} ms", duration.as_millis()); + + RTC::regs().wpr().write(|w| w.set_key(0xca)); + RTC::regs().wpr().write(|w| w.set_key(0x53)); RTC::regs().wutr().modify(|w| w.set_wut(rtc_ticks)); @@ -125,36 +187,45 @@ impl super::Rtc { w.set_wute(true); }); - duration + if !RTC::regs().cr().read().wute() { + trace!("wakeup timer not enabled"); + } else { + trace!("wakeup timer enabled"); + } + + crate::interrupt::typelevel::RTC_WKUP::unpend(); + unsafe { crate::interrupt::typelevel::RTC_WKUP::enable() }; + + RtcInstant::now() } #[allow(dead_code)] - #[cfg(all(feature = "time", stm32wb))] - // stop the wakeup alarm and return the time remaining - pub(crate) fn stop_wakeup_alarm() -> embassy_time::Duration { - use embassy_time::{Duration, TICK_HZ}; - + #[cfg(all(feature = "time", any(stm32wb, stm32f4)))] + /// stop the wakeup alarm and return the time remaining + /// + /// note: this api is exposed for testing purposes until low power is implemented. + /// it is not intended to be public + pub fn stop_wakeup_alarm() -> RtcInstant { use crate::interrupt::typelevel::Interrupt; - use crate::rcc::get_freqs; + + crate::interrupt::typelevel::RTC_WKUP::disable(); + + trace!("disable wakeup timer..."); RTC::regs().cr().modify(|w| { w.set_wute(false); }); + trace!("wait for wakeup timer stop..."); + // Wait for the wakeup timer to stop - while !RTC::regs().isr().read().wutf() {} + // while !RTC::regs().isr().read().wutf() {} + // + // RTC::regs().isr().modify(|w| w.set_wutf(false)); - RTC::regs().isr().modify(|w| w.set_wutf(false)); + trace!("wait for wakeup timer stop...done"); - crate::interrupt::typelevel::RTC_WKUP::disable(); - - let rtc_hz = unsafe { get_freqs() }.rtc.unwrap().0 as u64; - let prescaler: WakeupPrescaler = RTC::regs().cr().read().wucksel().into(); - let rtc_ticks = RTC::regs().wutr().read().wut(); - - Duration::from_ticks( - rtc_ticks as u64 * TICK_HZ * (>::into(prescaler) as u64) / rtc_hz, - ) + RtcInstant::now() } #[allow(dead_code)] From 8c12453544131a5ef8a6be78e87c8e49a12cbec3 Mon Sep 17 00:00:00 2001 From: xoviat Date: Mon, 21 Aug 2023 17:50:18 -0500 Subject: [PATCH 015/106] stm32/rcc: set rtc clock on f4 --- embassy-stm32/src/rcc/f4.rs | 7 +++++++ embassy-stm32/src/rcc/mod.rs | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/embassy-stm32/src/rcc/f4.rs b/embassy-stm32/src/rcc/f4.rs index 2ae0d15c..ee9cb289 100644 --- a/embassy-stm32/src/rcc/f4.rs +++ b/embassy-stm32/src/rcc/f4.rs @@ -473,6 +473,11 @@ pub(crate) unsafe fn init(config: Config) { Rtc::set_clock_source(clock_source); }); + let rtc = match config.rtc { + Some(RtcClockSource::LSI) => Some(LSI_FREQ), + _ => None, + }; + set_freqs(Clocks { sys: Hertz(sysclk), apb1: Hertz(pclk1), @@ -492,6 +497,8 @@ pub(crate) unsafe fn init(config: Config) { #[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f446, stm32f469, stm32f479))] pllsai: None, + + rtc: rtc, }); } diff --git a/embassy-stm32/src/rcc/mod.rs b/embassy-stm32/src/rcc/mod.rs index 62c19bda..698da8d8 100644 --- a/embassy-stm32/src/rcc/mod.rs +++ b/embassy-stm32/src/rcc/mod.rs @@ -74,7 +74,7 @@ pub struct Clocks { #[cfg(any(rcc_h5, rcc_h50, rcc_h7, rcc_h7ab))] pub adc: Option, - #[cfg(rcc_wb)] + #[cfg(any(rcc_wb, rcc_f4))] /// Set only if the lsi or lse is configured pub rtc: Option, } From 7148397771a7c1a374d4b298b206f815573772f8 Mon Sep 17 00:00:00 2001 From: xoviat Date: Mon, 21 Aug 2023 18:00:49 -0500 Subject: [PATCH 016/106] stm32/rtc: misc fixes --- embassy-stm32/src/rtc/v2.rs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/embassy-stm32/src/rtc/v2.rs b/embassy-stm32/src/rtc/v2.rs index ba881e3f..7acf1b6a 100644 --- a/embassy-stm32/src/rtc/v2.rs +++ b/embassy-stm32/src/rtc/v2.rs @@ -18,9 +18,15 @@ impl RtcInstant { use crate::rtc::bcd2_to_byte; let tr = RTC::regs().tr().read(); + let tr2 = RTC::regs().tr().read(); let ssr = RTC::regs().ssr().read().ss(); + let ssr2 = RTC::regs().ssr().read().ss(); let st = bcd2_to_byte((tr.st(), tr.su())); + let st2 = bcd2_to_byte((tr2.st(), tr2.su())); + + assert!(st == st2); + assert!(ssr == ssr2); let _ = RTC::regs().dr().read(); @@ -41,12 +47,15 @@ impl core::ops::Sub for RtcInstant { trace!("self st: {}", self.st); trace!("other st: {}", rhs.st); + trace!("self ssr: {}", self.ssr); + trace!("other ssr: {}", rhs.ssr); + let st = if self.st < rhs.st { self.st + 60 } else { self.st }; trace!("self st: {}", st); - let self_ticks = (st as u32 * 256 + self.ssr as u32); - let other_ticks = (rhs.st as u32 * 256 + rhs.ssr as u32); + let self_ticks = st as u32 * 256 + self.ssr as u32; + let other_ticks = rhs.st as u32 * 256 + rhs.ssr as u32; let rtc_ticks = self_ticks - other_ticks; trace!("self ticks: {}", self_ticks); From 5bfddfc9b6c5b64cecba377cc6c42e1e270e98cc Mon Sep 17 00:00:00 2001 From: xoviat Date: Mon, 21 Aug 2023 18:10:10 -0500 Subject: [PATCH 017/106] stm32/rcc: add rtc to f410 --- embassy-stm32/src/rcc/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/embassy-stm32/src/rcc/mod.rs b/embassy-stm32/src/rcc/mod.rs index 698da8d8..4d4c6b61 100644 --- a/embassy-stm32/src/rcc/mod.rs +++ b/embassy-stm32/src/rcc/mod.rs @@ -74,7 +74,7 @@ pub struct Clocks { #[cfg(any(rcc_h5, rcc_h50, rcc_h7, rcc_h7ab))] pub adc: Option, - #[cfg(any(rcc_wb, rcc_f4))] + #[cfg(any(rcc_wb, rcc_f4, rcc_f410))] /// Set only if the lsi or lse is configured pub rtc: Option, } From 8878ce046c2665eb641f33bc484ca68083d7d353 Mon Sep 17 00:00:00 2001 From: xoviat Date: Mon, 21 Aug 2023 18:33:10 -0500 Subject: [PATCH 018/106] rtc: fix rtcinstant delay computation --- embassy-stm32/src/rtc/v2.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/embassy-stm32/src/rtc/v2.rs b/embassy-stm32/src/rtc/v2.rs index 7acf1b6a..e9b83123 100644 --- a/embassy-stm32/src/rtc/v2.rs +++ b/embassy-stm32/src/rtc/v2.rs @@ -54,8 +54,8 @@ impl core::ops::Sub for RtcInstant { trace!("self st: {}", st); - let self_ticks = st as u32 * 256 + self.ssr as u32; - let other_ticks = rhs.st as u32 * 256 + rhs.ssr as u32; + let self_ticks = st as u32 * 256 + (255 - self.ssr as u32); + let other_ticks = rhs.st as u32 * 256 + (255 - rhs.ssr as u32); let rtc_ticks = self_ticks - other_ticks; trace!("self ticks: {}", self_ticks); @@ -65,7 +65,8 @@ impl core::ops::Sub for RtcInstant { // TODO: read prescaler Duration::from_ticks( - ((((st as u32 * 256 + self.ssr as u32) - (rhs.st as u32 * 256 + rhs.ssr as u32)) * TICK_HZ as u32) as u32 + ((((st as u32 * 256 + (255u32 - self.ssr as u32)) - (rhs.st as u32 * 256 + (255u32 - rhs.ssr as u32))) + * TICK_HZ as u32) as u32 / 256u32) as u64, ) } From c39671266e21dd9e35e60cc680453cd5c38162db Mon Sep 17 00:00:00 2001 From: Ruben De Smet Date: Fri, 11 Aug 2023 11:58:22 +0200 Subject: [PATCH 019/106] Deprecate *recv* in favor of *receive* --- embassy-stm32-wpan/src/mac/driver.rs | 4 +- embassy-stm32-wpan/src/mac/runner.rs | 2 +- embassy-stm32/src/can/bxcan.rs | 4 +- embassy-sync/src/channel.rs | 88 +++++++++---------- examples/nrf52840/src/bin/channel.rs | 2 +- .../src/bin/channel_sender_receiver.rs | 2 +- examples/nrf52840/src/bin/uart_split.rs | 2 +- .../rp/src/bin/lora_p2p_send_multicore.rs | 2 +- examples/rp/src/bin/multicore.rs | 2 +- examples/stm32f3/src/bin/button_events.rs | 4 +- examples/stm32h5/src/bin/usart_split.rs | 2 +- examples/stm32h7/src/bin/usart_split.rs | 2 +- tests/rp/src/bin/gpio_multicore.rs | 6 +- tests/rp/src/bin/multicore.rs | 4 +- 14 files changed, 63 insertions(+), 63 deletions(-) diff --git a/embassy-stm32-wpan/src/mac/driver.rs b/embassy-stm32-wpan/src/mac/driver.rs index 93898d88..bfc4f1ee 100644 --- a/embassy-stm32-wpan/src/mac/driver.rs +++ b/embassy-stm32-wpan/src/mac/driver.rs @@ -93,7 +93,7 @@ impl<'d> embassy_net_driver::RxToken for RxToken<'d> { { // Only valid data events should be put into the queue - let data_event = match self.rx.try_recv().unwrap() { + let data_event = match self.rx.try_receive().unwrap() { MacEvent::McpsDataInd(data_event) => data_event, _ => unreachable!(), }; @@ -113,7 +113,7 @@ impl<'d> embassy_net_driver::TxToken for TxToken<'d> { F: FnOnce(&mut [u8]) -> R, { // Only valid tx buffers should be put into the queue - let buf = self.tx_buf.try_recv().unwrap(); + let buf = self.tx_buf.try_receive().unwrap(); let r = f(&mut buf[..len]); // The tx channel should always be of equal capacity to the tx_buf channel diff --git a/embassy-stm32-wpan/src/mac/runner.rs b/embassy-stm32-wpan/src/mac/runner.rs index 1be6df8a..d3099b6b 100644 --- a/embassy-stm32-wpan/src/mac/runner.rs +++ b/embassy-stm32-wpan/src/mac/runner.rs @@ -73,7 +73,7 @@ impl<'a> Runner<'a> { let mut msdu_handle = 0x02; loop { - let (buf, len) = self.tx_channel.recv().await; + let (buf, len) = self.tx_channel.receive().await; let _wm = self.write_mutex.lock().await; // The mutex should be dropped on the next loop iteration diff --git a/embassy-stm32/src/can/bxcan.rs b/embassy-stm32/src/can/bxcan.rs index e439207e..7ad13cec 100644 --- a/embassy-stm32/src/can/bxcan.rs +++ b/embassy-stm32/src/can/bxcan.rs @@ -478,7 +478,7 @@ impl<'c, 'd, T: Instance> CanRx<'c, 'd, T> { pub async fn read(&mut self) -> Result { poll_fn(|cx| { T::state().err_waker.register(cx.waker()); - if let Poll::Ready(envelope) = T::state().rx_queue.recv().poll_unpin(cx) { + if let Poll::Ready(envelope) = T::state().rx_queue.receive().poll_unpin(cx) { return Poll::Ready(Ok(envelope)); } else if let Some(err) = self.curr_error() { return Poll::Ready(Err(err)); @@ -493,7 +493,7 @@ impl<'c, 'd, T: Instance> CanRx<'c, 'd, T> { /// /// Returns [Err(TryReadError::Empty)] if there are no frames in the rx queue. pub fn try_read(&mut self) -> Result { - if let Ok(envelope) = T::state().rx_queue.try_recv() { + if let Ok(envelope) = T::state().rx_queue.try_receive() { return Ok(envelope); } diff --git a/embassy-sync/src/channel.rs b/embassy-sync/src/channel.rs index dc727fb1..62ea1307 100644 --- a/embassy-sync/src/channel.rs +++ b/embassy-sync/src/channel.rs @@ -147,16 +147,16 @@ where { /// Receive the next value. /// - /// See [`Channel::recv()`]. - pub fn recv(&self) -> RecvFuture<'_, M, T, N> { - self.channel.recv() + /// See [`Channel::receive()`]. + pub fn receive(&self) -> ReceiveFuture<'_, M, T, N> { + self.channel.receive() } /// Attempt to immediately receive the next value. /// - /// See [`Channel::try_recv()`] - pub fn try_recv(&self) -> Result { - self.channel.try_recv() + /// See [`Channel::try_receive()`] + pub fn try_receive(&self) -> Result { + self.channel.try_receive() } /// Allows a poll_fn to poll until the channel is ready to receive @@ -190,16 +190,16 @@ impl<'ch, T> Copy for DynamicReceiver<'ch, T> {} impl<'ch, T> DynamicReceiver<'ch, T> { /// Receive the next value. /// - /// See [`Channel::recv()`]. - pub fn recv(&self) -> DynamicRecvFuture<'_, T> { - DynamicRecvFuture { channel: self.channel } + /// See [`Channel::receive()`]. + pub fn receive(&self) -> DynamicReceiveFuture<'_, T> { + DynamicReceiveFuture { channel: self.channel } } /// Attempt to immediately receive the next value. /// - /// See [`Channel::try_recv()`] - pub fn try_recv(&self) -> Result { - self.channel.try_recv_with_context(None) + /// See [`Channel::try_receive()`] + pub fn try_receive(&self) -> Result { + self.channel.try_receive_with_context(None) } /// Allows a poll_fn to poll until the channel is ready to receive @@ -226,16 +226,16 @@ where } } -/// Future returned by [`Channel::recv`] and [`Receiver::recv`]. +/// Future returned by [`Channel::receive`] and [`Receiver::receive`]. #[must_use = "futures do nothing unless you `.await` or poll them"] -pub struct RecvFuture<'ch, M, T, const N: usize> +pub struct ReceiveFuture<'ch, M, T, const N: usize> where M: RawMutex, { channel: &'ch Channel, } -impl<'ch, M, T, const N: usize> Future for RecvFuture<'ch, M, T, N> +impl<'ch, M, T, const N: usize> Future for ReceiveFuture<'ch, M, T, N> where M: RawMutex, { @@ -246,19 +246,19 @@ where } } -/// Future returned by [`DynamicReceiver::recv`]. +/// Future returned by [`DynamicReceiver::receive`]. #[must_use = "futures do nothing unless you `.await` or poll them"] -pub struct DynamicRecvFuture<'ch, T> { +pub struct DynamicReceiveFuture<'ch, T> { channel: &'ch dyn DynamicChannel, } -impl<'ch, T> Future for DynamicRecvFuture<'ch, T> { +impl<'ch, T> Future for DynamicReceiveFuture<'ch, T> { type Output = T; fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { - match self.channel.try_recv_with_context(Some(cx)) { + match self.channel.try_receive_with_context(Some(cx)) { Ok(v) => Poll::Ready(v), - Err(TryRecvError::Empty) => Poll::Pending, + Err(TryReceiveError::Empty) => Poll::Pending, } } } @@ -324,7 +324,7 @@ impl<'ch, T> Unpin for DynamicSendFuture<'ch, T> {} trait DynamicChannel { fn try_send_with_context(&self, message: T, cx: Option<&mut Context<'_>>) -> Result<(), TrySendError>; - fn try_recv_with_context(&self, cx: Option<&mut Context<'_>>) -> Result; + fn try_receive_with_context(&self, cx: Option<&mut Context<'_>>) -> Result; fn poll_ready_to_send(&self, cx: &mut Context<'_>) -> Poll<()>; fn poll_ready_to_receive(&self, cx: &mut Context<'_>) -> Poll<()>; @@ -332,10 +332,10 @@ trait DynamicChannel { fn poll_receive(&self, cx: &mut Context<'_>) -> Poll; } -/// Error returned by [`try_recv`](Channel::try_recv). +/// Error returned by [`try_receive`](Channel::try_receive). #[derive(PartialEq, Eq, Clone, Copy, Debug)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] -pub enum TryRecvError { +pub enum TryReceiveError { /// A message could not be received because the channel is empty. Empty, } @@ -364,11 +364,11 @@ impl ChannelState { } } - fn try_recv(&mut self) -> Result { - self.try_recv_with_context(None) + fn try_receive(&mut self) -> Result { + self.try_receive_with_context(None) } - fn try_recv_with_context(&mut self, cx: Option<&mut Context<'_>>) -> Result { + fn try_receive_with_context(&mut self, cx: Option<&mut Context<'_>>) -> Result { if self.queue.is_full() { self.senders_waker.wake(); } @@ -379,7 +379,7 @@ impl ChannelState { if let Some(cx) = cx { self.receiver_waker.register(cx.waker()); } - Err(TryRecvError::Empty) + Err(TryReceiveError::Empty) } } @@ -474,8 +474,8 @@ where self.inner.lock(|rc| f(&mut *rc.borrow_mut())) } - fn try_recv_with_context(&self, cx: Option<&mut Context<'_>>) -> Result { - self.lock(|c| c.try_recv_with_context(cx)) + fn try_receive_with_context(&self, cx: Option<&mut Context<'_>>) -> Result { + self.lock(|c| c.try_receive_with_context(cx)) } /// Poll the channel for the next message @@ -536,16 +536,16 @@ where /// /// If there are no messages in the channel's buffer, this method will /// wait until a message is sent. - pub fn recv(&self) -> RecvFuture<'_, M, T, N> { - RecvFuture { channel: self } + pub fn receive(&self) -> ReceiveFuture<'_, M, T, N> { + ReceiveFuture { channel: self } } /// Attempt to immediately receive a message. /// /// This method will either receive a message from the channel immediately or return an error /// if the channel is empty. - pub fn try_recv(&self) -> Result { - self.lock(|c| c.try_recv()) + pub fn try_receive(&self) -> Result { + self.lock(|c| c.try_receive()) } } @@ -559,8 +559,8 @@ where Channel::try_send_with_context(self, m, cx) } - fn try_recv_with_context(&self, cx: Option<&mut Context<'_>>) -> Result { - Channel::try_recv_with_context(self, cx) + fn try_receive_with_context(&self, cx: Option<&mut Context<'_>>) -> Result { + Channel::try_receive_with_context(self, cx) } fn poll_ready_to_send(&self, cx: &mut Context<'_>) -> Poll<()> { @@ -616,15 +616,15 @@ mod tests { fn receiving_once_with_one_send() { let mut c = ChannelState::::new(); assert!(c.try_send(1).is_ok()); - assert_eq!(c.try_recv().unwrap(), 1); + assert_eq!(c.try_receive().unwrap(), 1); assert_eq!(capacity(&c), 3); } #[test] fn receiving_when_empty() { let mut c = ChannelState::::new(); - match c.try_recv() { - Err(TryRecvError::Empty) => assert!(true), + match c.try_receive() { + Err(TryReceiveError::Empty) => assert!(true), _ => assert!(false), } assert_eq!(capacity(&c), 3); @@ -634,7 +634,7 @@ mod tests { fn simple_send_and_receive() { let c = Channel::::new(); assert!(c.try_send(1).is_ok()); - assert_eq!(c.try_recv().unwrap(), 1); + assert_eq!(c.try_receive().unwrap(), 1); } #[test] @@ -654,7 +654,7 @@ mod tests { let r: DynamicReceiver<'_, u32> = c.receiver().into(); assert!(s.try_send(1).is_ok()); - assert_eq!(r.try_recv().unwrap(), 1); + assert_eq!(r.try_receive().unwrap(), 1); } #[futures_test::test] @@ -669,14 +669,14 @@ mod tests { assert!(c2.try_send(1).is_ok()); }) .is_ok()); - assert_eq!(c.recv().await, 1); + assert_eq!(c.receive().await, 1); } #[futures_test::test] async fn sender_send_completes_if_capacity() { let c = Channel::::new(); c.send(1).await; - assert_eq!(c.recv().await, 1); + assert_eq!(c.receive().await, 1); } #[futures_test::test] @@ -694,11 +694,11 @@ mod tests { // Wish I could think of a means of determining that the async send is waiting instead. // However, I've used the debugger to observe that the send does indeed wait. Delay::new(Duration::from_millis(500)).await; - assert_eq!(c.recv().await, 1); + assert_eq!(c.receive().await, 1); assert!(executor .spawn(async move { loop { - c.recv().await; + c.receive().await; } }) .is_ok()); diff --git a/examples/nrf52840/src/bin/channel.rs b/examples/nrf52840/src/bin/channel.rs index d782a79e..bd9c909d 100644 --- a/examples/nrf52840/src/bin/channel.rs +++ b/examples/nrf52840/src/bin/channel.rs @@ -35,7 +35,7 @@ async fn main(spawner: Spawner) { unwrap!(spawner.spawn(my_task())); loop { - match CHANNEL.recv().await { + match CHANNEL.receive().await { LedState::On => led.set_high(), LedState::Off => led.set_low(), } diff --git a/examples/nrf52840/src/bin/channel_sender_receiver.rs b/examples/nrf52840/src/bin/channel_sender_receiver.rs index fcccdaed..ec4f1d80 100644 --- a/examples/nrf52840/src/bin/channel_sender_receiver.rs +++ b/examples/nrf52840/src/bin/channel_sender_receiver.rs @@ -33,7 +33,7 @@ async fn recv_task(led: AnyPin, receiver: Receiver<'static, NoopRawMutex, LedSta let mut led = Output::new(led, Level::Low, OutputDrive::Standard); loop { - match receiver.recv().await { + match receiver.receive().await { LedState::On => led.set_high(), LedState::Off => led.set_low(), } diff --git a/examples/nrf52840/src/bin/uart_split.rs b/examples/nrf52840/src/bin/uart_split.rs index 9979a1d5..b748bfcd 100644 --- a/examples/nrf52840/src/bin/uart_split.rs +++ b/examples/nrf52840/src/bin/uart_split.rs @@ -46,7 +46,7 @@ async fn main(spawner: Spawner) { // back out the buffer we receive from the read // task. loop { - let buf = CHANNEL.recv().await; + let buf = CHANNEL.receive().await; info!("writing..."); unwrap!(tx.write(&buf).await); } diff --git a/examples/rp/src/bin/lora_p2p_send_multicore.rs b/examples/rp/src/bin/lora_p2p_send_multicore.rs index 89a62818..b54cc92f 100644 --- a/examples/rp/src/bin/lora_p2p_send_multicore.rs +++ b/examples/rp/src/bin/lora_p2p_send_multicore.rs @@ -113,7 +113,7 @@ async fn core1_task( }; loop { - let buffer: [u8; 3] = CHANNEL.recv().await; + let buffer: [u8; 3] = CHANNEL.receive().await; match lora.prepare_for_tx(&mdltn_params, 20, false).await { Ok(()) => {} Err(err) => { diff --git a/examples/rp/src/bin/multicore.rs b/examples/rp/src/bin/multicore.rs index 893b724b..bf017f6a 100644 --- a/examples/rp/src/bin/multicore.rs +++ b/examples/rp/src/bin/multicore.rs @@ -56,7 +56,7 @@ async fn core0_task() { async fn core1_task(mut led: Output<'static, PIN_25>) { info!("Hello from core 1"); loop { - match CHANNEL.recv().await { + match CHANNEL.receive().await { LedState::On => led.set_high(), LedState::Off => led.set_low(), } diff --git a/examples/stm32f3/src/bin/button_events.rs b/examples/stm32f3/src/bin/button_events.rs index 02c475f6..8e97e85e 100644 --- a/examples/stm32f3/src/bin/button_events.rs +++ b/examples/stm32f3/src/bin/button_events.rs @@ -49,12 +49,12 @@ impl<'a> Leds<'a> { async fn show(&mut self) { self.leds[self.current_led].set_high(); - if let Ok(new_message) = with_timeout(Duration::from_millis(500), CHANNEL.recv()).await { + if let Ok(new_message) = with_timeout(Duration::from_millis(500), CHANNEL.receive()).await { self.leds[self.current_led].set_low(); self.process_event(new_message).await; } else { self.leds[self.current_led].set_low(); - if let Ok(new_message) = with_timeout(Duration::from_millis(200), CHANNEL.recv()).await { + if let Ok(new_message) = with_timeout(Duration::from_millis(200), CHANNEL.receive()).await { self.process_event(new_message).await; } } diff --git a/examples/stm32h5/src/bin/usart_split.rs b/examples/stm32h5/src/bin/usart_split.rs index debd6f45..a6b2e690 100644 --- a/examples/stm32h5/src/bin/usart_split.rs +++ b/examples/stm32h5/src/bin/usart_split.rs @@ -44,7 +44,7 @@ async fn main(spawner: Spawner) -> ! { unwrap!(spawner.spawn(reader(rx))); loop { - let buf = CHANNEL.recv().await; + let buf = CHANNEL.receive().await; info!("writing..."); unwrap!(tx.write(&buf).await); } diff --git a/examples/stm32h7/src/bin/usart_split.rs b/examples/stm32h7/src/bin/usart_split.rs index 330d1ce0..aa075345 100644 --- a/examples/stm32h7/src/bin/usart_split.rs +++ b/examples/stm32h7/src/bin/usart_split.rs @@ -44,7 +44,7 @@ async fn main(spawner: Spawner) -> ! { unwrap!(spawner.spawn(reader(rx))); loop { - let buf = CHANNEL.recv().await; + let buf = CHANNEL.receive().await; info!("writing..."); unwrap!(tx.write(&buf).await); } diff --git a/tests/rp/src/bin/gpio_multicore.rs b/tests/rp/src/bin/gpio_multicore.rs index 780112bc..611cecb7 100644 --- a/tests/rp/src/bin/gpio_multicore.rs +++ b/tests/rp/src/bin/gpio_multicore.rs @@ -38,11 +38,11 @@ async fn core0_task(p: PIN_0) { let mut pin = Output::new(p, Level::Low); CHANNEL0.send(()).await; - CHANNEL1.recv().await; + CHANNEL1.receive().await; pin.set_high(); - CHANNEL1.recv().await; + CHANNEL1.receive().await; info!("Test OK"); cortex_m::asm::bkpt(); @@ -52,7 +52,7 @@ async fn core0_task(p: PIN_0) { async fn core1_task(p: PIN_1) { info!("CORE1 is running"); - CHANNEL0.recv().await; + CHANNEL0.receive().await; let mut pin = Input::new(p, Pull::Down); let wait = pin.wait_for_rising_edge(); diff --git a/tests/rp/src/bin/multicore.rs b/tests/rp/src/bin/multicore.rs index 114889de..c4579e5b 100644 --- a/tests/rp/src/bin/multicore.rs +++ b/tests/rp/src/bin/multicore.rs @@ -34,7 +34,7 @@ async fn core0_task() { info!("CORE0 is running"); let ping = true; CHANNEL0.send(ping).await; - let pong = CHANNEL1.recv().await; + let pong = CHANNEL1.receive().await; assert_eq!(ping, pong); info!("Test OK"); @@ -44,6 +44,6 @@ async fn core0_task() { #[embassy_executor::task] async fn core1_task() { info!("CORE1 is running"); - let ping = CHANNEL0.recv().await; + let ping = CHANNEL0.receive().await; CHANNEL1.send(ping).await; } From a5484cd119293967d1d1c663ee2e2ee3a5827e3d Mon Sep 17 00:00:00 2001 From: Dion Dokter Date: Tue, 22 Aug 2023 20:52:02 +0200 Subject: [PATCH 020/106] Modified the brr calculation to be fully 32-bit --- embassy-stm32/src/usart/mod.rs | 46 +++++++++++++++++++++------------- 1 file changed, 29 insertions(+), 17 deletions(-) diff --git a/embassy-stm32/src/usart/mod.rs b/embassy-stm32/src/usart/mod.rs index e203336e..255ddfd4 100644 --- a/embassy-stm32/src/usart/mod.rs +++ b/embassy-stm32/src/usart/mod.rs @@ -809,45 +809,57 @@ fn configure(r: Regs, config: &Config, pclk_freq: Hertz, kind: Kind, enable_rx: Kind::Uart => (1, 0x10, 0x1_0000), }; + fn calculate_brr(baud: u32, pclk: u32, presc: u32, mul: u32) -> u32 { + // The calculation to be done to get the BRR is `mul * pclk / presc / baud` + // To do this in 32-bit only we can't multiply `mul` and `pclk` + let clock = pclk / presc; + + // The mul is applied as the last operation to prevent overflow + let brr = clock / baud * mul; + + // The BRR calculation will be a bit off because of integer rounding. + // Because we multiplied our inaccuracy with mul, our rounding now needs to be in proportion to mul. + let rounding = ((clock % baud) * mul + (baud / 2)) / baud; + + brr + rounding + } + #[cfg(not(usart_v1))] let mut over8 = false; - let mut found = None; + let mut found_brr = None; for &(presc, _presc_val) in &DIVS { - let denom = (config.baudrate * presc as u32) as u64; - let div = (pclk_freq.0 as u64 * mul + (denom / 2)) / denom; + let brr = calculate_brr(config.baudrate, pclk_freq.0, presc as u32, mul); trace!( "USART: presc={}, div=0x{:08x} (mantissa = {}, fraction = {})", presc, - div, - div >> 4, - div & 0x0F + brr, + brr >> 4, + brr & 0x0F ); - if div < brr_min { + if brr < brr_min { #[cfg(not(usart_v1))] - if div * 2 >= brr_min && kind == Kind::Uart && !cfg!(usart_v1) { + if brr * 2 >= brr_min && kind == Kind::Uart && !cfg!(usart_v1) { over8 = true; - let div = div as u32; - r.brr().write_value(regs::Brr(((div << 1) & !0xF) | (div & 0x07))); + r.brr().write_value(regs::Brr(((brr << 1) & !0xF) | (brr & 0x07))); #[cfg(usart_v4)] r.presc().write(|w| w.set_prescaler(_presc_val)); - found = Some(div); + found_brr = Some(brr); break; } panic!("USART: baudrate too high"); } - if div < brr_max { - let div = div as u32; - r.brr().write_value(regs::Brr(div)); + if brr < brr_max { + r.brr().write_value(regs::Brr(brr)); #[cfg(usart_v4)] r.presc().write(|w| w.set_prescaler(_presc_val)); - found = Some(div); + found_brr = Some(brr); break; } } - let div = found.expect("USART: baudrate too low"); + let brr = found_brr.expect("USART: baudrate too low"); #[cfg(not(usart_v1))] let oversampling = if over8 { "8 bit" } else { "16 bit" }; @@ -857,7 +869,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 * mul as u32) / div + pclk_freq.0 / brr * mul ); r.cr2().write(|w| { From 048bdf6968773a642c60ddcac46958d3a54af7c3 Mon Sep 17 00:00:00 2001 From: xoviat Date: Tue, 22 Aug 2023 16:48:08 -0500 Subject: [PATCH 021/106] stm32/rtc: allow dead code --- embassy-stm32/src/rtc/v2.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/embassy-stm32/src/rtc/v2.rs b/embassy-stm32/src/rtc/v2.rs index e9b83123..53d0161d 100644 --- a/embassy-stm32/src/rtc/v2.rs +++ b/embassy-stm32/src/rtc/v2.rs @@ -72,6 +72,7 @@ impl core::ops::Sub for RtcInstant { } } +#[allow(dead_code)] #[derive(Clone, Copy)] pub(crate) enum WakeupPrescaler { Div2, @@ -120,6 +121,7 @@ impl From for u32 { } } +#[allow(dead_code)] impl WakeupPrescaler { pub fn compute_min(val: u32) -> Self { *[ From 9e3266b74554ea397bdd963ff12a26aa51e77b63 Mon Sep 17 00:00:00 2001 From: xoviat Date: Tue, 22 Aug 2023 16:58:19 -0500 Subject: [PATCH 022/106] rtc: make fns private --- embassy-stm32/src/rtc/v2.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/embassy-stm32/src/rtc/v2.rs b/embassy-stm32/src/rtc/v2.rs index e9b83123..4a166e19 100644 --- a/embassy-stm32/src/rtc/v2.rs +++ b/embassy-stm32/src/rtc/v2.rs @@ -160,7 +160,7 @@ impl super::Rtc { /// /// note: this api is exposed for testing purposes until low power is implemented. /// it is not intended to be public - pub fn start_wakeup_alarm(requested_duration: embassy_time::Duration) -> RtcInstant { + pub(crate) fn start_wakeup_alarm(requested_duration: embassy_time::Duration) -> RtcInstant { use embassy_time::{Duration, TICK_HZ}; use crate::interrupt::typelevel::Interrupt; @@ -215,7 +215,7 @@ impl super::Rtc { /// /// note: this api is exposed for testing purposes until low power is implemented. /// it is not intended to be public - pub fn stop_wakeup_alarm() -> RtcInstant { + pub(crate) fn stop_wakeup_alarm() -> RtcInstant { use crate::interrupt::typelevel::Interrupt; crate::interrupt::typelevel::RTC_WKUP::disable(); From 6d35bcc3d9818c3380e0d7071c78275b50856c90 Mon Sep 17 00:00:00 2001 From: xoviat Date: Tue, 22 Aug 2023 17:00:00 -0500 Subject: [PATCH 023/106] stm32: add low-power mod --- embassy-stm32/Cargo.toml | 3 ++- embassy-stm32/src/lib.rs | 2 ++ embassy-stm32/src/low_power.rs | 15 +++++++++++++++ 3 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 embassy-stm32/src/low_power.rs diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index fe5dc443..828414f2 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml @@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0" src_base = "https://github.com/embassy-rs/embassy/blob/embassy-stm32-v$VERSION/embassy-stm32/src/" src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-stm32/src/" -features = ["nightly", "defmt", "unstable-pac", "unstable-traits", "exti", "time-driver-any", "time"] +features = ["nightly", "defmt", "unstable-pac", "unstable-traits", "exti", "time-driver-any", "time", "low-power"] flavors = [ { regex_feature = "stm32f0.*", target = "thumbv6m-none-eabi" }, { regex_feature = "stm32f1.*", target = "thumbv7m-none-eabi" }, @@ -88,6 +88,7 @@ rt = ["stm32-metapac/rt"] defmt = ["dep:defmt", "bxcan/unstable-defmt", "embassy-sync/defmt", "embassy-embedded-hal/defmt", "embassy-hal-internal/defmt", "embedded-io-async?/defmt-03", "embassy-usb-driver?/defmt", "embassy-net-driver/defmt", "embassy-time?/defmt"] exti = [] +low-power = [] ## Automatically generate `memory.x` file using [`stm32-metapac`](https://docs.rs/stm32-metapac/) memory-x = ["stm32-metapac/memory-x"] diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs index adb3054d..8c87ea7d 100644 --- a/embassy-stm32/src/lib.rs +++ b/embassy-stm32/src/lib.rs @@ -47,6 +47,8 @@ pub mod i2c; pub mod i2s; #[cfg(stm32wb)] pub mod ipcc; +#[cfg(feature = "low-power")] +pub mod low_power; #[cfg(quadspi)] pub mod qspi; #[cfg(rng)] diff --git a/embassy-stm32/src/low_power.rs b/embassy-stm32/src/low_power.rs new file mode 100644 index 00000000..ddcfbbb1 --- /dev/null +++ b/embassy-stm32/src/low_power.rs @@ -0,0 +1,15 @@ +use crate::rtc::{Rtc, RtcInstant}; + +static mut RTC: Option<&'static Rtc> = None; + +pub fn stop_with_rtc(rtc: &'static Rtc) { + unsafe { RTC = Some(rtc) }; +} + +pub fn start_wakeup_alarm(requested_duration: embassy_time::Duration) -> RtcInstant { + unsafe { RTC }.unwrap().start_wakeup_alarm(requested_duration) +} + +pub fn stop_wakeup_alarm() -> RtcInstant { + unsafe { RTC }.unwrap().stop_wakeup_alarm() +} From faab2d0d53d52f7f311d3958e7e72dd1ee66c3b7 Mon Sep 17 00:00:00 2001 From: xoviat Date: Tue, 22 Aug 2023 17:31:40 -0500 Subject: [PATCH 024/106] stm32: add executor to low-power mod --- embassy-stm32/Cargo.toml | 4 ++- embassy-stm32/src/low_power.rs | 66 ++++++++++++++++++++++++++++++++++ embassy-stm32/src/rtc/v2.rs | 4 +-- 3 files changed, 71 insertions(+), 3 deletions(-) diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index 828414f2..048d231d 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml @@ -38,6 +38,7 @@ embassy-hal-internal = {version = "0.1.0", path = "../embassy-hal-internal", fea embassy-embedded-hal = {version = "0.1.0", path = "../embassy-embedded-hal" } embassy-net-driver = { version = "0.1.0", path = "../embassy-net-driver" } embassy-usb-driver = {version = "0.1.0", path = "../embassy-usb-driver", optional = true } +embassy-executor = { version = "0.2.0", path = "../embassy-executor", optional = true } embedded-hal-02 = { package = "embedded-hal", version = "0.2.6", features = ["unproven"] } embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-rc.1", optional = true} @@ -88,7 +89,8 @@ rt = ["stm32-metapac/rt"] defmt = ["dep:defmt", "bxcan/unstable-defmt", "embassy-sync/defmt", "embassy-embedded-hal/defmt", "embassy-hal-internal/defmt", "embedded-io-async?/defmt-03", "embassy-usb-driver?/defmt", "embassy-net-driver/defmt", "embassy-time?/defmt"] exti = [] -low-power = [] +low-power = [ "dep:embassy-executor", "embassy-executor/arch-cortex-m" ] +embassy-executor = [] ## Automatically generate `memory.x` file using [`stm32-metapac`](https://docs.rs/stm32-metapac/) memory-x = ["stm32-metapac/memory-x"] diff --git a/embassy-stm32/src/low_power.rs b/embassy-stm32/src/low_power.rs index ddcfbbb1..3fe28b9d 100644 --- a/embassy-stm32/src/low_power.rs +++ b/embassy-stm32/src/low_power.rs @@ -1,3 +1,10 @@ +use core::arch::asm; +use core::marker::PhantomData; + +use embassy_executor::*; + +const THREAD_PENDER: usize = usize::MAX; + use crate::rtc::{Rtc, RtcInstant}; static mut RTC: Option<&'static Rtc> = None; @@ -13,3 +20,62 @@ pub fn start_wakeup_alarm(requested_duration: embassy_time::Duration) -> RtcInst pub fn stop_wakeup_alarm() -> RtcInstant { unsafe { RTC }.unwrap().stop_wakeup_alarm() } + +/// Thread mode executor, using WFE/SEV. +/// +/// This is the simplest and most common kind of executor. It runs on +/// thread mode (at the lowest priority level), and uses the `WFE` ARM instruction +/// to sleep when it has no more work to do. When a task is woken, a `SEV` instruction +/// is executed, to make the `WFE` exit from sleep and poll the task. +/// +/// This executor allows for ultra low power consumption for chips where `WFE` +/// triggers low-power sleep without extra steps. If your chip requires extra steps, +/// you may use [`raw::Executor`] directly to program custom behavior. +pub struct Executor { + inner: raw::Executor, + not_send: PhantomData<*mut ()>, +} + +impl Executor { + /// Create a new Executor. + pub fn new() -> Self { + Self { + inner: raw::Executor::new(THREAD_PENDER as *mut ()), + not_send: PhantomData, + } + } + + fn configure_power(&self) { + todo!() + } + + /// Run the executor. + /// + /// The `init` closure is called with a [`Spawner`] that spawns tasks on + /// this executor. Use it to spawn the initial task(s). After `init` returns, + /// the executor starts running the tasks. + /// + /// To spawn more tasks later, you may keep copies of the [`Spawner`] (it is `Copy`), + /// for example by passing it as an argument to the initial tasks. + /// + /// This function requires `&'static mut self`. This means you have to store the + /// Executor instance in a place where it'll live forever and grants you mutable + /// access. There's a few ways to do this: + /// + /// - a [StaticCell](https://docs.rs/static_cell/latest/static_cell/) (safe) + /// - a `static mut` (unsafe) + /// - a local variable in a function you know never returns (like `fn main() -> !`), upgrading its lifetime with `transmute`. (unsafe) + /// + /// This function never returns. + pub fn run(&'static mut self, init: impl FnOnce(Spawner)) -> ! { + init(self.inner.spawner()); + + loop { + unsafe { + self.inner.poll(); + self.configure_power(); + asm!("wfe"); + }; + } + } +} diff --git a/embassy-stm32/src/rtc/v2.rs b/embassy-stm32/src/rtc/v2.rs index 744e9a11..f6565a72 100644 --- a/embassy-stm32/src/rtc/v2.rs +++ b/embassy-stm32/src/rtc/v2.rs @@ -162,7 +162,7 @@ impl super::Rtc { /// /// note: this api is exposed for testing purposes until low power is implemented. /// it is not intended to be public - pub(crate) fn start_wakeup_alarm(requested_duration: embassy_time::Duration) -> RtcInstant { + pub(crate) fn start_wakeup_alarm(&self, requested_duration: embassy_time::Duration) -> RtcInstant { use embassy_time::{Duration, TICK_HZ}; use crate::interrupt::typelevel::Interrupt; @@ -217,7 +217,7 @@ impl super::Rtc { /// /// note: this api is exposed for testing purposes until low power is implemented. /// it is not intended to be public - pub(crate) fn stop_wakeup_alarm() -> RtcInstant { + pub(crate) fn stop_wakeup_alarm(&self) -> RtcInstant { use crate::interrupt::typelevel::Interrupt; crate::interrupt::typelevel::RTC_WKUP::disable(); From 1ea4c58c39d831408d7584be3f37b9f2d880d4ca Mon Sep 17 00:00:00 2001 From: xoviat Date: Tue, 22 Aug 2023 20:00:00 -0500 Subject: [PATCH 025/106] stm32: impl. draft cfgr pwr --- embassy-stm32/src/low_power.rs | 63 ++++++++++++++++++++++++++++++++-- embassy-stm32/src/rtc/v2.rs | 8 ----- 2 files changed, 60 insertions(+), 11 deletions(-) diff --git a/embassy-stm32/src/low_power.rs b/embassy-stm32/src/low_power.rs index 3fe28b9d..7d5093b6 100644 --- a/embassy-stm32/src/low_power.rs +++ b/embassy-stm32/src/low_power.rs @@ -1,15 +1,33 @@ use core::arch::asm; use core::marker::PhantomData; +use cortex_m::peripheral::SCB; use embassy_executor::*; +use embassy_time::Duration; + +use crate::interrupt; +use crate::interrupt::typelevel::Interrupt; const THREAD_PENDER: usize = usize::MAX; +const THRESHOLD: Duration = Duration::from_millis(500); use crate::rtc::{Rtc, RtcInstant}; static mut RTC: Option<&'static Rtc> = None; +foreach_interrupt! { + (RTC, rtc, $block:ident, WKUP, $irq:ident) => { + #[interrupt] + unsafe fn $irq() { + Executor::on_wakeup_irq(); + } + }; +} + pub fn stop_with_rtc(rtc: &'static Rtc) { + crate::interrupt::typelevel::RTC_WKUP::unpend(); + unsafe { crate::interrupt::typelevel::RTC_WKUP::enable() }; + unsafe { RTC = Some(rtc) }; } @@ -45,8 +63,47 @@ impl Executor { } } - fn configure_power(&self) { - todo!() + unsafe fn on_wakeup_irq() { + info!("on wakeup irq"); + + cortex_m::asm::bkpt(); + } + + fn low_power_ready(&self) -> bool { + true + } + + fn time_until_next_alarm(&self) -> Duration { + Duration::from_secs(3) + } + + fn get_scb(&self) -> SCB { + unsafe { cortex_m::Peripherals::steal() }.SCB + } + + fn configure_pwr(&self) { + trace!("low power before wfe"); + + if !self.low_power_ready() { + return; + } + + let time_until_next_alarm = self.time_until_next_alarm(); + if time_until_next_alarm < THRESHOLD { + return; + } + + trace!("low power stop required"); + + critical_section::with(|_| { + trace!("executor: set wakeup alarm..."); + + start_wakeup_alarm(time_until_next_alarm); + + trace!("low power wait for rtc ready..."); + + self.get_scb().set_sleepdeep(); + }); } /// Run the executor. @@ -73,7 +130,7 @@ impl Executor { loop { unsafe { self.inner.poll(); - self.configure_power(); + self.configure_pwr(); asm!("wfe"); }; } diff --git a/embassy-stm32/src/rtc/v2.rs b/embassy-stm32/src/rtc/v2.rs index f6565a72..e03c7d2a 100644 --- a/embassy-stm32/src/rtc/v2.rs +++ b/embassy-stm32/src/rtc/v2.rs @@ -165,7 +165,6 @@ impl super::Rtc { pub(crate) fn start_wakeup_alarm(&self, requested_duration: embassy_time::Duration) -> RtcInstant { use embassy_time::{Duration, TICK_HZ}; - use crate::interrupt::typelevel::Interrupt; use crate::rcc::get_freqs; let rtc_hz = unsafe { get_freqs() }.rtc.unwrap().0 as u64; @@ -205,9 +204,6 @@ impl super::Rtc { trace!("wakeup timer enabled"); } - crate::interrupt::typelevel::RTC_WKUP::unpend(); - unsafe { crate::interrupt::typelevel::RTC_WKUP::enable() }; - RtcInstant::now() } @@ -218,10 +214,6 @@ impl super::Rtc { /// note: this api is exposed for testing purposes until low power is implemented. /// it is not intended to be public pub(crate) fn stop_wakeup_alarm(&self) -> RtcInstant { - use crate::interrupt::typelevel::Interrupt; - - crate::interrupt::typelevel::RTC_WKUP::disable(); - trace!("disable wakeup timer..."); RTC::regs().cr().modify(|w| { From a6d22e199aa2fe7e76bffa104911d954151a03ef Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Wed, 23 Aug 2023 11:37:50 +0200 Subject: [PATCH 026/106] net-esp-hosted: fix set link down on disconnect. --- embassy-net-esp-hosted/src/control.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/embassy-net-esp-hosted/src/control.rs b/embassy-net-esp-hosted/src/control.rs index b8026611..ce6636a8 100644 --- a/embassy-net-esp-hosted/src/control.rs +++ b/embassy-net-esp-hosted/src/control.rs @@ -82,7 +82,7 @@ impl<'a> Control<'a> { pub async fn disconnect(&mut self) -> Result<(), Error> { let req = proto::CtrlMsgReqGetStatus {}; ioctl!(self, ReqDisconnectAp, RespDisconnectAp, req, resp); - self.state_ch.set_link_state(LinkState::Up); + self.state_ch.set_link_state(LinkState::Down); Ok(()) } From a2c718f61c0587e19d10c5c86ff4cd79272e2b87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Buga?= Date: Wed, 23 Aug 2023 20:34:37 +0200 Subject: [PATCH 027/106] Bump executor crate version to 0.3.0 --- docs/modules/ROOT/examples/basic/Cargo.toml | 2 +- .../ROOT/examples/layer-by-layer/blinky-async/Cargo.toml | 2 +- embassy-executor/CHANGELOG.md | 2 +- embassy-executor/Cargo.toml | 2 +- embassy-rp/Cargo.toml | 2 +- embassy-time/Cargo.toml | 2 +- examples/boot/application/nrf/Cargo.toml | 2 +- examples/boot/application/rp/Cargo.toml | 2 +- examples/boot/application/stm32f3/Cargo.toml | 2 +- examples/boot/application/stm32f7/Cargo.toml | 2 +- examples/boot/application/stm32h7/Cargo.toml | 2 +- examples/boot/application/stm32l0/Cargo.toml | 2 +- examples/boot/application/stm32l1/Cargo.toml | 2 +- examples/boot/application/stm32l4/Cargo.toml | 2 +- examples/boot/application/stm32wl/Cargo.toml | 2 +- examples/nrf-rtos-trace/Cargo.toml | 2 +- examples/nrf52840/Cargo.toml | 2 +- examples/nrf5340/Cargo.toml | 2 +- examples/rp/Cargo.toml | 2 +- examples/std/Cargo.toml | 2 +- examples/stm32c0/Cargo.toml | 2 +- examples/stm32f0/Cargo.toml | 2 +- examples/stm32f1/Cargo.toml | 2 +- examples/stm32f2/Cargo.toml | 2 +- examples/stm32f3/Cargo.toml | 2 +- examples/stm32f334/Cargo.toml | 2 +- examples/stm32f4/Cargo.toml | 2 +- examples/stm32f7/Cargo.toml | 2 +- examples/stm32g0/Cargo.toml | 2 +- examples/stm32g4/Cargo.toml | 2 +- examples/stm32h5/Cargo.toml | 2 +- examples/stm32h7/Cargo.toml | 2 +- examples/stm32l0/Cargo.toml | 2 +- examples/stm32l1/Cargo.toml | 2 +- examples/stm32l4/Cargo.toml | 2 +- examples/stm32l5/Cargo.toml | 2 +- examples/stm32u5/Cargo.toml | 2 +- examples/stm32wb/Cargo.toml | 2 +- examples/stm32wl/Cargo.toml | 2 +- examples/wasm/Cargo.toml | 2 +- tests/nrf/Cargo.toml | 2 +- tests/riscv32/Cargo.toml | 2 +- tests/rp/Cargo.toml | 2 +- tests/stm32/Cargo.toml | 2 +- 44 files changed, 44 insertions(+), 44 deletions(-) diff --git a/docs/modules/ROOT/examples/basic/Cargo.toml b/docs/modules/ROOT/examples/basic/Cargo.toml index 237ae0ac..e94358a9 100644 --- a/docs/modules/ROOT/examples/basic/Cargo.toml +++ b/docs/modules/ROOT/examples/basic/Cargo.toml @@ -6,7 +6,7 @@ version = "0.1.0" license = "MIT OR Apache-2.0" [dependencies] -embassy-executor = { version = "0.2.0", path = "../../../../../embassy-executor", features = ["defmt", "nightly", "integrated-timers", "arch-cortex-m", "executor-thread"] } +embassy-executor = { version = "0.3.0", path = "../../../../../embassy-executor", features = ["defmt", "nightly", "integrated-timers", "arch-cortex-m", "executor-thread"] } embassy-time = { version = "0.1.0", path = "../../../../../embassy-time", features = ["defmt", "nightly"] } embassy-nrf = { version = "0.1.0", path = "../../../../../embassy-nrf", features = ["defmt", "nrf52840", "time-driver-rtc1", "gpiote", "nightly"] } diff --git a/docs/modules/ROOT/examples/layer-by-layer/blinky-async/Cargo.toml b/docs/modules/ROOT/examples/layer-by-layer/blinky-async/Cargo.toml index a7236ed5..b39f02ae 100644 --- a/docs/modules/ROOT/examples/layer-by-layer/blinky-async/Cargo.toml +++ b/docs/modules/ROOT/examples/layer-by-layer/blinky-async/Cargo.toml @@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0" cortex-m = "0.7" cortex-m-rt = "0.7" embassy-stm32 = { version = "0.1.0", features = ["stm32l475vg", "memory-x", "exti"] } -embassy-executor = { version = "0.2.0", features = ["nightly", "arch-cortex-m", "executor-thread"] } +embassy-executor = { version = "0.3.0", features = ["nightly", "arch-cortex-m", "executor-thread"] } defmt = "0.3.0" defmt-rtt = "0.3.0" diff --git a/embassy-executor/CHANGELOG.md b/embassy-executor/CHANGELOG.md index 43d94e54..4853ba29 100644 --- a/embassy-executor/CHANGELOG.md +++ b/embassy-executor/CHANGELOG.md @@ -5,7 +5,7 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## Unreleased +## 0.3.0 - TBD - Replaced Pender. Implementations now must define an extern function called `__pender`. - Made `raw::AvailableTask` public diff --git a/embassy-executor/Cargo.toml b/embassy-executor/Cargo.toml index d190c95a..2a67f70d 100644 --- a/embassy-executor/Cargo.toml +++ b/embassy-executor/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "embassy-executor" -version = "0.2.1" +version = "0.3.0" edition = "2021" license = "MIT OR Apache-2.0" description = "async/await executor designed for embedded usage" diff --git a/embassy-rp/Cargo.toml b/embassy-rp/Cargo.toml index b9ebcc86..60143c2b 100644 --- a/embassy-rp/Cargo.toml +++ b/embassy-rp/Cargo.toml @@ -95,5 +95,5 @@ pio = {version= "0.2.1" } rp2040-boot2 = "0.3" [dev-dependencies] -embassy-executor = { version = "0.2.0", path = "../embassy-executor", features = ["nightly", "arch-std", "executor-thread"] } +embassy-executor = { version = "0.3.0", path = "../embassy-executor", features = ["nightly", "arch-std", "executor-thread"] } static_cell = "1.1" diff --git a/embassy-time/Cargo.toml b/embassy-time/Cargo.toml index ec1f2ec3..00d31d30 100644 --- a/embassy-time/Cargo.toml +++ b/embassy-time/Cargo.toml @@ -169,4 +169,4 @@ wasm-timer = { version = "0.2.5", optional = true } [dev-dependencies] serial_test = "0.9" critical-section = { version = "1.1", features = ["std"] } -embassy-executor = { version = "0.2.0", path = "../embassy-executor", features = ["nightly"] } +embassy-executor = { version = "0.3.0", path = "../embassy-executor", features = ["nightly"] } diff --git a/examples/boot/application/nrf/Cargo.toml b/examples/boot/application/nrf/Cargo.toml index 2a0cf781..46ce7ba9 100644 --- a/examples/boot/application/nrf/Cargo.toml +++ b/examples/boot/application/nrf/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-sync = { version = "0.2.0", path = "../../../../embassy-sync" } -embassy-executor = { version = "0.2.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "nightly", "integrated-timers", "arch-cortex-m", "executor-thread"] } +embassy-executor = { version = "0.3.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "nightly", "integrated-timers", "arch-cortex-m", "executor-thread"] } embassy-time = { version = "0.1.2", path = "../../../../embassy-time", features = ["nightly"] } embassy-nrf = { version = "0.1.0", path = "../../../../embassy-nrf", features = ["time-driver-rtc1", "gpiote", "nightly"] } embassy-boot = { version = "0.1.0", path = "../../../../embassy-boot/boot", features = ["nightly"] } diff --git a/examples/boot/application/rp/Cargo.toml b/examples/boot/application/rp/Cargo.toml index 95b2da95..be85f443 100644 --- a/examples/boot/application/rp/Cargo.toml +++ b/examples/boot/application/rp/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-sync = { version = "0.2.0", path = "../../../../embassy-sync" } -embassy-executor = { version = "0.2.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "nightly", "integrated-timers", "arch-cortex-m", "executor-thread"] } +embassy-executor = { version = "0.3.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "nightly", "integrated-timers", "arch-cortex-m", "executor-thread"] } embassy-time = { version = "0.1.2", path = "../../../../embassy-time", features = ["nightly"] } embassy-rp = { version = "0.1.0", path = "../../../../embassy-rp", features = ["time-driver", "unstable-traits", "nightly"] } embassy-boot-rp = { version = "0.1.0", path = "../../../../embassy-boot/rp", features = ["nightly"] } diff --git a/examples/boot/application/stm32f3/Cargo.toml b/examples/boot/application/stm32f3/Cargo.toml index 3b0fc4d9..ea878933 100644 --- a/examples/boot/application/stm32f3/Cargo.toml +++ b/examples/boot/application/stm32f3/Cargo.toml @@ -6,7 +6,7 @@ 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 = ["arch-cortex-m", "executor-thread", "nightly", "integrated-timers"] } +embassy-executor = { version = "0.3.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "nightly", "integrated-timers"] } embassy-time = { version = "0.1.2", path = "../../../../embassy-time", features = ["nightly", "tick-hz-32_768"] } embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["unstable-traits", "nightly", "stm32f303re", "time-driver-any", "exti"] } embassy-boot-stm32 = { version = "0.1.0", path = "../../../../embassy-boot/stm32", features = ["nightly"] } diff --git a/examples/boot/application/stm32f7/Cargo.toml b/examples/boot/application/stm32f7/Cargo.toml index 323b4ab2..b39bc292 100644 --- a/examples/boot/application/stm32f7/Cargo.toml +++ b/examples/boot/application/stm32f7/Cargo.toml @@ -6,7 +6,7 @@ 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 = ["arch-cortex-m", "executor-thread", "nightly", "integrated-timers"] } +embassy-executor = { version = "0.3.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "nightly", "integrated-timers"] } embassy-time = { version = "0.1.2", path = "../../../../embassy-time", features = ["nightly", "tick-hz-32_768"] } embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["unstable-traits", "nightly", "stm32f767zi", "time-driver-any", "exti"] } embassy-boot-stm32 = { version = "0.1.0", path = "../../../../embassy-boot/stm32", features = ["nightly"] } diff --git a/examples/boot/application/stm32h7/Cargo.toml b/examples/boot/application/stm32h7/Cargo.toml index b2abdc89..f015b2ca 100644 --- a/examples/boot/application/stm32h7/Cargo.toml +++ b/examples/boot/application/stm32h7/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-sync = { version = "0.2.0", path = "../../../../embassy-sync" } -embassy-executor = { version = "0.2.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "nightly", "integrated-timers"] } +embassy-executor = { version = "0.3.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "nightly", "integrated-timers"] } embassy-time = { version = "0.1.2", path = "../../../../embassy-time", features = ["nightly", "tick-hz-32_768"] } embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["unstable-traits", "nightly", "stm32h743zi", "time-driver-any", "exti"] } embassy-boot-stm32 = { version = "0.1.0", path = "../../../../embassy-boot/stm32", features = ["nightly"] } diff --git a/examples/boot/application/stm32l0/Cargo.toml b/examples/boot/application/stm32l0/Cargo.toml index 0b7e72d5..f221e1de 100644 --- a/examples/boot/application/stm32l0/Cargo.toml +++ b/examples/boot/application/stm32l0/Cargo.toml @@ -6,7 +6,7 @@ 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 = ["arch-cortex-m", "executor-thread", "nightly", "integrated-timers"] } +embassy-executor = { version = "0.3.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "nightly", "integrated-timers"] } embassy-time = { version = "0.1.2", path = "../../../../embassy-time", features = ["nightly", "tick-hz-32_768"] } embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["unstable-traits", "nightly", "stm32l072cz", "time-driver-any", "exti", "memory-x"] } embassy-boot-stm32 = { version = "0.1.0", path = "../../../../embassy-boot/stm32", features = ["nightly"] } diff --git a/examples/boot/application/stm32l1/Cargo.toml b/examples/boot/application/stm32l1/Cargo.toml index 5f3f365c..2896afa3 100644 --- a/examples/boot/application/stm32l1/Cargo.toml +++ b/examples/boot/application/stm32l1/Cargo.toml @@ -6,7 +6,7 @@ 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 = ["arch-cortex-m", "executor-thread", "nightly", "integrated-timers"] } +embassy-executor = { version = "0.3.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "nightly", "integrated-timers"] } embassy-time = { version = "0.1.2", path = "../../../../embassy-time", features = ["nightly", "tick-hz-32_768"] } embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["unstable-traits", "nightly", "stm32l151cb-a", "time-driver-any", "exti"] } embassy-boot-stm32 = { version = "0.1.0", path = "../../../../embassy-boot/stm32", features = ["nightly"] } diff --git a/examples/boot/application/stm32l4/Cargo.toml b/examples/boot/application/stm32l4/Cargo.toml index 44eb5aba..50d8967a 100644 --- a/examples/boot/application/stm32l4/Cargo.toml +++ b/examples/boot/application/stm32l4/Cargo.toml @@ -6,7 +6,7 @@ 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 = ["arch-cortex-m", "executor-thread", "nightly", "integrated-timers"] } +embassy-executor = { version = "0.3.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "nightly", "integrated-timers"] } embassy-time = { version = "0.1.2", path = "../../../../embassy-time", features = ["nightly", "tick-hz-32_768"] } embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["unstable-traits", "nightly", "stm32l475vg", "time-driver-any", "exti"] } embassy-boot-stm32 = { version = "0.1.0", path = "../../../../embassy-boot/stm32", features = ["nightly"] } diff --git a/examples/boot/application/stm32wl/Cargo.toml b/examples/boot/application/stm32wl/Cargo.toml index fdad5506..27541439 100644 --- a/examples/boot/application/stm32wl/Cargo.toml +++ b/examples/boot/application/stm32wl/Cargo.toml @@ -6,7 +6,7 @@ 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 = ["arch-cortex-m", "executor-thread", "nightly", "integrated-timers"] } +embassy-executor = { version = "0.3.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "nightly", "integrated-timers"] } embassy-time = { version = "0.1.2", path = "../../../../embassy-time", features = ["nightly", "tick-hz-32_768"] } embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["unstable-traits", "nightly", "stm32wl55jc-cm4", "time-driver-any", "exti"] } embassy-boot-stm32 = { version = "0.1.0", path = "../../../../embassy-boot/stm32", features = ["nightly"] } diff --git a/examples/nrf-rtos-trace/Cargo.toml b/examples/nrf-rtos-trace/Cargo.toml index 068474e7..b06722f5 100644 --- a/examples/nrf-rtos-trace/Cargo.toml +++ b/examples/nrf-rtos-trace/Cargo.toml @@ -17,7 +17,7 @@ log = [ [dependencies] embassy-sync = { version = "0.2.0", path = "../../embassy-sync" } -embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "rtos-trace", "rtos-trace-interrupt", "integrated-timers"] } +embassy-executor = { version = "0.3.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "rtos-trace", "rtos-trace-interrupt", "integrated-timers"] } embassy-time = { version = "0.1.2", path = "../../embassy-time" } embassy-nrf = { version = "0.1.0", path = "../../embassy-nrf", features = ["nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac"] } diff --git a/examples/nrf52840/Cargo.toml b/examples/nrf52840/Cargo.toml index 2ce44b51..1b2f1eb1 100644 --- a/examples/nrf52840/Cargo.toml +++ b/examples/nrf52840/Cargo.toml @@ -30,7 +30,7 @@ nightly = [ [dependencies] embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } 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", "executor-interrupt", "defmt", "integrated-timers"] } +embassy-executor = { version = "0.3.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] } embassy-time = { version = "0.1.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } embassy-nrf = { version = "0.1.0", path = "../../embassy-nrf", features = ["defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } embassy-net = { version = "0.1.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet"], optional = true } diff --git a/examples/nrf5340/Cargo.toml b/examples/nrf5340/Cargo.toml index 57660f12..4968a79a 100644 --- a/examples/nrf5340/Cargo.toml +++ b/examples/nrf5340/Cargo.toml @@ -9,7 +9,7 @@ embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } 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", +embassy-executor = { version = "0.3.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "nightly", "defmt", "integrated-timers", diff --git a/examples/rp/Cargo.toml b/examples/rp/Cargo.toml index 102611bc..3efc804a 100644 --- a/examples/rp/Cargo.toml +++ b/examples/rp/Cargo.toml @@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-embedded-hal = { version = "0.1.0", path = "../../embassy-embedded-hal", features = ["defmt"] } 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-executor = { version = "0.3.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 = ["nightly", "unstable-traits", "defmt", "defmt-timestamp-uptime"] } embassy-rp = { version = "0.1.0", path = "../../embassy-rp", features = ["defmt", "unstable-traits", "nightly", "unstable-pac", "time-driver", "critical-section-impl"] } embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] } diff --git a/examples/std/Cargo.toml b/examples/std/Cargo.toml index 3e26d2e2..0d4d5fa1 100644 --- a/examples/std/Cargo.toml +++ b/examples/std/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["log"] } -embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["arch-std", "executor-thread", "log", "nightly", "integrated-timers"] } +embassy-executor = { version = "0.3.0", path = "../../embassy-executor", features = ["arch-std", "executor-thread", "log", "nightly", "integrated-timers"] } embassy-time = { version = "0.1.2", path = "../../embassy-time", features = ["log", "std", "nightly"] } embassy-net = { version = "0.1.0", path = "../../embassy-net", features=[ "std", "nightly", "log", "medium-ethernet", "tcp", "udp", "dns", "dhcpv4", "proto-ipv6"] } embassy-net-tuntap = { version = "0.1.0", path = "../../embassy-net-tuntap" } diff --git a/examples/stm32c0/Cargo.toml b/examples/stm32c0/Cargo.toml index 8534921a..9d188513 100644 --- a/examples/stm32c0/Cargo.toml +++ b/examples/stm32c0/Cargo.toml @@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0" # 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-executor = { version = "0.3.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"] } defmt = "0.3" diff --git a/examples/stm32f0/Cargo.toml b/examples/stm32f0/Cargo.toml index 46b6db45..ca9ab1cf 100644 --- a/examples/stm32f0/Cargo.toml +++ b/examples/stm32f0/Cargo.toml @@ -15,7 +15,7 @@ defmt = "0.3" defmt-rtt = "0.4" 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-executor = { version = "0.3.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"] } static_cell = { version = "1.1", features = ["nightly"]} diff --git a/examples/stm32f1/Cargo.toml b/examples/stm32f1/Cargo.toml index 5d32992c..16796841 100644 --- a/examples/stm32f1/Cargo.toml +++ b/examples/stm32f1/Cargo.toml @@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0" # 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-executor = { version = "0.3.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-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } diff --git a/examples/stm32f2/Cargo.toml b/examples/stm32f2/Cargo.toml index 9857fb63..54eadd1a 100644 --- a/examples/stm32f2/Cargo.toml +++ b/examples/stm32f2/Cargo.toml @@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0" # 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-executor = { version = "0.3.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"] } defmt = "0.3" diff --git a/examples/stm32f3/Cargo.toml b/examples/stm32f3/Cargo.toml index bd594d16..5d8f5f74 100644 --- a/examples/stm32f3/Cargo.toml +++ b/examples/stm32f3/Cargo.toml @@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0" # 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-executor = { version = "0.3.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-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } diff --git a/examples/stm32f334/Cargo.toml b/examples/stm32f334/Cargo.toml index d8f6b8fe..65183b88 100644 --- a/examples/stm32f334/Cargo.toml +++ b/examples/stm32f334/Cargo.toml @@ -6,7 +6,7 @@ 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"] } +embassy-executor = { version = "0.3.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] } embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32f334r8", "unstable-pac", "memory-x", "time-driver-any", "exti"] } embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] } diff --git a/examples/stm32f4/Cargo.toml b/examples/stm32f4/Cargo.toml index 65a4e51f..ed456c5c 100644 --- a/examples/stm32f4/Cargo.toml +++ b/examples/stm32f4/Cargo.toml @@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0" # 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-executor = { version = "0.3.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/stm32f7/Cargo.toml b/examples/stm32f7/Cargo.toml index 41170f2c..b658a964 100644 --- a/examples/stm32f7/Cargo.toml +++ b/examples/stm32f7/Cargo.toml @@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0" # 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-executor = { version = "0.3.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-net = { path = "../../embassy-net", features = ["defmt", "nightly", "tcp", "dhcpv4", "medium-ethernet"] } embedded-io-async = { version = "0.5.0" } diff --git a/examples/stm32g0/Cargo.toml b/examples/stm32g0/Cargo.toml index b4dfe3c6..4e88151a 100644 --- a/examples/stm32g0/Cargo.toml +++ b/examples/stm32g0/Cargo.toml @@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0" # 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-executor = { version = "0.3.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"] } defmt = "0.3" diff --git a/examples/stm32g4/Cargo.toml b/examples/stm32g4/Cargo.toml index cf3e2ce9..7bb05dbc 100644 --- a/examples/stm32g4/Cargo.toml +++ b/examples/stm32g4/Cargo.toml @@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0" # 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-executor = { version = "0.3.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-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] } diff --git a/examples/stm32h5/Cargo.toml b/examples/stm32h5/Cargo.toml index 5d73e435..f7a1de63 100644 --- a/examples/stm32h5/Cargo.toml +++ b/examples/stm32h5/Cargo.toml @@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0" # 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-executor = { version = "0.3.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-net = { path = "../../embassy-net", features = ["defmt", "nightly", "tcp", "dhcpv4", "medium-ethernet", "proto-ipv6"] } embedded-io-async = { version = "0.5.0" } diff --git a/examples/stm32h7/Cargo.toml b/examples/stm32h7/Cargo.toml index c78c4c60..1ee11b07 100644 --- a/examples/stm32h7/Cargo.toml +++ b/examples/stm32h7/Cargo.toml @@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0" # 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-executor = { version = "0.3.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-net = { path = "../../embassy-net", features = ["defmt", "nightly", "tcp", "dhcpv4", "medium-ethernet", "proto-ipv6"] } embedded-io-async = { version = "0.5.0" } diff --git a/examples/stm32l0/Cargo.toml b/examples/stm32l0/Cargo.toml index 332a6c5e..d4e0da0b 100644 --- a/examples/stm32l0/Cargo.toml +++ b/examples/stm32l0/Cargo.toml @@ -13,7 +13,7 @@ nightly = ["embassy-stm32/nightly", "embassy-time/nightly", "embassy-time/unstab # 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-executor = { version = "0.3.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-lora = { version = "0.1.0", path = "../../embassy-lora", features = ["time", "defmt"], optional = true } lora-phy = { version = "1", optional = true } diff --git a/examples/stm32l1/Cargo.toml b/examples/stm32l1/Cargo.toml index 329d44ca..192fd3e3 100644 --- a/examples/stm32l1/Cargo.toml +++ b/examples/stm32l1/Cargo.toml @@ -6,7 +6,7 @@ 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", "defmt", "integrated-timers"] } +embassy-executor = { version = "0.3.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", "stm32l151cb-a", "time-driver-any", "memory-x"] } diff --git a/examples/stm32l4/Cargo.toml b/examples/stm32l4/Cargo.toml index 944c8c27..f552a610 100644 --- a/examples/stm32l4/Cargo.toml +++ b/examples/stm32l4/Cargo.toml @@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0" # 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-executor = { version = "0.3.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-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] } diff --git a/examples/stm32l5/Cargo.toml b/examples/stm32l5/Cargo.toml index 9dfc08f2..b46c2570 100644 --- a/examples/stm32l5/Cargo.toml +++ b/examples/stm32l5/Cargo.toml @@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0" # 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-executor = { version = "0.3.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-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"] } diff --git a/examples/stm32u5/Cargo.toml b/examples/stm32u5/Cargo.toml index db251eaf..f928e7a6 100644 --- a/examples/stm32u5/Cargo.toml +++ b/examples/stm32u5/Cargo.toml @@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0" # 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-executor = { version = "0.3.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-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] } diff --git a/examples/stm32wb/Cargo.toml b/examples/stm32wb/Cargo.toml index 1a5aff35..f58a5189 100644 --- a/examples/stm32wb/Cargo.toml +++ b/examples/stm32wb/Cargo.toml @@ -9,7 +9,7 @@ license = "MIT OR Apache-2.0" 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-executor = { version = "0.3.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-net = { version = "0.1.0", path = "../../embassy-net", features = ["defmt", "udp", "medium-ieee802154", "nightly"], optional=true } diff --git a/examples/stm32wl/Cargo.toml b/examples/stm32wl/Cargo.toml index 5440807f..1c771ddc 100644 --- a/examples/stm32wl/Cargo.toml +++ b/examples/stm32wl/Cargo.toml @@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0" # 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-executor = { version = "0.3.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-embedded-hal = { version = "0.1.0", path = "../../embassy-embedded-hal" } embassy-lora = { version = "0.1.0", path = "../../embassy-lora", features = ["stm32wl", "time", "defmt"] } diff --git a/examples/wasm/Cargo.toml b/examples/wasm/Cargo.toml index 2791cc34..5b206d71 100644 --- a/examples/wasm/Cargo.toml +++ b/examples/wasm/Cargo.toml @@ -9,7 +9,7 @@ crate-type = ["cdylib"] [dependencies] embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["log"] } -embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["arch-wasm", "executor-thread", "log", "nightly", "integrated-timers"] } +embassy-executor = { version = "0.3.0", path = "../../embassy-executor", features = ["arch-wasm", "executor-thread", "log", "nightly", "integrated-timers"] } embassy-time = { version = "0.1.2", path = "../../embassy-time", features = ["log", "wasm", "nightly"] } wasm-logger = "0.2.0" diff --git a/tests/nrf/Cargo.toml b/tests/nrf/Cargo.toml index 034ed85e..4e31bed5 100644 --- a/tests/nrf/Cargo.toml +++ b/tests/nrf/Cargo.toml @@ -9,7 +9,7 @@ teleprobe-meta = "1" embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt", "nightly"] } -embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "nightly", "integrated-timers"] } +embassy-executor = { version = "0.3.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "nightly", "integrated-timers"] } embassy-time = { version = "0.1.2", path = "../../embassy-time", features = ["defmt", "nightly", "unstable-traits", "defmt-timestamp-uptime"] } embassy-nrf = { version = "0.1.0", path = "../../embassy-nrf", features = ["defmt", "nightly", "unstable-traits", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac"] } embedded-io-async = { version = "0.5.0" } diff --git a/tests/riscv32/Cargo.toml b/tests/riscv32/Cargo.toml index 61f886c0..be610b1c 100644 --- a/tests/riscv32/Cargo.toml +++ b/tests/riscv32/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] critical-section = { version = "1.1.1", features = ["restore-state-bool"] } embassy-sync = { version = "0.2.0", path = "../../embassy-sync" } -embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["arch-riscv32", "nightly", "executor-thread"] } +embassy-executor = { version = "0.3.0", path = "../../embassy-executor", features = ["arch-riscv32", "nightly", "executor-thread"] } embassy-time = { version = "0.1.2", path = "../../embassy-time" } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } diff --git a/tests/rp/Cargo.toml b/tests/rp/Cargo.toml index 6a3df4b9..c494b66e 100644 --- a/tests/rp/Cargo.toml +++ b/tests/rp/Cargo.toml @@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0" teleprobe-meta = "1.1" 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-executor = { version = "0.3.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", "nightly", "unstable-traits"] } embassy-rp = { version = "0.1.0", path = "../../embassy-rp", features = ["nightly", "defmt", "unstable-pac", "unstable-traits", "time-driver", "critical-section-impl", "intrinsics", "rom-v2-intrinsics", "run-from-ram"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } diff --git a/tests/stm32/Cargo.toml b/tests/stm32/Cargo.toml index e2638897..754356cb 100644 --- a/tests/stm32/Cargo.toml +++ b/tests/stm32/Cargo.toml @@ -29,7 +29,7 @@ dac-adc-pin = [] teleprobe-meta = "1" 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-executor = { version = "0.3.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", "tick-hz-32_768", "defmt-timestamp-uptime"] } embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "unstable-pac", "memory-x", "time-driver-any"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } From e19f7d9a76fa13012b6c606167a6a8f215875a4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20van=20Dorst?= Date: Fri, 18 Aug 2023 00:01:13 +0200 Subject: [PATCH 028/106] Add embassy-net-adin1110 This add a library for Analog ADIN1110 SPE SPI chip. This library is inspired by `embassy-net-w5500`. --- embassy-net-adin1110/.gitignore | 1 + embassy-net-adin1110/.vscode/settings.json | 8 + embassy-net-adin1110/Cargo.toml | 41 + embassy-net-adin1110/README.md | 55 + embassy-net-adin1110/rust-toolchain.toml | 3 + embassy-net-adin1110/src/crc32.rs | 101 ++ embassy-net-adin1110/src/crc8.rs | 53 + embassy-net-adin1110/src/lib.rs | 1246 ++++++++++++++++++++ embassy-net-adin1110/src/mdio.rs | 174 +++ embassy-net-adin1110/src/phy.rs | 137 +++ embassy-net-adin1110/src/regs.rs | 407 +++++++ 11 files changed, 2226 insertions(+) create mode 100644 embassy-net-adin1110/.gitignore create mode 100644 embassy-net-adin1110/.vscode/settings.json create mode 100644 embassy-net-adin1110/Cargo.toml create mode 100644 embassy-net-adin1110/README.md create mode 100644 embassy-net-adin1110/rust-toolchain.toml create mode 100644 embassy-net-adin1110/src/crc32.rs create mode 100644 embassy-net-adin1110/src/crc8.rs create mode 100644 embassy-net-adin1110/src/lib.rs create mode 100644 embassy-net-adin1110/src/mdio.rs create mode 100644 embassy-net-adin1110/src/phy.rs create mode 100644 embassy-net-adin1110/src/regs.rs diff --git a/embassy-net-adin1110/.gitignore b/embassy-net-adin1110/.gitignore new file mode 100644 index 00000000..c41cc9e3 --- /dev/null +++ b/embassy-net-adin1110/.gitignore @@ -0,0 +1 @@ +/target \ No newline at end of file diff --git a/embassy-net-adin1110/.vscode/settings.json b/embassy-net-adin1110/.vscode/settings.json new file mode 100644 index 00000000..daa2ccf0 --- /dev/null +++ b/embassy-net-adin1110/.vscode/settings.json @@ -0,0 +1,8 @@ +{ + "rust-analyzer.check.command": "clippy", + "rust-analyzer.showUnlinkedFileNotification": false, + "[rust]": { + "editor.defaultFormatter": "rust-lang.rust-analyzer", + "editor.formatOnSave": true + } +} \ No newline at end of file diff --git a/embassy-net-adin1110/Cargo.toml b/embassy-net-adin1110/Cargo.toml new file mode 100644 index 00000000..e74fb7cd --- /dev/null +++ b/embassy-net-adin1110/Cargo.toml @@ -0,0 +1,41 @@ +[package] +name = "embassy-net-adin1110" +version = "0.1.0" +description = "embassy-net driver for the ADIN1110 ethernet chip" +keywords = ["embedded", "ADIN1110", "embassy-net", "embedded-hal-async", "ethernet", "async"] +categories = ["embedded", "hardware-support", "no-std", "network-programming", "async"] +license = "MIT OR Apache-2.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +heapless = "0.7.16" +defmt = { version = "0.3", optional = true } +log = { version = "0.4.4", default-features = false, optional = true } +embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-rc.1" } +embedded-hal-async = { version = "=1.0.0-rc.1" } +embedded-hal-bus = { version = "=0.1.0-rc.1", features = ["async"] } +embassy-net-driver-channel = { version = "0.1.0", path = "../embassy-net-driver-channel" } +embassy-time = { version = "0.1.0" } +embassy-futures = { version = "0.1.0", path = "../embassy-futures" } +bitfield = "0.14.0" + + +[dev-dependencies] +# reenable when https://github.com/dbrgn/embedded-hal-mock/pull/86 is merged. +#embedded-hal-mock = { git = "https://github.com/dbrgn/embedded-hal-mock", branch = "1-alpha", features = ["embedded-hal-async", "eh1"] }] } +embedded-hal-mock = { git = "https://github.com/newAM/embedded-hal-mock", branch = "eh1-rc.1", features = ["embedded-hal-async", "eh1"] } +crc = "3.0.1" +env_logger = "0.10" +critical-section = { version = "1.1.1", features = ["std"] } +futures-test = "0.3.17" + +[features] +default = [ ] +defmt = [ "dep:defmt" ] + +[package.metadata.embassy_docs] +src_base = "https://github.com/embassy-rs/embassy/blob/embassy-net-adin1110-v$VERSION/embassy-net-adin1110/src/" +src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-net-adin1110/src/" +target = "thumbv7em-none-eabi" diff --git a/embassy-net-adin1110/README.md b/embassy-net-adin1110/README.md new file mode 100644 index 00000000..9b7b4e0e --- /dev/null +++ b/embassy-net-adin1110/README.md @@ -0,0 +1,55 @@ +# SPE ADIN1110 `embassy-net` integration + +[`embassy-net`](https://crates.io/crates/embassy-net) integration for the `Analog ADIN1110` SPI SPE ethernet chips. + +## What is SPE or Single Pair Ethernet / 10 BASE-T1L + +SPE is Single Pair Ethernet, what the names implies, it uses a single twisted/differancial pair (only 2 wires) to transmit ethernet packet in full-duplex. +SPE is still ethernet, only the phissical layer is different. + +SPE also supports [`PoDL(Power over Data Line)`](https://www.ti.com/lit/an/snla395/snla395.pdf), power delivery from 0.5 up to 50 Watts, similair to [`PoE`](https://en.wikipedia.org/wiki/Power_over_Ethernet), but additional hardware and handshake protocol is needed. + +SPE has many link speeds but only `10 BASE-T1L` is able to reach cable length up to 1000 meters in `2.4 Vpp` transmit amplitude. +Currently in 2023, none of the standards are compatiable with eachother. +So `10 BASE-T1L` don't work with a `10 BASE-T1S` or `100 BASE-T1`. + +In the industry SPE is also called [`APL(Advanced Physical Layer)`](https://www.ethernet-apl.org), it is based on the `10 BASE-T1L` standard. + +APL can be use in [`intrinsic safety applications/explosion hazardous areas`](https://en.wikipedia.org/wiki/Electrical_equipment_in_hazardous_areas) which has it's own name and standard [`2-WISE(2-wire intrinsically safe ethernet) IEC TS 60079-47:2021`](https://webstore.iec.ch/publication/64292). + +`10 BASE-T1L` and `ADIN1110` are designed to support intrinsic safety applications. The power supply energy is fixed and PDoL is not supported. + +## Supported SPI modes + +`ADIN1110` supports two SPI modes. `Generic` and [`OPEN Alliance 10BASE-T1x MAC-PHY serial interface`](https://opensig.org/download/document/OPEN_Alliance_10BASET1x_MAC-PHY_Serial_Interface_V1.1.pdf) + +Both modes support with and without additional CRC. +Currently only `Generic` SPI with or without CRC is supported. + +*NOTE:* SPI Mode is selected by the hardware pins `SPI_CFG0` and `SPI_CFG1`. Software can't detect nor change the mode. + +## Hardware + +- Testen on [`Analog Devices EVAL-ADIN1110EBZ`](https://www.analog.com/en/design-center/evaluation-hardware-and-software/evaluation-boards-kits/eval-adin1110.html) with a `STM32L4S5QII3P`, see [`spe_adin1110_http_server`](../examples/stm32l4/src/bin/spe_adin1110_http_server.rs) example. +- [`SparkFun MicroMod Single Pair Ethernet Function Board`](https://www.sparkfun.com/products/19038) or [`SparkFun MicroMod Single Pair Ethernet Kit`](https://www.sparkfun.com/products/19628), the kit supports multiple microcontrollers, please check if get the right microcontroller that is supported by Embassy! + +## Other SPE chips + +* [`Analog ADIN2111`](https://www.analog.com/en/products/adin2111.html) 2 Port SPI version. Can work with this driver. +* [`Analog ADIN1100`](https://www.analog.com/en/products/adin1100.html) RGMII version. + +## Testing + +ADIN1110 library can tested on the host with a mock SPI driver + +$ `cargo test --target x86_64-unknown-linux-gnu` + +## License + +This work is licensed under either of + +- Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or + http://www.apache.org/licenses/LICENSE-2.0) +- MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) + +at your option. diff --git a/embassy-net-adin1110/rust-toolchain.toml b/embassy-net-adin1110/rust-toolchain.toml new file mode 100644 index 00000000..d5f51a7f --- /dev/null +++ b/embassy-net-adin1110/rust-toolchain.toml @@ -0,0 +1,3 @@ +[toolchain] +channel = "nightly" +components = [ "rustfmt", "rustc-dev" ] diff --git a/embassy-net-adin1110/src/crc32.rs b/embassy-net-adin1110/src/crc32.rs new file mode 100644 index 00000000..75a7d65b --- /dev/null +++ b/embassy-net-adin1110/src/crc32.rs @@ -0,0 +1,101 @@ +pub const CRC32R_LOOKUP_TABLE: [u32; 256] = [ + 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, 0x0EDB8832, + 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2, + 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, 0x136C9856, 0x646BA8C0, 0xFD62F97A, + 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, + 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, + 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, + 0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, + 0xB6662D3D, 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, + 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, 0x6B6B51F4, + 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950, + 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, 0x4DB26158, 0x3AB551CE, 0xA3BC0074, + 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, + 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, + 0x206F85B3, 0xB966D409, 0xCE61E49F, 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, + 0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, + 0x73DC1683, 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, + 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, 0xFED41B76, + 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E, + 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, + 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, + 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, + 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, + 0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, + 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, + 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, 0xA00AE278, + 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC, + 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, 0xBDBDF21C, 0xCABAC28A, 0x53B39330, + 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, + 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D, +]; + +#[allow(non_camel_case_types)] +#[derive(Debug)] +pub struct ETH_FSC(pub u32); + +impl ETH_FSC { + pub const CRC32_OK: u32 = 0x2144df1c; + + pub fn new(data: &[u8]) -> Self { + let fsc = data.iter().fold(u32::MAX, |crc, byte| { + let idx = u8::try_from(crc & 0xFF).unwrap() ^ byte; + CRC32R_LOOKUP_TABLE[usize::from(idx)] ^ (crc >> 8) + }) ^ u32::MAX; + Self(fsc) + } + + pub fn crc_ok(&self) -> bool { + self.0 == Self::CRC32_OK + } + + pub fn hton_bytes(&self) -> [u8; 4] { + self.0.to_le_bytes() + } + + pub fn hton(&self) -> u32 { + self.0.to_le() + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn crc32_ethernet_frame() { + let packet_a = &[ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0xe0, 0x4c, 0x68, 0xee, 0xee, 0xff, 0x06, 0x00, 0x01, 0x08, 0x00, + 0x06, 0x04, 0x00, 0x01, 0x00, 0xe0, 0x4c, 0x68, 0x0e, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc0, 0xa8, 0x10, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf2, 0x65, 0x90, 0x3d, + ]; + + let packet_b = &[ + 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0x00, 0xe0, 0x4c, 0x68, 0xee, 0xee, 0xdd, 0x06, 0x00, 0x01, 0x08, 0x00, + 0x06, 0x04, 0x00, 0x02, 0x00, 0xe0, 0x4c, 0x68, 0x09, 0xde, 0xc0, 0xa8, 0x01, 0x02, 0x12, 0x34, 0x56, 0x78, + 0x9a, 0xbc, 0xc0, 0xa8, 0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x3d, 0x67, 0x7c, + ]; + + // Packet A + let own_crc = ETH_FSC::new(&packet_a[0..60]); + let crc_bytes = own_crc.hton_bytes(); + println!("{:08x} {:02x?}", own_crc.0, crc_bytes); + assert_eq!(&crc_bytes, &packet_a[60..64]); + + let own_crc = ETH_FSC::new(packet_a); + println!("{:08x}", own_crc.0); + assert_eq!(own_crc.0, ETH_FSC::CRC32_OK); + + // Packet B + let own_crc = ETH_FSC::new(&packet_b[0..60]); + let crc_bytes = own_crc.hton_bytes(); + println!("{:08x} {:02x?}", own_crc.0, crc_bytes); + assert_eq!(&crc_bytes, &packet_b[60..64]); + + let own_crc = ETH_FSC::new(packet_b); + println!("{:08x}", own_crc.0); + assert_eq!(own_crc.0, ETH_FSC::CRC32_OK); + } +} diff --git a/embassy-net-adin1110/src/crc8.rs b/embassy-net-adin1110/src/crc8.rs new file mode 100644 index 00000000..7d20a740 --- /dev/null +++ b/embassy-net-adin1110/src/crc8.rs @@ -0,0 +1,53 @@ +/// CRC-8/ITU +const CRC8X_TABLE: [u8; 256] = [ + 0x00, 0x07, 0x0e, 0x09, 0x1c, 0x1b, 0x12, 0x15, 0x38, 0x3f, 0x36, 0x31, 0x24, 0x23, 0x2a, 0x2d, 0x70, 0x77, 0x7e, + 0x79, 0x6c, 0x6b, 0x62, 0x65, 0x48, 0x4f, 0x46, 0x41, 0x54, 0x53, 0x5a, 0x5d, 0xe0, 0xe7, 0xee, 0xe9, 0xfc, 0xfb, + 0xf2, 0xf5, 0xd8, 0xdf, 0xd6, 0xd1, 0xc4, 0xc3, 0xca, 0xcd, 0x90, 0x97, 0x9e, 0x99, 0x8c, 0x8b, 0x82, 0x85, 0xa8, + 0xaf, 0xa6, 0xa1, 0xb4, 0xb3, 0xba, 0xbd, 0xc7, 0xc0, 0xc9, 0xce, 0xdb, 0xdc, 0xd5, 0xd2, 0xff, 0xf8, 0xf1, 0xf6, + 0xe3, 0xe4, 0xed, 0xea, 0xb7, 0xb0, 0xb9, 0xbe, 0xab, 0xac, 0xa5, 0xa2, 0x8f, 0x88, 0x81, 0x86, 0x93, 0x94, 0x9d, + 0x9a, 0x27, 0x20, 0x29, 0x2e, 0x3b, 0x3c, 0x35, 0x32, 0x1f, 0x18, 0x11, 0x16, 0x03, 0x04, 0x0d, 0x0a, 0x57, 0x50, + 0x59, 0x5e, 0x4b, 0x4c, 0x45, 0x42, 0x6f, 0x68, 0x61, 0x66, 0x73, 0x74, 0x7d, 0x7a, 0x89, 0x8e, 0x87, 0x80, 0x95, + 0x92, 0x9b, 0x9c, 0xb1, 0xb6, 0xbf, 0xb8, 0xad, 0xaa, 0xa3, 0xa4, 0xf9, 0xfe, 0xf7, 0xf0, 0xe5, 0xe2, 0xeb, 0xec, + 0xc1, 0xc6, 0xcf, 0xc8, 0xdd, 0xda, 0xd3, 0xd4, 0x69, 0x6e, 0x67, 0x60, 0x75, 0x72, 0x7b, 0x7c, 0x51, 0x56, 0x5f, + 0x58, 0x4d, 0x4a, 0x43, 0x44, 0x19, 0x1e, 0x17, 0x10, 0x05, 0x02, 0x0b, 0x0c, 0x21, 0x26, 0x2f, 0x28, 0x3d, 0x3a, + 0x33, 0x34, 0x4e, 0x49, 0x40, 0x47, 0x52, 0x55, 0x5c, 0x5b, 0x76, 0x71, 0x78, 0x7f, 0x6a, 0x6d, 0x64, 0x63, 0x3e, + 0x39, 0x30, 0x37, 0x22, 0x25, 0x2c, 0x2b, 0x06, 0x01, 0x08, 0x0f, 0x1a, 0x1d, 0x14, 0x13, 0xae, 0xa9, 0xa0, 0xa7, + 0xb2, 0xb5, 0xbc, 0xbb, 0x96, 0x91, 0x98, 0x9f, 0x8a, 0x8d, 0x84, 0x83, 0xde, 0xd9, 0xd0, 0xd7, 0xc2, 0xc5, 0xcc, + 0xcb, 0xe6, 0xe1, 0xe8, 0xef, 0xfa, 0xfd, 0xf4, 0xf3, +]; + +/// Calculate the crc of a pease of data. +pub fn crc8(data: &[u8]) -> u8 { + data.iter().fold(0, |crc, &byte| CRC8X_TABLE[usize::from(byte ^ crc)]) +} + +#[cfg(test)] +mod tests { + use ::crc::{Crc, CRC_8_SMBUS}; + + use super::crc8; + + #[test] + fn spi_header_crc8() { + let data = &[0x80, 0x00]; + + let c = Crc::::new(&CRC_8_SMBUS); + let mut dig = c.digest(); + dig.update(data); + let sw_crc = dig.finalize(); + + let own_crc = crc8(data); + + assert_eq!(own_crc, sw_crc); + assert_eq!(own_crc, 182); + + let data = &[0x80, 0x01]; + let mut dig = c.digest(); + dig.update(data); + let sw_crc = dig.finalize(); + let own_crc = crc8(data); + + assert_eq!(own_crc, sw_crc); + assert_eq!(own_crc, 177); + } +} diff --git a/embassy-net-adin1110/src/lib.rs b/embassy-net-adin1110/src/lib.rs new file mode 100644 index 00000000..a4010d25 --- /dev/null +++ b/embassy-net-adin1110/src/lib.rs @@ -0,0 +1,1246 @@ +#![allow(clippy::pedantic)] +#![feature(type_alias_impl_trait)] +#![feature(async_fn_in_trait)] +#![cfg_attr(not(any(test, feature = "std")), no_std)] + +use ch::driver::LinkState; +use embassy_futures::select::{select, Either}; +use embassy_net_driver_channel as ch; +use embassy_time::{Duration, Timer}; +use embedded_hal_1::digital::OutputPin; +use embedded_hal_async::digital::Wait; +use embedded_hal_async::spi::{Operation, SpiDevice}; +use heapless::Vec; + +mod crc32; +mod crc8; +mod mdio; +mod phy; +mod regs; + +pub use crc32::ETH_FSC; +use crc8::crc8; +pub use mdio::MdioBus; +pub use phy::{Phy10BaseT1x, RegsC22, RegsC45}; +pub use regs::{Config0, Config2, SpiRegisters as sr, Status0, Status1}; + +use crate::regs::{LedCntrl, LedFunc, LedPol, LedPolarity, SpiHeader}; + +pub const PHYID: u32 = 0x0283BC91; + +/// Error values ADIN1110 +#[derive(Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[allow(non_camel_case_types)] +pub enum AdinError { + Spi(E), + SENDERROR, + READERROR, + CRC, + PACKET_TOO_BIG, + PACKET_TOO_SMALL, + MDIO_ACC_TIMEOUT, +} + +pub type AEResult = core::result::Result>; +pub const MDIO_PHY_ADDR: u8 = 0x01; +pub const MTU: usize = 1500; +/// Max SPI/Frame buffer size +pub const MAX_BUFF: usize = 2048; + +const DONT_CARE_BYTE: u8 = 0x00; +const TURN_AROUND_BYTE: u8 = 0x00; + +const FEC_LEN: usize = 4; +const FRAME_HEADER_LEN: usize = 2; +const WR_HEADER_LEN: usize = 2; + +// P1 = 0x00, P2 = 0x01 +const PORT_ID_BYTE: u8 = 0x00; + +pub type Packet = Vec; + +/// Type alias for the embassy-net driver for ADIN1110 +pub type Device<'d> = embassy_net_driver_channel::Device<'d, MTU>; + +/// Internal state for the embassy-net integration. +pub struct State { + ch_state: ch::State, +} +impl State { + /// Create a new `State`. + pub const fn new() -> Self { + Self { + ch_state: ch::State::new(), + } + } +} + +#[derive(Debug)] +pub struct ADIN1110 { + /// SPI bus + spi: SPI, + /// Enable CRC on SPI transfer. + /// This must match with the hardware pin SPI_CFG0 were 0 = CRC enable, 1 CRC disabled. + crc: bool, +} + +// Round size up the N u32; +pub(crate) fn size_align_u32(size: u32) -> u32 { + (size + 3) & 0xFFFF_FFFC +} + +impl ADIN1110 +where + SPI: SpiDevice, + SpiE: core::fmt::Debug, +{ + pub fn new(spi: SPI, crc: bool) -> Self { + Self { spi, crc } + } + + pub async fn read_reg(&mut self, reg: sr) -> AEResult { + let mut tx_buf = Vec::::new(); + + let mut spi_hdr = SpiHeader(0); + spi_hdr.set_control(true); + spi_hdr.set_addr(reg); + let _ = tx_buf.extend_from_slice(spi_hdr.0.to_be_bytes().as_slice()); + + if self.crc { + // Add CRC for header data + let _ = tx_buf.push(crc8(&tx_buf)); + } + + // Turn around byte, TODO: Unknown that this is. + let _ = tx_buf.push(TURN_AROUND_BYTE); + + let mut rx_buf = [0; 5]; + + let spi_read_len = if self.crc { rx_buf.len() } else { rx_buf.len() - 1 }; + + let mut spi_op = [Operation::Write(&tx_buf), Operation::Read(&mut rx_buf[0..spi_read_len])]; + + self.spi.transaction(&mut spi_op).await.map_err(AdinError::Spi)?; + + if self.crc { + let crc = crc8(&rx_buf[0..4]); + if crc != rx_buf[4] { + return Err(AdinError::CRC); + } + } + + let value = u32::from_be_bytes(rx_buf[0..4].try_into().unwrap()); + + #[cfg(feature = "defmt")] + defmt::trace!("REG Read {} = {:08x} SPI {:02x}", reg, value, &tx_buf); + + Ok(value) + } + + pub async fn write_reg(&mut self, reg: sr, value: u32) -> AEResult<(), SpiE> { + let mut tx_buf = Vec::::new(); + + let mut spi_hdr = SpiHeader(0); + spi_hdr.set_control(true); + spi_hdr.set_write(true); + spi_hdr.set_addr(reg); + let _ = tx_buf.extend_from_slice(spi_hdr.0.to_be_bytes().as_slice()); + + if self.crc { + // Add CRC for header data + let _ = tx_buf.push(crc8(&tx_buf)); + } + + let val = value.to_be_bytes(); + let _ = tx_buf.extend_from_slice(val.as_slice()); + + if self.crc { + // Add CRC for header data + let _ = tx_buf.push(crc8(val.as_slice())); + } + + #[cfg(feature = "defmt")] + defmt::trace!("REG Write {} = {:08x} SPI {:02x}", reg, value, &tx_buf); + + self.spi.write(&tx_buf).await.map_err(AdinError::Spi) + } + + // helper function for write to MDIO_ACC register and wait for ready! + async fn write_mdio_acc_reg(&mut self, mdio_acc_val: u32) -> AEResult { + self.write_reg(sr::MDIO_ACC, mdio_acc_val).await?; + + // TODO: Add proper timeout! + for _ in 0..100_000 { + let val = self.read_reg(sr::MDIO_ACC).await?; + if val & 0x8000_0000 != 0 { + return Ok(val); + } + } + + Err(AdinError::MDIO_ACC_TIMEOUT) + } + + pub async fn read_fifo(&mut self, packet: &mut [u8]) -> AEResult { + let mut tx_buf = Vec::::new(); + + // Size of the frame, also includes the appednded header. + let packet_size = self.read_reg(sr::RX_FSIZE).await?; + + // Packet read of write to the MAC packet buffer must be a multipul of 4! + let read_size = size_align_u32(packet_size); + + if packet_size < u32::try_from(FRAME_HEADER_LEN + FEC_LEN).unwrap() + || read_size > u32::try_from(packet.len()).unwrap() + { + return Err(AdinError::PACKET_TOO_BIG); + } + + let mut spi_hdr = SpiHeader(0); + spi_hdr.set_control(true); + spi_hdr.set_addr(sr::RX); + let _ = tx_buf.extend_from_slice(spi_hdr.0.to_be_bytes().as_slice()); + + if self.crc { + // Add CRC for header data + let _ = tx_buf.push(crc8(&tx_buf)); + } + + // Turn around byte, TODO: Unknown that this is. + let _ = tx_buf.push(TURN_AROUND_BYTE); + + let spi_packet = &mut packet[0..read_size as usize]; + + assert_eq!(spi_packet.len() & 0x03, 0x00); + + let mut pkt_header = [0, 0]; + + let mut spi_op = [ + Operation::Write(&tx_buf), + Operation::Read(&mut pkt_header), + Operation::Read(spi_packet), + ]; + + self.spi.transaction(&mut spi_op).await.map_err(AdinError::Spi)?; + + Ok(packet_size as usize) + } + + pub async fn write_fifo(&mut self, frame: &[u8]) -> AEResult<(), SpiE> { + let header_len = self.header_write_len(); + // if packet.len() < header_len { + // return Err(AdinError::PACKET_TOO_SMALL); + // } + + let mut packet = Packet::new(); + + let mut spi_hdr = SpiHeader(0); + spi_hdr.set_control(true); + spi_hdr.set_write(true); + spi_hdr.set_addr(sr::TX); + + packet + .extend_from_slice(spi_hdr.0.to_be_bytes().as_slice()) + .map_err(|_| AdinError::PACKET_TOO_BIG)?; + + if self.crc { + assert_eq!(header_len, 5); + // Add CRC for header data + packet + .push(crc8(&packet[0..2])) + .map_err(|_| AdinError::PACKET_TOO_BIG)?; + } + + // Add port number + // packet[header_len - FRAME_HEADER_LEN..header_len] + // .copy_from_slice(u16::from(PORT_ID_BYTE).to_be_bytes().as_slice()); + packet + .extend_from_slice(u16::from(PORT_ID_BYTE).to_be_bytes().as_slice()) + .map_err(|_| AdinError::PACKET_TOO_BIG)?; + + packet.extend_from_slice(frame).map_err(|_| AdinError::PACKET_TOO_BIG)?; + + // Pad data up to 64 + for _ in packet.len()..(64 - FEC_LEN + header_len) { + let _ = packet.push(0x00); + } + + // // add ethernet crc32 + let crc = ETH_FSC::new(&packet[header_len..]); + let _ = packet.extend_from_slice(crc.hton_bytes().as_slice()); + + let crc = ETH_FSC::new(&packet[header_len..]); + assert!(crc.crc_ok()); + + let send_len = packet.len() - header_len + FRAME_HEADER_LEN; + + // Packet read of write to the MAC packet buffer must be a multipul of 4! + while packet.len() & 0x3 != 0 { + let _ = packet.push(DONT_CARE_BYTE); + } + + #[cfg(feature = "defmt")] + defmt::trace!( + "TX: hdr {} [{}] {:02x} SIZE: {}", + header_len, + packet.len(), + &packet, + send_len, + ); + + self.write_reg(sr::TX_FSIZE, send_len as u32).await?; + + // Spi packet must be half word / even length + if send_len & 1 != 0 { + let _ = packet.push(0x00); + } + + self.spi.write(&packet).await.map_err(AdinError::Spi) + } + + pub fn header_write_len(&self) -> usize { + // u16 + [CRC] + PORT + WR_HEADER_LEN + FRAME_HEADER_LEN + usize::from(self.crc) + } + + pub fn header_len_read(&self) -> usize { + // u16 + [CRC] + u8 + WR_HEADER_LEN + 1 + usize::from(self.crc) + } + + /// Programs the mac address in the mac filters. + /// Also set the boardcast address. + /// The chip supports 2 priority queues but current code doesn't support this mode. + pub async fn set_mac_addr(&mut self, mac: &[u8; 6]) -> AEResult<(), SpiE> { + let mac_high_part = u16::from_be_bytes(mac[0..2].try_into().unwrap()); + let mac_low_part = u32::from_be_bytes(mac[2..6].try_into().unwrap()); + + // program our mac address in the mac address filter + self.write_reg(sr::ADDR_FILT_UPR0, (1 << 16) | (1 << 30) | u32::from(mac_high_part)) + .await?; + self.write_reg(sr::ADDR_FILT_LWR0, mac_low_part).await?; + + self.write_reg(sr::ADDR_MSK_UPR0, u32::from(mac_high_part)).await?; + self.write_reg(sr::ADDR_MSK_LWR0, mac_low_part).await?; + + // Also program broadcast address in the mac address filter + self.write_reg(sr::ADDR_FILT_UPR1, (1 << 16) | (1 << 30) | 0xFFFF) + .await?; + self.write_reg(sr::ADDR_FILT_LWR1, 0xFFFF_FFFF).await?; + self.write_reg(sr::ADDR_MSK_UPR1, 0xFFFF).await?; + self.write_reg(sr::ADDR_MSK_LWR1, 0xFFFF_FFFF).await?; + + Ok(()) + } +} + +impl mdio::MdioBus for ADIN1110 +where + SPI: SpiDevice, + SpiE: core::fmt::Debug, +{ + type Error = AdinError; + + /// Read from the PHY Registers as Clause 22. + async fn read_cl22(&mut self, phy_id: u8, reg: u8) -> Result { + let mdio_acc_val: u32 = + (0x1 << 28) | u32::from(phy_id & 0x1F) << 21 | u32::from(reg & 0x1F) << 16 | (0x3 << 26); + + self.write_mdio_acc_reg(mdio_acc_val).await.map(|val| val as u16) + } + + /// Read from the PHY Registers as Clause 45. + async fn read_cl45(&mut self, phy_id: u8, regc45: (u8, u16)) -> Result { + let mdio_acc_val: u32 = u32::from(phy_id & 0x1F) << 21 | u32::from(regc45.0 & 0x1F) << 16 | u32::from(regc45.1); + + self.write_mdio_acc_reg(mdio_acc_val).await?; + + let mdio_acc_val: u32 = u32::from(phy_id & 0x1F) << 21 | u32::from(regc45.0 & 0x1F) << 16 | (0x03 << 26); + + self.write_mdio_acc_reg(mdio_acc_val).await.map(|val| val as u16) + } + + /// Write to the PHY Registers as Clause 22. + async fn write_cl22(&mut self, phy_id: u8, reg: u8, val: u16) -> Result<(), Self::Error> { + let mdio_acc_val: u32 = + (0x1 << 28) | u32::from(phy_id & 0x1F) << 21 | u32::from(reg & 0x1F) << 16 | (0x1 << 26) | u32::from(val); + + self.write_mdio_acc_reg(mdio_acc_val).await.map(|_| ()) + } + + /// Write to the PHY Registers as Clause 45. + async fn write_cl45(&mut self, phy_id: u8, regc45: (u8, u16), value: u16) -> AEResult<(), SpiE> { + let phy_id = u32::from(phy_id & 0x1F) << 21; + let dev_addr = u32::from(regc45.0 & 0x1F) << 16; + let reg = u32::from(regc45.1); + + let mdio_acc_val: u32 = phy_id | dev_addr | reg; + self.write_mdio_acc_reg(mdio_acc_val).await?; + + let mdio_acc_val: u32 = phy_id | dev_addr | (0x01 << 26) | u32::from(value); + self.write_mdio_acc_reg(mdio_acc_val).await.map(|_| ()) + } +} + +/// Background runner for the ADIN110. +/// +/// You must call `.run()` in a background task for the ADIN1100 to operate. +pub struct Runner<'d, SPI, INT, RST> { + mac: ADIN1110, + ch: ch::Runner<'d, MTU>, + int: INT, + is_link_up: bool, + _reset: RST, +} + +impl<'d, SPI: SpiDevice, INT: Wait, RST: OutputPin> Runner<'d, SPI, INT, RST> { + pub async fn run(mut self) -> ! { + loop { + let (state_chan, mut rx_chan, mut tx_chan) = self.ch.split(); + + loop { + #[cfg(feature = "defmt")] + defmt::debug!("Waiting for interrupts"); + match select(self.int.wait_for_low(), tx_chan.tx_buf()).await { + Either::First(_) => { + let mut status1_clr = Status1(0); + let mut status1 = Status1(self.mac.read_reg(sr::STATUS1).await.unwrap()); + + while status1.p1_rx_rdy() { + #[cfg(feature = "defmt")] + defmt::debug!("alloc RX packet buffer"); + match select(rx_chan.rx_buf(), tx_chan.tx_buf()).await { + // Handle frames that needs to transmit from the wire. + // Note: rx_chan.rx_buf() channel don´t accept new request + // when the tx_chan is full. So these will be handled + // automaticly. + Either::First(frame) => match self.mac.read_fifo(frame).await { + Ok(n) => { + rx_chan.rx_done(n); + } + Err(e) => match e { + AdinError::PACKET_TOO_BIG => { + #[cfg(feature = "defmt")] + defmt::error!("RX Packet to big, DROP"); + self.mac.write_reg(sr::FIFO_CLR, 1).await.unwrap(); + } + AdinError::Spi(_) => { + #[cfg(feature = "defmt")] + defmt::error!("RX Spi error") + } + _ => { + #[cfg(feature = "defmt")] + defmt::error!("RX Error") + } + }, + }, + Either::Second(frame) => { + // Handle frames that needs to transmit to the wire. + self.mac.write_fifo(frame).await.unwrap(); + tx_chan.tx_done(); + } + } + status1 = Status1(self.mac.read_reg(sr::STATUS1).await.unwrap()); + } + + let status0 = Status0(self.mac.read_reg(sr::STATUS0).await.unwrap()); + if status1.0 & !0x1b != 0 { + #[cfg(feature = "defmt")] + defmt::error!("SPE CHIP STATUS 0:{:08x} 1:{:08x}", status0.0, status1.0); + } + + if status1.tx_rdy() { + status1_clr.set_tx_rdy(true); + #[cfg(feature = "defmt")] + defmt::info!("TX_DONE"); + } + + if status1.link_change() { + let link = status1.p1_link_status(); + self.is_link_up = link; + + #[cfg(feature = "defmt")] + if link { + let link_status = self + .mac + .read_cl45(MDIO_PHY_ADDR, RegsC45::DA7::AN_STATUS_EXTRA.into()) + .await + .unwrap(); + + let volt = if link_status & (0b11 << 5) == (0b11 << 5) { + "2.4" + } else { + "1.0" + }; + + let mse = self + .mac + .read_cl45(MDIO_PHY_ADDR, RegsC45::DA1::MSE_VAL.into()) + .await + .unwrap(); + + defmt::info!("LINK Changed: Link Up, Volt: {} V p-p, MSE: {:0004}", volt, mse); + } else { + defmt::info!("LINK Changed: Link Down"); + } + + state_chan.set_link_state(if link { LinkState::Up } else { LinkState::Down }); + status1_clr.set_link_change(true); + } + + if status1.tx_ecc_err() { + #[cfg(feature = "defmt")] + defmt::error!("SPI TX_ECC_ERR error, CLEAR TX FIFO"); + self.mac.write_reg(sr::FIFO_CLR, 2).await.unwrap(); + status1_clr.set_tx_ecc_err(true); + } + + if status1.rx_ecc_err() { + #[cfg(feature = "defmt")] + defmt::error!("SPI RX_ECC_ERR error"); + status1_clr.set_rx_ecc_err(true); + } + + if status1.spi_err() { + #[cfg(feature = "defmt")] + defmt::error!("SPI SPI_ERR CRC error"); + status1_clr.set_spi_err(true); + } + + if status0.phyint() { + let crsm_irq_st = self + .mac + .read_cl45(MDIO_PHY_ADDR, RegsC45::DA1E::CRSM_IRQ_STATUS.into()) + .await + .unwrap(); + + let phy_irq_st = self + .mac + .read_cl45(MDIO_PHY_ADDR, RegsC45::DA1F::PHY_SYBSYS_IRQ_STATUS.into()) + .await + .unwrap(); + #[cfg(feature = "defmt")] + defmt::warn!( + "SPE CHIP PHY CRSM_IRQ_STATUS {:04x} PHY_SUBSYS_IRQ_STATUS {:04x}", + crsm_irq_st, + phy_irq_st + ); + } + + if status0.txfcse() { + #[cfg(feature = "defmt")] + defmt::error!("SPE CHIP PHY TX Frame CRC error"); + } + + // Clear status0 + self.mac.write_reg(sr::STATUS0, 0xFFF).await.unwrap(); + self.mac.write_reg(sr::STATUS1, status1_clr.0).await.unwrap(); + } + Either::Second(packet) => { + // Handle frames that needs to transmit to the wire. + self.mac.write_fifo(packet).await.unwrap(); + tx_chan.tx_done(); + } + } + } + } + } +} + +/// Obtain a driver for using the ADIN1110 with [`embassy-net`](crates.io/crates/embassy-net). +pub async fn new( + mac_addr: [u8; 6], + state: &'_ mut State, + spi_dev: SPI, + int: INT, + mut reset: RST, + crc: bool, +) -> (Device<'_>, Runner<'_, SPI, INT, RST>) { + use crate::regs::{IMask0, IMask1}; + + #[cfg(feature = "defmt")] + defmt::info!("INIT ADIN1110"); + + // Reset sequence + reset.set_low().unwrap(); + // Wait t1: 20-43mS + Timer::after(Duration::from_millis(30)).await; + + reset.set_high().unwrap(); + + // Wait t3: 50mS + Timer::after(Duration::from_millis(50)).await; + + // Create device + let mut mac = ADIN1110::new(spi_dev, crc); + + // Check PHYID + let id = mac.read_reg(sr::PHYID).await.unwrap(); + assert_eq!(id, PHYID); + + #[cfg(feature = "defmt")] + defmt::debug!("SPE: CHIP MAC/ID: {:08x}", id); + + #[cfg(feature = "defmt")] + let adin_phy = Phy10BaseT1x::default(); + #[cfg(feature = "defmt")] + let phy_id = adin_phy.get_id(&mut mac).await.unwrap(); + #[cfg(feature = "defmt")] + defmt::debug!("SPE: CHIP: PHY ID: {:08x}", phy_id); + + let mi_control = mac.read_cl22(MDIO_PHY_ADDR, RegsC22::CONTROL as u8).await.unwrap(); + #[cfg(feature = "defmt")] + defmt::println!("SPE CHIP PHY MI_CONTROL {:04x}", mi_control); + if mi_control & 0x0800 != 0 { + let val = mi_control & !0x0800; + #[cfg(feature = "defmt")] + defmt::println!("SPE CHIP PHY MI_CONTROL Disable PowerDown"); + mac.write_cl22(MDIO_PHY_ADDR, RegsC22::CONTROL as u8, val) + .await + .unwrap(); + } + + // Config2: CRC_APPEND + let mut config2 = Config2(0x00000800); + config2.set_crc_append(true); + mac.write_reg(sr::CONFIG2, config2.0).await.unwrap(); + + // Pin Mux Config 1 + let led_val = (0b11 << 6) | (0b11 << 4); // | (0b00 << 1); + mac.write_cl45(MDIO_PHY_ADDR, RegsC45::DA1E::DIGIO_PINMUX.into(), led_val) + .await + .unwrap(); + + let mut led_pol = LedPolarity(0); + led_pol.set_led1_polarity(LedPol::ActiveLow); + led_pol.set_led0_polarity(LedPol::ActiveLow); + + // Led Polarity Regisgere Active Low + mac.write_cl45(MDIO_PHY_ADDR, RegsC45::DA1E::LED_POLARITY.into(), led_pol.0) + .await + .unwrap(); + + // Led Both On + let mut led_cntr = LedCntrl(0x0); + + // LED1: Yellow + led_cntr.set_led1_en(true); + led_cntr.set_led1_function(LedFunc::TxLevel2P4); + // LED0: Green + led_cntr.set_led0_en(true); + led_cntr.set_led0_function(LedFunc::LinkupTxRxActicity); + + mac.write_cl45(MDIO_PHY_ADDR, RegsC45::DA1E::LED_CNTRL.into(), led_cntr.0) + .await + .unwrap(); + + // Set ADIN1110 Interrupts, RX_READY and LINK_CHANGE + // Enable interrupts LINK_CHANGE, TX_RDY, RX_RDY(P1), SPI_ERR + // Have to clear the mask the enable it. + let mut imask0_val = IMask0(0x0000_1FBF); + imask0_val.set_txfcsem(false); + imask0_val.set_phyintm(false); + imask0_val.set_txboem(false); + imask0_val.set_rxboem(false); + imask0_val.set_txpem(false); + + mac.write_reg(sr::IMASK0, imask0_val.0).await.unwrap(); + + // Set ADIN1110 Interrupts, RX_READY and LINK_CHANGE + // Enable interrupts LINK_CHANGE, TX_RDY, RX_RDY(P1), SPI_ERR + // Have to clear the mask the enable it. + let mut imask1_val = IMask1(0x43FA_1F1A); + imask1_val.set_link_change_mask(false); + imask1_val.set_p1_rx_rdy_mask(false); + imask1_val.set_spi_err_mask(false); + imask1_val.set_tx_ecc_err_mask(false); + imask1_val.set_rx_ecc_err_mask(false); + + mac.write_reg(sr::IMASK1, imask1_val.0).await.unwrap(); + + // Program mac address but also sets mac filters. + mac.set_mac_addr(&mac_addr).await.unwrap(); + + let (runner, device) = ch::new(&mut state.ch_state, ch::driver::HardwareAddress::Ethernet(mac_addr)); + ( + device, + Runner { + ch: runner, + mac, + int, + is_link_up: false, + _reset: reset, + }, + ) +} + +#[cfg(test)] +mod tests { + use core::convert::Infallible; + + use embedded_hal_1::digital::{ErrorType, OutputPin}; + use embedded_hal_async::delay::DelayUs; + use embedded_hal_bus::spi::ExclusiveDevice; + use embedded_hal_mock::eh1::spi::{Mock as SpiMock, Transaction as SpiTransaction}; + + #[derive(Debug, Default)] + struct CsPinMock { + pub high: u32, + pub low: u32, + } + impl OutputPin for CsPinMock { + fn set_low(&mut self) -> Result<(), Self::Error> { + self.low += 1; + Ok(()) + } + + fn set_high(&mut self) -> Result<(), Self::Error> { + self.high += 1; + Ok(()) + } + } + impl ErrorType for CsPinMock { + type Error = Infallible; + } + + use super::*; + + // TODO: This is currently a workaround unit `ExclusiveDevice` is moved to `embedded-hal-bus` + // see https://github.com/rust-embedded/embedded-hal/pull/462#issuecomment-1560014426 + struct MockDelay {} + + impl DelayUs for MockDelay { + async fn delay_us(&mut self, _us: u32) { + todo!() + } + + async fn delay_ms(&mut self, _ms: u32) { + todo!() + } + } + + #[futures_test::test] + async fn mac_read_registers_without_crc() { + // Configure expectations + let expectations = [ + // 1st + SpiTransaction::write_vec(vec![0x80, 0x01, TURN_AROUND_BYTE]), + SpiTransaction::read_vec(vec![0x02, 0x83, 0xBC, 0x91]), + SpiTransaction::flush(), + // 2nd + SpiTransaction::write_vec(vec![0x80, 0x02, TURN_AROUND_BYTE]), + SpiTransaction::read_vec(vec![0x00, 0x00, 0x06, 0xC3]), + SpiTransaction::flush(), + ]; + let mut spi = SpiMock::new(&expectations); + + let cs = CsPinMock::default(); + let delay = MockDelay {}; + let spi_dev = ExclusiveDevice::new(spi.clone(), cs, delay); + let mut spe = ADIN1110::new(spi_dev, false); + + // Read PHIID + match spe.read_reg(sr::PHYID).await { + Ok(val) => assert_eq!(val, 0x0283BC91), + Err(_e) => panic!("Error:"), + }; + + // Read CAPAVILITY + match spe.read_reg(sr::CAPABILITY).await { + Ok(val) => assert_eq!(val, 0x000006C3), + Err(_e) => panic!("Error:"), + }; + + spi.done(); + } + + #[futures_test::test] + async fn mac_read_registers_with_crc() { + // Configure expectations + let expectations = [ + // 1st + SpiTransaction::write_vec(vec![0x80, 0x01, 177, TURN_AROUND_BYTE]), + SpiTransaction::read_vec(vec![0x02, 0x83, 0xBC, 0x91, 215]), + SpiTransaction::flush(), + // 2nd + SpiTransaction::write_vec(vec![0x80, 0x02, 184, TURN_AROUND_BYTE]), + SpiTransaction::read_vec(vec![0x00, 0x00, 0x06, 0xC3, 57]), + SpiTransaction::flush(), + ]; + let mut spi = SpiMock::new(&expectations); + + let cs = CsPinMock::default(); + let delay = MockDelay {}; + let spi_dev = ExclusiveDevice::new(spi.clone(), cs, delay); + + let mut spe = ADIN1110::new(spi_dev, true); + + assert_eq!(crc8(0x0283BC91_u32.to_be_bytes().as_slice()), 215); + assert_eq!(crc8(0x000006C3_u32.to_be_bytes().as_slice()), 57); + + // Read PHIID + match spe.read_reg(sr::PHYID).await { + Ok(val) => assert_eq!(val, 0x0283BC91), + Err(e) => panic!("Error: {e:?}"), + }; + + // Read CAPAVILITY + match spe.read_reg(sr::CAPABILITY).await { + Ok(val) => assert_eq!(val, 0x000006C3), + Err(_e) => panic!("Error:"), + }; + + spi.done(); + } + + #[futures_test::test] + async fn mac_write_registers_without_crc() { + // Configure expectations + let expectations = [ + SpiTransaction::write_vec(vec![0xA0, 0x09, 0x12, 0x34, 0x56, 0x78]), + SpiTransaction::flush(), + ]; + let mut spi = SpiMock::new(&expectations); + + let cs = CsPinMock::default(); + let delay = MockDelay {}; + let spi_dev = ExclusiveDevice::new(spi.clone(), cs, delay); + + let mut spe = ADIN1110::new(spi_dev, false); + + // Write reg: 0x1FFF + assert!(spe.write_reg(sr::STATUS1, 0x1234_5678).await.is_ok()); + + spi.done(); + } + + #[futures_test::test] + async fn mac_write_registers_with_crc() { + // Configure expectations + let expectations = [ + SpiTransaction::write_vec(vec![0xA0, 0x09, 39, 0x12, 0x34, 0x56, 0x78, 28]), + SpiTransaction::flush(), + ]; + let mut spi = SpiMock::new(&expectations); + + let cs = CsPinMock::default(); + let delay = MockDelay {}; + let spi_dev = ExclusiveDevice::new(spi.clone(), cs, delay); + + let mut spe = ADIN1110::new(spi_dev, true); + + // Write reg: 0x1FFF + assert!(spe.write_reg(sr::STATUS1, 0x1234_5678).await.is_ok()); + + spi.done(); + } + + #[test] + fn align_size() { + assert_eq!(size_align_u32(1), 4); + assert_eq!(size_align_u32(2), 4); + assert_eq!(size_align_u32(3), 4); + assert_eq!(size_align_u32(4), 4); + assert_eq!(size_align_u32(5), 8); + assert_eq!(size_align_u32(6), 8); + assert_eq!(size_align_u32(7), 8); + assert_eq!(size_align_u32(8), 8); + } + + // #[test] + // fn write_packet_to_fifo_less_64b_with_crc() { + // // Configure expectations + // let mut expectations = vec![ + // // HEADER + // SpiTransaction::send(0xA0), + // SpiTransaction::read(DONT_CARE_BYTE), + // SpiTransaction::send(0x30), + // SpiTransaction::read(DONT_CARE_BYTE), + // SpiTransaction::send(136), + // SpiTransaction::read(DONT_CARE_BYTE), + // // Frame Size + // SpiTransaction::send(0x00), + // SpiTransaction::read(DONT_CARE_BYTE), + // SpiTransaction::send(0x00), + // SpiTransaction::read(DONT_CARE_BYTE), + // SpiTransaction::send(0x00), + // SpiTransaction::read(DONT_CARE_BYTE), + // SpiTransaction::send(66), + // SpiTransaction::read(DONT_CARE_BYTE), + // SpiTransaction::send(201), + // SpiTransaction::read(DONT_CARE_BYTE), + // // HEADER + // SpiTransaction::send(0xA0), + // SpiTransaction::read(DONT_CARE_BYTE), + // SpiTransaction::send(0x31), + // SpiTransaction::read(DONT_CARE_BYTE), + // // Port + // SpiTransaction::send(0x00), + // SpiTransaction::read(DONT_CARE_BYTE), + // SpiTransaction::send(PORT_ID_BYTE), + // SpiTransaction::read(DONT_CARE_BYTE), + // ]; + + // let mut packet = Packet::new(); + // packet.resize(64, 0).unwrap(); + + // for &byte in &packet[4..] { + // expectations.push(SpiTransaction::send(byte)); + // expectations.push(SpiTransaction::read(DONT_CARE_BYTE)); + // } + + // // padding + // for _ in packet.len() as u32..65 { + // expectations.push(SpiTransaction::send(0x00)); + // expectations.push(SpiTransaction::read(DONT_CARE_BYTE)); + // } + + // // fcs + // for &byte in &[8, 137, 18, 4] { + // expectations.push(SpiTransaction::send(byte)); + // expectations.push(SpiTransaction::read(DONT_CARE_BYTE)); + // } + + // let spi = SpiMock::new(&expectations); + + // let cs = CsPinMock {}; + // let mut spe = Adin1110::new(spi, cs, true); + + // assert!(spe.write_fifo(&mut packet).is_ok()); + // } + + // #[test] + // fn write_packet_to_fifo_less_64b_no_crc() { + // // Configure expectations + // let mut expectations = vec![ + // // HEADER + // SpiTransaction::send(0xA0), + // SpiTransaction::read(DONT_CARE_BYTE), + // SpiTransaction::send(0x30), + // SpiTransaction::read(DONT_CARE_BYTE), + // // Frame Size + // SpiTransaction::send(0x00), + // SpiTransaction::read(DONT_CARE_BYTE), + // SpiTransaction::send(0x00), + // SpiTransaction::read(DONT_CARE_BYTE), + // SpiTransaction::send(0x00), + // SpiTransaction::read(DONT_CARE_BYTE), + // SpiTransaction::send(66), + // SpiTransaction::read(DONT_CARE_BYTE), + // // HEADER + // SpiTransaction::send(0xA0), + // SpiTransaction::read(DONT_CARE_BYTE), + // SpiTransaction::send(0x31), + // SpiTransaction::read(DONT_CARE_BYTE), + // // Port + // SpiTransaction::send(0x00), + // SpiTransaction::read(DONT_CARE_BYTE), + // SpiTransaction::send(PORT_ID_BYTE), + // SpiTransaction::read(DONT_CARE_BYTE), + // ]; + + // let mut packet = Packet::new(); + // packet.resize(64, 0).unwrap(); + + // for &byte in &packet[4..] { + // expectations.push(SpiTransaction::send(byte)); + // expectations.push(SpiTransaction::read(DONT_CARE_BYTE)); + // } + + // // padding + // for _ in packet.len() as u32..64 { + // expectations.push(SpiTransaction::send(0x00)); + // expectations.push(SpiTransaction::read(DONT_CARE_BYTE)); + // } + + // // fcs + // for &byte in &[8, 137, 18, 4] { + // expectations.push(SpiTransaction::send(byte)); + // expectations.push(SpiTransaction::read(DONT_CARE_BYTE)); + // } + + // let spi = SpiMock::new(&expectations); + + // let cs = CsPinMock {}; + // let mut spe = Adin1110::new(spi, cs, false); + + // assert!(spe.write_fifo(&mut packet).is_ok()); + // } + + // #[test] + // fn write_packet_to_fifo_1500b() { + // // Configure expectations + // let mut expectations = vec![ + // // HEADER + // SpiTransaction::send(0xA0), + // SpiTransaction::read(DONT_CARE_BYTE), + // SpiTransaction::send(0x30), + // SpiTransaction::read(DONT_CARE_BYTE), + // // Frame Size + // SpiTransaction::send(0x00), + // SpiTransaction::read(DONT_CARE_BYTE), + // SpiTransaction::send(0x00), + // SpiTransaction::read(DONT_CARE_BYTE), + // SpiTransaction::send(0x05), + // SpiTransaction::read(DONT_CARE_BYTE), + // SpiTransaction::send(0xDE), + // SpiTransaction::read(DONT_CARE_BYTE), + // // HEADER + // SpiTransaction::send(0xA0), + // SpiTransaction::read(DONT_CARE_BYTE), + // SpiTransaction::send(0x31), + // SpiTransaction::read(DONT_CARE_BYTE), + // // Port + // SpiTransaction::send(0x00), + // SpiTransaction::read(DONT_CARE_BYTE), + // SpiTransaction::send(PORT_ID_BYTE), + // SpiTransaction::read(DONT_CARE_BYTE), + // ]; + + // let mut packet = Packet::new(); + // packet.resize(1500, 0).unwrap(); + + // for &byte in &packet[4..] { + // expectations.push(SpiTransaction::send(byte)); + // expectations.push(SpiTransaction::read(DONT_CARE_BYTE)); + // } + + // // fcs + // for &byte in &[212, 114, 18, 50] { + // expectations.push(SpiTransaction::send(byte)); + // expectations.push(SpiTransaction::read(DONT_CARE_BYTE)); + // } + + // let spi = SpiMock::new(&expectations); + + // let cs = CsPinMock {}; + // let mut spe = Adin1110::new(spi, cs, false); + + // assert!(spe.write_fifo(&mut packet).is_ok()); + // } + + // #[test] + // fn write_packet_to_fifo_65b() { + // // Configure expectations + // let mut expectations = vec![ + // // HEADER + // SpiTransaction::send(0xA0), + // SpiTransaction::read(DONT_CARE_BYTE), + // SpiTransaction::send(0x30), + // SpiTransaction::read(DONT_CARE_BYTE), + // // Frame Size + // SpiTransaction::send(0x00), + // SpiTransaction::read(DONT_CARE_BYTE), + // SpiTransaction::send(0x00), + // SpiTransaction::read(DONT_CARE_BYTE), + // SpiTransaction::send(0x00), + // SpiTransaction::read(DONT_CARE_BYTE), + // SpiTransaction::send(67), + // SpiTransaction::read(DONT_CARE_BYTE), + // // HEADER + // SpiTransaction::send(0xA0), + // SpiTransaction::read(DONT_CARE_BYTE), + // SpiTransaction::send(0x31), + // SpiTransaction::read(DONT_CARE_BYTE), + // // Port + // SpiTransaction::send(0x00), + // SpiTransaction::read(DONT_CARE_BYTE), + // SpiTransaction::send(PORT_ID_BYTE), + // SpiTransaction::read(DONT_CARE_BYTE), + // ]; + + // let mut packet = Packet::new(); + // packet.resize(65, 0).unwrap(); + + // for &byte in &packet[4..] { + // expectations.push(SpiTransaction::send(byte)); + // expectations.push(SpiTransaction::read(DONT_CARE_BYTE)); + // } + + // // padding + // for _ in packet.len() as u32..64 { + // expectations.push(SpiTransaction::send(0x00)); + // expectations.push(SpiTransaction::read(DONT_CARE_BYTE)); + // } + + // // fcs + // for &byte in &[54, 117, 221, 220] { + // expectations.push(SpiTransaction::send(byte)); + // expectations.push(SpiTransaction::read(DONT_CARE_BYTE)); + // } + + // let spi = SpiMock::new(&expectations); + + // let cs = CsPinMock {}; + // let mut spe = Adin1110::new(spi, cs, false); + + // assert!(spe.write_fifo(&mut packet).is_ok()); + // } + + // #[test] + // fn write_packet_to_fifo_66b() { + // // Configure expectations + // let mut expectations = vec![ + // // HEADER + // SpiTransaction::send(0xA0), + // SpiTransaction::read(DONT_CARE_BYTE), + // SpiTransaction::send(0x30), + // SpiTransaction::read(DONT_CARE_BYTE), + // // Frame Size + // SpiTransaction::send(0x00), + // SpiTransaction::read(DONT_CARE_BYTE), + // SpiTransaction::send(0x00), + // SpiTransaction::read(DONT_CARE_BYTE), + // SpiTransaction::send(0x00), + // SpiTransaction::read(DONT_CARE_BYTE), + // SpiTransaction::send(68), + // SpiTransaction::read(DONT_CARE_BYTE), + // // HEADER + // SpiTransaction::send(0xA0), + // SpiTransaction::read(DONT_CARE_BYTE), + // SpiTransaction::send(0x31), + // SpiTransaction::read(DONT_CARE_BYTE), + // // Port + // SpiTransaction::send(0x00), + // SpiTransaction::read(DONT_CARE_BYTE), + // SpiTransaction::send(PORT_ID_BYTE), + // SpiTransaction::read(DONT_CARE_BYTE), + // ]; + + // let mut packet = Packet::new(); + // packet.resize(66, 0).unwrap(); + + // for &byte in &packet[4..] { + // expectations.push(SpiTransaction::send(byte)); + // expectations.push(SpiTransaction::read(DONT_CARE_BYTE)); + // } + + // // padding + // for _ in packet.len() as u32..64 { + // expectations.push(SpiTransaction::send(0x00)); + // expectations.push(SpiTransaction::read(DONT_CARE_BYTE)); + // } + + // // fcs + // for &byte in &[97, 167, 100, 29] { + // expectations.push(SpiTransaction::send(byte)); + // expectations.push(SpiTransaction::read(DONT_CARE_BYTE)); + // } + // let spi = SpiMock::new(&expectations); + + // let cs = CsPinMock {}; + // let mut spe = Adin1110::new(spi, cs, false); + + // assert!(spe.write_fifo(&mut packet).is_ok()); + // } + + // #[test] + // fn write_packet_to_fifo_67b() { + // // Configure expectations + // let mut expectations = vec![ + // // HEADER + // SpiTransaction::send(0xA0), + // SpiTransaction::read(DONT_CARE_BYTE), + // SpiTransaction::send(0x30), + // SpiTransaction::read(DONT_CARE_BYTE), + // // Frame Size + // SpiTransaction::send(0x00), + // SpiTransaction::read(DONT_CARE_BYTE), + // SpiTransaction::send(0x00), + // SpiTransaction::read(DONT_CARE_BYTE), + // SpiTransaction::send(0x00), + // SpiTransaction::read(DONT_CARE_BYTE), + // SpiTransaction::send(69), + // SpiTransaction::read(DONT_CARE_BYTE), + // // HEADER + // SpiTransaction::send(0xA0), + // SpiTransaction::read(DONT_CARE_BYTE), + // SpiTransaction::send(0x31), + // SpiTransaction::read(DONT_CARE_BYTE), + // // Port + // SpiTransaction::send(0x00), + // SpiTransaction::read(DONT_CARE_BYTE), + // SpiTransaction::send(PORT_ID_BYTE), + // SpiTransaction::read(DONT_CARE_BYTE), + // ]; + + // let mut packet = Packet::new(); + // packet.resize(67, 0).unwrap(); + + // for &byte in &packet[4..] { + // expectations.push(SpiTransaction::send(byte)); + // expectations.push(SpiTransaction::read(DONT_CARE_BYTE)); + // } + + // // padding + // for _ in packet.len() as u32..64 { + // expectations.push(SpiTransaction::send(0x00)); + // expectations.push(SpiTransaction::read(DONT_CARE_BYTE)); + // } + + // // fcs + // for &byte in &[228, 218, 170, 232] { + // expectations.push(SpiTransaction::send(byte)); + // expectations.push(SpiTransaction::read(DONT_CARE_BYTE)); + // } + // let spi = SpiMock::new(&expectations); + + // let cs = CsPinMock {}; + // let mut spe = Adin1110::new(spi, cs, false); + + // assert!(spe.write_fifo(&mut packet).is_ok()); + // } + + #[futures_test::test] + async fn write_packet_to_fifo_arp_46bytes() { + // Configure expectations + let mut expectations = vec![]; + + let mut packet = Packet::new(); + //arp packet; + packet + .extend_from_slice(&[ + 34, 51, 68, 85, 102, 119, 18, 52, 86, 120, 154, 188, 8, 6, 0, 1, 8, 0, 6, 4, 0, 2, 18, 52, 86, 120, + 154, 188, 192, 168, 16, 4, 34, 51, 68, 85, 102, 119, 192, 168, 16, 1, + ]) + .unwrap(); + + let mut spi_packet = Packet::new(); + + // Write TX_SIZE reg + expectations.push(SpiTransaction::write_vec(vec![160, 48, 136, 0, 0, 0, 66, 201])); + expectations.push(SpiTransaction::flush()); + + // Write TX reg. + // Header + spi_packet.extend_from_slice(&[160, 49, 143, 0, 0]).unwrap(); + // Packet data + spi_packet.extend_from_slice(&packet).unwrap(); + // Packet padding up to 60 (64 - FCS) + for _ in packet.len() as u32..60 { + spi_packet.push(0x00).unwrap(); + } + // Packet FCS + spi_packet.extend_from_slice(&[147, 149, 213, 68]).unwrap(); + + // SPI HEADER Padding of u32 + for _ in spi_packet.len() as u32..size_align_u32(spi_packet.len() as u32) { + spi_packet.push(0x00).unwrap(); + } + + expectations.push(SpiTransaction::write_vec(spi_packet.to_vec())); + expectations.push(SpiTransaction::flush()); + + let mut spi = SpiMock::new(&expectations); + + let cs = CsPinMock::default(); + let delay = MockDelay {}; + let spi_dev = ExclusiveDevice::new(spi.clone(), cs, delay); + + let mut spe = ADIN1110::new(spi_dev, true); + + assert!(spe.write_fifo(&mut packet).await.is_ok()); + + spi.done(); + } +} diff --git a/embassy-net-adin1110/src/mdio.rs b/embassy-net-adin1110/src/mdio.rs new file mode 100644 index 00000000..ab7629d3 --- /dev/null +++ b/embassy-net-adin1110/src/mdio.rs @@ -0,0 +1,174 @@ +/// PHY Address: (0..=0x1F), 5-bits long. +#[allow(dead_code)] +type PhyAddr = u8; + +/// PHY Register: (0..=0x1F), 5-bits long. +#[allow(dead_code)] +type RegC22 = u8; + +/// PHY Register Clause 45. +#[allow(dead_code)] +type RegC45 = u16; + +/// PHY Register Value +#[allow(dead_code)] +type RegVal = u16; + +#[allow(dead_code)] +const REG13: RegC22 = 13; +#[allow(dead_code)] +const REG14: RegC22 = 14; + +#[allow(dead_code)] +const PHYADDR_MASK: u8 = 0x1f; +#[allow(dead_code)] +const DEV_MASK: u8 = 0x1f; + +#[allow(dead_code)] +#[repr(u16)] +enum Reg13Op { + Addr = 0b00 << 14, + Write = 0b01 << 14, + PostReadIncAddr = 0b10 << 14, + Read = 0b11 << 14, +} +/// MdioBus trait +/// Driver needs to implemnt the Claus 22 +/// Optional Clause 45 is the device supports this. +/// +/// Claus 45 methodes are bases on https://www.ieee802.org/3/efm/public/nov02/oam/pannell_oam_1_1102.pdf +pub trait MdioBus { + type Error; + + /// Read, Clause 22 + async fn read_cl22(&mut self, phy_id: PhyAddr, reg: RegC22) -> Result; + + /// Write, Clause 22 + async fn write_cl22(&mut self, phy_id: PhyAddr, reg: RegC22, reg_val: RegVal) -> Result<(), Self::Error>; + + /// Read, Clause 45 + /// This is the default implementation. + /// Many hardware these days support direct Clause 45 operations. + /// Implement this function when your hardware supports it. + async fn read_cl45(&mut self, phy_id: PhyAddr, regc45: (u8, RegC45)) -> Result { + // Write FN + let val = (Reg13Op::Addr as RegVal) | (regc45.0 & DEV_MASK) as RegVal; + self.write_cl22(phy_id, REG13, val).await?; + // Write Addr + self.write_cl22(phy_id, REG14, regc45.1).await?; + + // Write FN + let val = (Reg13Op::Read as RegVal) | (regc45.0 & DEV_MASK) as RegVal; + self.write_cl22(phy_id, REG13, val).await?; + // Write Addr + self.read_cl22(phy_id, REG14).await + } + + /// Write, Clause 45 + /// This is the default implementation. + /// Many hardware these days support direct Clause 45 operations. + /// Implement this function when your hardware supports it. + async fn write_cl45(&mut self, phy_id: PhyAddr, regc45: (u8, RegC45), reg_val: RegVal) -> Result<(), Self::Error> { + let dev_addr = (regc45.0 & DEV_MASK) as RegVal; + let reg = regc45.1; + + // Write FN + let val = (Reg13Op::Addr as RegVal) | dev_addr; + self.write_cl22(phy_id, REG13, val).await?; + // Write Addr + self.write_cl22(phy_id, REG14, reg).await?; + + // Write FN + let val = (Reg13Op::Write as RegVal) | dev_addr; + self.write_cl22(phy_id, REG13, val).await?; + // Write Addr + self.write_cl22(phy_id, REG14, reg_val).await + } +} + +// #[cfg(test)] +// mod tests { +// use core::convert::Infallible; + +// use super::{MdioBus, PhyAddr, RegC22, RegVal}; + +// #[derive(Debug, PartialEq, Eq)] +// enum A { +// Read(PhyAddr, RegC22), +// Write(PhyAddr, RegC22, RegVal), +// } + +// struct MockMdioBus(Vec); + +// impl MockMdioBus { +// pub fn clear(&mut self) { +// self.0.clear(); +// } +// } + +// impl MdioBus for MockMdioBus { +// type Error = Infallible; + +// fn write_cl22( +// &mut self, +// phy_id: super::PhyAddr, +// reg: super::RegC22, +// reg_val: super::RegVal, +// ) -> Result<(), Self::Error> { +// self.0.push(A::Write(phy_id, reg, reg_val)); +// Ok(()) +// } + +// fn read_cl22( +// &mut self, +// phy_id: super::PhyAddr, +// reg: super::RegC22, +// ) -> Result { +// self.0.push(A::Read(phy_id, reg)); +// Ok(0) +// } +// } + +// #[test] +// fn read_test() { +// let mut mdiobus = MockMdioBus(Vec::with_capacity(20)); + +// mdiobus.clear(); +// mdiobus.read_cl22(0x01, 0x00).unwrap(); +// assert_eq!(mdiobus.0, vec![A::Read(0x01, 0x00)]); + +// mdiobus.clear(); +// mdiobus.read_cl45(0x01, (0xBB, 0x1234)).unwrap(); +// assert_eq!( +// mdiobus.0, +// vec![ +// #[allow(clippy::identity_op)] +// A::Write(0x01, 13, (0b00 << 14) | 27), +// A::Write(0x01, 14, 0x1234), +// A::Write(0x01, 13, (0b11 << 14) | 27), +// A::Read(0x01, 14) +// ] +// ); +// } + +// #[test] +// fn write_test() { +// let mut mdiobus = MockMdioBus(Vec::with_capacity(20)); + +// mdiobus.clear(); +// mdiobus.write_cl22(0x01, 0x00, 0xABCD).unwrap(); +// assert_eq!(mdiobus.0, vec![A::Write(0x01, 0x00, 0xABCD)]); + +// mdiobus.clear(); +// mdiobus.write_cl45(0x01, (0xBB, 0x1234), 0xABCD).unwrap(); +// assert_eq!( +// mdiobus.0, +// vec![ +// A::Write(0x01, 13, 27), +// A::Write(0x01, 14, 0x1234), +// A::Write(0x01, 13, (0b01 << 14) | 27), +// A::Write(0x01, 14, 0xABCD) +// ] +// ); +// } +// } diff --git a/embassy-net-adin1110/src/phy.rs b/embassy-net-adin1110/src/phy.rs new file mode 100644 index 00000000..78d3fdf7 --- /dev/null +++ b/embassy-net-adin1110/src/phy.rs @@ -0,0 +1,137 @@ +use crate::mdio::MdioBus; + +#[allow(dead_code, non_camel_case_types, clippy::upper_case_acronyms)] +#[repr(u8)] +/// Clause 22 Registers +pub enum RegsC22 { + /// MII Control Register + CONTROL = 0x00, + /// MII Status Register + STATUS = 0x01, + /// PHY Identifier 1 Register + PHY_ID1 = 0x02, + /// PHY Identifier 2 Register. + PHY_ID2 = 0x03, +} + +/// Clause 45 Registers +#[allow(non_snake_case, dead_code)] +pub mod RegsC45 { + /// Device Address: 0x01 + #[allow(non_camel_case_types, clippy::upper_case_acronyms)] + #[repr(u16)] + pub enum DA1 { + /// PMA/PMD Control 1 Register + PMA_PMD_CNTRL1 = 0x0000, + /// PMA/PMD Status 1 Register + PMA_PMD_STAT1 = 0x0001, + /// MSE Value Register + MSE_VAL = 0x830B, + } + + impl DA1 { + pub fn into(self) -> (u8, u16) { + (0x01, self as u16) + } + } + + /// Device Address: 0x03 + #[allow(non_camel_case_types, clippy::upper_case_acronyms)] + #[repr(u16)] + pub enum DA3 { + /// PCS Control 1 Register + PCS_CNTRL1 = 0x0000, + /// PCS Status 1 Register + PCS_STAT1 = 0x0001, + /// PCS Status 2 Register + PCS_STAT2 = 0x0008, + } + + impl DA3 { + pub fn into(self) -> (u8, u16) { + (0x03, self as u16) + } + } + + /// Device Address: 0x07 + #[allow(non_camel_case_types, clippy::upper_case_acronyms)] + #[repr(u16)] + pub enum DA7 { + /// Extra Autonegotiation Status Register + AN_STATUS_EXTRA = 0x8001, + } + + impl DA7 { + pub fn into(self) -> (u8, u16) { + (0x07, self as u16) + } + } + + /// Device Address: 0x1E + #[allow(non_camel_case_types, clippy::upper_case_acronyms)] + #[repr(u16)] + pub enum DA1E { + /// System Interrupt Status Register + CRSM_IRQ_STATUS = 0x0010, + /// System Interrupt Mask Register + CRSM_IRQ_MASK = 0x0020, + /// Pin Mux Configuration 1 Register + DIGIO_PINMUX = 0x8c56, + /// LED Control Register. + LED_CNTRL = 0x8C82, + /// LED Polarity Register + LED_POLARITY = 0x8C83, + } + + impl DA1E { + pub fn into(self) -> (u8, u16) { + (0x1e, self as u16) + } + } + + /// Device Address: 0x1F + #[allow(non_camel_case_types, clippy::upper_case_acronyms)] + #[repr(u16)] + pub enum DA1F { + /// PHY Subsystem Interrupt Status Register + PHY_SYBSYS_IRQ_STATUS = 0x0011, + /// PHY Subsystem Interrupt Mask Register + PHY_SYBSYS_IRQ_MASK = 0x0021, + } + + impl DA1F { + pub fn into(self) -> (u8, u16) { + (0x1f, self as u16) + } + } +} + +pub struct Phy10BaseT1x(u8); + +impl Default for Phy10BaseT1x { + fn default() -> Self { + Self(0x01) + } +} + +impl Phy10BaseT1x { + /// Get the both parts of the PHYID. + pub async fn get_id(&self, mdiobus: &mut MDIOBUS) -> Result + where + MDIOBUS: MdioBus, + MDE: core::fmt::Debug, + { + let mut phyid = (mdiobus.read_cl22(self.0, RegsC22::PHY_ID1 as u8).await? as u32) << 16; + phyid |= mdiobus.read_cl22(self.0, RegsC22::PHY_ID2 as u8).await? as u32; + Ok(phyid) + } + + /// Get the Mean Squared Error Value. + pub async fn get_sqi(&self, mdiobus: &mut MDIOBUS) -> Result + where + MDIOBUS: MdioBus, + MDE: core::fmt::Debug, + { + mdiobus.read_cl45(self.0, RegsC45::DA1::MSE_VAL.into()).await + } +} diff --git a/embassy-net-adin1110/src/regs.rs b/embassy-net-adin1110/src/regs.rs new file mode 100644 index 00000000..93ce812d --- /dev/null +++ b/embassy-net-adin1110/src/regs.rs @@ -0,0 +1,407 @@ +use bitfield::{bitfield, bitfield_bitrange, bitfield_fields}; + +#[allow(non_camel_case_types)] +#[derive(Debug, Copy, Clone)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[repr(u16)] +/// SPI REGISTER DETAILS +/// Table 38. +pub enum SpiRegisters { + IDVER = 0x00, + PHYID = 0x01, + CAPABILITY = 0x02, + RESET = 0x03, + CONFIG0 = 0x04, + CONFIG2 = 0x06, + STATUS0 = 0x08, + STATUS1 = 0x09, + IMASK0 = 0x0C, + IMASK1 = 0x0D, + MDIO_ACC = 0x20, + TX_FSIZE = 0x30, + TX = 0x31, + TX_SPACE = 0x32, + FIFO_CLR = 0x36, + ADDR_FILT_UPR0 = 0x50, + ADDR_FILT_LWR0 = 0x51, + ADDR_FILT_UPR1 = 0x52, + ADDR_FILT_LWR1 = 0x53, + ADDR_MSK_LWR0 = 0x70, + ADDR_MSK_UPR0 = 0x71, + ADDR_MSK_LWR1 = 0x72, + ADDR_MSK_UPR1 = 0x73, + RX_FSIZE = 0x90, + RX = 0x91, +} + +impl From for u16 { + fn from(val: SpiRegisters) -> Self { + val as u16 + } +} + +impl From for SpiRegisters { + fn from(value: u16) -> Self { + match value { + 0x00 => Self::IDVER, + 0x01 => Self::PHYID, + 0x02 => Self::CAPABILITY, + 0x03 => Self::RESET, + 0x04 => Self::CONFIG0, + 0x06 => Self::CONFIG2, + 0x08 => Self::STATUS0, + 0x09 => Self::STATUS1, + 0x0C => Self::IMASK0, + 0x0D => Self::IMASK1, + 0x20 => Self::MDIO_ACC, + 0x30 => Self::TX_FSIZE, + 0x31 => Self::TX, + 0x32 => Self::TX_SPACE, + 0x36 => Self::FIFO_CLR, + 0x50 => Self::ADDR_FILT_UPR0, + 0x51 => Self::ADDR_FILT_LWR0, + 0x52 => Self::ADDR_FILT_UPR1, + 0x53 => Self::ADDR_FILT_LWR1, + 0x70 => Self::ADDR_MSK_LWR0, + 0x71 => Self::ADDR_MSK_UPR0, + 0x72 => Self::ADDR_MSK_LWR1, + 0x73 => Self::ADDR_MSK_UPR1, + 0x90 => Self::RX_FSIZE, + 0x91 => Self::RX, + e => panic!("Unknown value {e}"), + } + } +} + +// Register definitions + +bitfield! { + /// Status0 Register bits + pub struct Status0(u32); + impl Debug; + u32; + /// Control Data Protection Error + pub cdpe, _ : 12; + /// Transmit Frame Check Squence Error + pub txfcse, _: 11; + /// Transmit Time Stamp Capture Available C + pub ttscac, _ : 10; + /// Transmit Time Stamp Capture Available B + pub ttscab, _ : 9; + /// Transmit Time Stamp Capture Available A + pub ttscaa, _ : 8; + /// PHY Interrupt for Port 1 + pub phyint, _ : 7; + /// Reset Complete + pub resetc, _ : 6; + /// Header error + pub hdre, _ : 5; + /// Loss of Frame Error + pub lofe, _ : 4; + /// Receiver Buffer Overflow Error + pub rxboe, _ : 3; + /// Host Tx FIFO Under Run Error + pub txbue, _ : 2; + /// Host Tx FIFO Overflow + pub txboe, _ : 1; + /// Transmit Protocol Error + pub txpe, _ : 0; +} + +bitfield! { + /// Status1 Register bits + pub struct Status1(u32); + impl Debug; + u32; + /// ECC Error on Reading the Frame Size from a Tx FIFO + pub tx_ecc_err, set_tx_ecc_err: 12; + /// ECC Error on Reading the Frame Size from an Rx FIFO + pub rx_ecc_err, set_rx_ecc_err : 11; + /// Detected an Error on an SPI Transaction + pub spi_err, set_spi_err: 10; + /// Rx MAC Interframe Gap Error + pub p1_rx_ifg_err, set_p1_rx_ifg_err : 8; + /// Port1 Rx Ready High Priority + pub p1_rx_rdy_hi, set_p1_rx_rdy_hi : 5; + /// Port 1 Rx FIFO Contains Data + pub p1_rx_rdy, set_p1_rx_rdy : 4; + /// Tx Ready + pub tx_rdy, set_tx_rdy : 3; + /// Link Status Changed + pub link_change, set_link_change : 1; + /// Port 1 Link Status + pub p1_link_status, _ : 0; +} + +bitfield! { + /// Config0 Register bits + pub struct Config0(u32); + impl Debug; + u32; + /// Configuration Synchronization + pub sync, set_sync : 15; + /// Transmit Frame Check Sequence Validation Enable + pub txfcsve, set_txfcsve : 14; + /// !CS Align Receive Frame Enable + pub csarfe, set_csarfe : 13; + /// Zero Align Receive Frame Enable + pub zarfe, set_zarfe : 12; + /// Transmit Credit Threshold + pub tcxthresh, set_tcxthresh : 11, 10; + /// Transmit Cut Through Enable + pub txcte, set_txcte : 9; + /// Receive Cut Through Enable + pub rxcte, set_rxcte : 8; + /// Frame Time Stamp Enable + pub ftse, set_ftse : 7; + /// Receive Frame Time Stamp Select + pub ftss, set_ftss : 6; + /// Enable Control Data Read Write Protection + pub prote, set_prote : 5; + /// Enable TX Data Chunk Sequence and Retry + pub seqe, set_seqe : 4; + /// Chunk Payload Selector (N). + pub cps, set_cps : 2, 0; +} + +bitfield! { + /// Config2 Register bits + pub struct Config2(u32); + impl Debug; + u32; + /// Assert TX_RDY When the Tx FIFO is Empty + pub tx_rdy_on_empty, set_tx_rdy_on_empty : 8; + /// Determines If the SFD is Detected in the PHY or MAC + pub sdf_detect_src, set_sdf_detect_src : 7; + /// Statistics Clear on Reading + pub stats_clr_on_rd, set_stats_clr_on_rd : 6; + /// Enable CRC Append + pub crc_append, set_crc_append : 5; + /// Admit Frames with IFG Errors on Port 1 (P1) + pub p1_rcv_ifg_err_frm, set_p1_rcv_ifg_err_frm : 4; + /// Forward Frames Not Matching Any MAC Address to the Host + pub p1_fwd_unk2host, set_p1_fwd_unk2host : 2; + /// SPI to MDIO Bridge MDC Clock Speed + pub mspeed, set_mspeed : 0; +} + +bitfield! { + /// IMASK0 Register bits + pub struct IMask0(u32); + impl Debug; + u32; + /// Control Data Protection Error Mask + pub cppem, set_cppem : 12; + /// Transmit Frame Check Sequence Error Mask + pub txfcsem, set_txfcsem : 11; + /// Transmit Time Stamp Capture Available C Mask + pub ttscacm, set_ttscacm : 10; + /// Transmit Time Stamp Capture Available B Mask + pub ttscabm, set_ttscabm : 9; + /// Transmit Time Stamp Capture Available A Mask + pub ttscaam, set_ttscaam : 8; + /// Physical Layer Interrupt Mask + pub phyintm, set_phyintm : 7; + /// RESET Complete Mask + pub resetcm, set_resetcm : 6; + /// Header Error Mask + pub hdrem, set_hdrem : 5; + /// Loss of Frame Error Mask + pub lofem, set_lofem : 4; + /// Receive Buffer Overflow Error Mask + pub rxboem, set_rxboem : 3; + /// Transmit Buffer Underflow Error Mask + pub txbuem, set_txbuem : 2; + /// Transmit Buffer Overflow Error Mask + pub txboem, set_txboem : 1; + /// Transmit Protocol Error Mask + pub txpem, set_txpem : 0; +} + +bitfield! { + /// IMASK1 Register bits + pub struct IMask1(u32); + impl Debug; + u32; + /// Mask Bit for TXF_ECC_ERR + pub tx_ecc_err_mask, set_tx_ecc_err_mask : 12; + /// Mask Bit for RXF_ECC_ERR + pub rx_ecc_err_mask, set_rx_ecc_err_mask : 11; + /// Mask Bit for SPI_ERR + /// This field is only used with the generic SPI protocol + pub spi_err_mask, set_spi_err_mask : 10; + /// Mask Bit for RX_IFG_ERR + pub p1_rx_ifg_err_mask, set_p1_rx_ifg_err_mask : 8; + /// Mask Bit for P1_RX_RDY + /// This field is only used with the generic SPI protocol + pub p1_rx_rdy_mask, set_p1_rx_rdy_mask : 4; + /// Mask Bit for TX_FRM_DONE + /// This field is only used with the generic SPI protocol + pub tx_rdy_mask, set_tx_rdy_mask : 3; + /// Mask Bit for LINK_CHANGE + pub link_change_mask, set_link_change_mask : 1; +} + +#[repr(u8)] +pub enum LedFunc { + LinkupTxRxActicity = 0, + LinkupTxActicity, + LinkupRxActicity, + LinkupOnly, + TxRxActivity, + TxActivity, + RxActivity, + LinkupRxEr, + LinkupRxTxEr, + RxEr, + RxTxEr, + TxSop, + RxSop, + On, + Off, + Blink, + TxLevel2P4, + TxLevel1P0, + Master, + Slave, + IncompatiableLinkCfg, + AnLinkGood, + AnComplete, + TsTimer, + LocRcvrStatus, + RemRcvrStatus, + Clk25Ref, + TxTCLK, + Clk120MHz, +} + +impl From for u8 { + fn from(val: LedFunc) -> Self { + val as u8 + } +} + +impl From for LedFunc { + fn from(value: u8) -> Self { + match value { + 0 => LedFunc::LinkupTxRxActicity, + 1 => LedFunc::LinkupTxActicity, + 2 => LedFunc::LinkupRxActicity, + 3 => LedFunc::LinkupOnly, + 4 => LedFunc::TxRxActivity, + 5 => LedFunc::TxActivity, + 6 => LedFunc::RxActivity, + 7 => LedFunc::LinkupRxEr, + 8 => LedFunc::LinkupRxTxEr, + 9 => LedFunc::RxEr, + 10 => LedFunc::RxTxEr, + 11 => LedFunc::TxSop, + 12 => LedFunc::RxSop, + 13 => LedFunc::On, + 14 => LedFunc::Off, + 15 => LedFunc::Blink, + 16 => LedFunc::TxLevel2P4, + 17 => LedFunc::TxLevel1P0, + 18 => LedFunc::Master, + 19 => LedFunc::Slave, + 20 => LedFunc::IncompatiableLinkCfg, + 21 => LedFunc::AnLinkGood, + 22 => LedFunc::AnComplete, + 23 => LedFunc::TsTimer, + 24 => LedFunc::LocRcvrStatus, + 25 => LedFunc::RemRcvrStatus, + 26 => LedFunc::Clk25Ref, + 27 => LedFunc::TxTCLK, + 28 => LedFunc::Clk120MHz, + e => panic!("Invalid value {e}"), + } + } +} + +/// LED Control Register +#[derive(Copy, Clone, PartialEq, Eq, Hash)] +pub struct LedCntrl(pub u16); +bitfield_bitrange! {struct LedCntrl(u16)} + +impl LedCntrl { + bitfield_fields! { + u8; + /// LED_0 Pin Function + pub from into LedFunc, led0_function, set_led0_function: 4, 0; + /// LED 0 Mode Selection + pub led0_mode, set_led0_mode: 5; + /// Qualify Certain LED 0 Options with Link Status. + pub led0_link_st_qualify, set_led0_link_st_qualify: 6; + /// LED 0 Enable + pub led0_en, set_led0_en: 7; + /// LED_1 Pin Function + pub from into LedFunc, led1_function, set_led1_function: 12, 8; + /// /// LED 1 Mode Selection + pub led1_mode, set_led1_mode: 13; + /// Qualify Certain LED 1 Options with Link Status. + pub led1_link_st_qualify, set_led1_link_st_qualify: 14; + /// LED 1 Enable + pub led1_en, set_led1_en: 15; + } + + pub fn new() -> Self { + LedCntrl(0) + } +} + +// #[allow(dead_code)] +#[repr(u8)] +pub enum LedPol { + AutoSense = 0, + ActiveHigh, + ActiveLow, +} + +impl From for u8 { + fn from(val: LedPol) -> Self { + val as u8 + } +} + +impl From for LedPol { + fn from(value: u8) -> Self { + match value { + 0 => LedPol::AutoSense, + 1 => LedPol::ActiveHigh, + 2 => LedPol::ActiveLow, + e => panic!("Invalid value {e}"), + } + } +} + +/// LED Control Register +#[derive(Copy, Clone, PartialEq, Eq, Hash)] +pub struct LedPolarity(pub u16); +bitfield_bitrange! {struct LedPolarity(u16)} + +impl LedPolarity { + bitfield_fields! { + u8; + /// LED 1 Polarity + pub from into LedPol, led1_polarity, set_led1_polarity: 3, 2; + /// LED_0 Polarity + pub from into LedPol, led0_polarity, set_led0_polarity: 1, 0; + } +} + +/// LED Control Register +#[derive(Copy, Clone, PartialEq, Eq, Hash)] +pub struct SpiHeader(pub u16); +bitfield_bitrange! {struct SpiHeader(u16)} + +impl SpiHeader { + bitfield_fields! { + u16; + /// Mask Bit for TXF_ECC_ERR + pub control, set_control : 15; + pub full_duplex, set_full_duplex : 14; + pub write, set_write : 13; + /// LED_0 Polarity + pub from into SpiRegisters, addr, set_addr: 11, 0; + } +} From 2cf6a5911408ff0a666f915e32fac7bc6b9fb5d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20van=20Dorst?= Date: Thu, 24 Aug 2023 00:45:15 +0200 Subject: [PATCH 029/106] stm32l4: Add EVAL-ADIN1110EBZ example with basic http server Page show the current temperature and auto refresh every 1s. --- examples/stm32l4/.cargo/config.toml | 2 +- examples/stm32l4/Cargo.toml | 12 +- .../src/bin/spe_adin1110_http_server.rs | 438 ++++++++++++++++++ 3 files changed, 449 insertions(+), 3 deletions(-) create mode 100644 examples/stm32l4/src/bin/spe_adin1110_http_server.rs diff --git a/examples/stm32l4/.cargo/config.toml b/examples/stm32l4/.cargo/config.toml index 36e74e5a..db3a7cef 100644 --- a/examples/stm32l4/.cargo/config.toml +++ b/examples/stm32l4/.cargo/config.toml @@ -2,7 +2,7 @@ # replace STM32F429ZITx with your chip as listed in `probe-rs chip list` #runner = "probe-rs run --chip STM32L475VGT6" #runner = "probe-rs run --chip STM32L475VG" -runner = "probe-rs run --chip STM32L4S5VI" +runner = "probe-run --chip STM32L4S5QI" [build] target = "thumbv7em-none-eabi" diff --git a/examples/stm32l4/Cargo.toml b/examples/stm32l4/Cargo.toml index f552a610..e5be94ed 100644 --- a/examples/stm32l4/Cargo.toml +++ b/examples/stm32l4/Cargo.toml @@ -6,12 +6,17 @@ 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-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "unstable-pac", "stm32l4s5qi", "memory-x", "time-driver-any", "exti", "unstable-traits", "chrono"] } embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.3.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-time = { version = "0.1.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768", "unstable-traits", "nightly"] } embassy-embedded-hal = { version = "0.1.0", path = "../../embassy-embedded-hal" } embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] } +embassy-net-adin1110 = { version = "0.1.0", path = "../../embassy-net-adin1110", default-features = false } +embassy-net = { version = "0.1.0", path = "../../embassy-net", features = ["defmt", "nightly", "udp", "tcp", "dhcpv4", "medium-ethernet"] } +embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } +embedded-io-async = { version = "0.5.0", features = ["defmt-03"] } +embedded-io = { version = "0.5.0", features = ["defmt-03"] } defmt = "0.3" defmt-rtt = "0.4" @@ -21,10 +26,13 @@ cortex-m-rt = "0.7.0" embedded-hal = "0.2.6" embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-rc.1" } embedded-hal-async = { version = "=1.0.0-rc.1" } +embedded-hal-bus = { version = "=0.1.0-rc.1", features = ["async"] } 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 } chrono = { version = "^0.4", default-features = false } +rand = { version = "0.8.5", default-features = false } +static_cell = {version = "1.1", features = ["nightly"]} micromath = "2.0.0" diff --git a/examples/stm32l4/src/bin/spe_adin1110_http_server.rs b/examples/stm32l4/src/bin/spe_adin1110_http_server.rs new file mode 100644 index 00000000..148c5877 --- /dev/null +++ b/examples/stm32l4/src/bin/spe_adin1110_http_server.rs @@ -0,0 +1,438 @@ +#![deny(clippy::pedantic)] +#![allow(clippy::doc_markdown)] +#![no_main] +#![no_std] +// Needed unitl https://github.com/rust-lang/rust/issues/63063 is stablised. +#![feature(type_alias_impl_trait)] +#![feature(associated_type_bounds)] +#![allow(clippy::missing_errors_doc)] + +// This example works on a ANALOG DEVICE EVAL-ADIN110EBZ board. +// Settings switch S201 "HW CFG": +// - Without SPI CRC: OFF-ON-OFF-OFF-OFF +// - With SPI CRC: ON -ON-OFF-OFF-OFF +// Settings switch S303 "uC CFG": CFG0: On = static ip, Off = Dhcp +// The webserver shows the actual temperature of the onboard i2c temp sensor. + +use core::marker::PhantomData; +use core::sync::atomic::{AtomicI32, Ordering}; + +use defmt::{error, info, println, unwrap, Format}; +use defmt_rtt as _; // global logger +use embassy_executor::Spawner; +use embassy_futures::select::{select, Either}; +use embassy_futures::yield_now; +use embassy_net::tcp::TcpSocket; +use embassy_net::{Ipv4Address, Ipv4Cidr, Stack, StackResources, StaticConfigV4}; +use embassy_time::{Delay, Duration, Ticker, Timer}; +use embedded_hal_async::i2c::I2c as I2cBus; +use embedded_io::Write as bWrite; +use embedded_io_async::Write; +use hal::gpio::{Input, Level, Output, Speed}; +use hal::i2c::{self, I2c}; +use hal::rcc::{self}; +use hal::rng::{self, Rng}; +use hal::{bind_interrupts, exti, pac, peripherals}; +use heapless::Vec; +use rand::RngCore; +use static_cell::make_static; +use {embassy_stm32 as hal, panic_probe as _}; + +bind_interrupts!(struct Irqs { + I2C3_EV => i2c::InterruptHandler; + RNG => rng::InterruptHandler; +}); + +use embassy_net_adin1110::{self, Device, Runner, ADIN1110}; +use embedded_hal_bus::spi::ExclusiveDevice; +use hal::gpio::Pull; +use hal::i2c::Config as I2C_Config; +use hal::rcc::{ClockSrc, PLLClkDiv, PLLMul, PLLSource, PLLSrcDiv}; +use hal::spi::{Config as SPI_Config, Spi}; +use hal::time::Hertz; + +// Basic settings +// MAC-address used by the adin1110 +const MAC: [u8; 6] = [0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff]; +// Static IP settings +const IP_ADDRESS: Ipv4Cidr = Ipv4Cidr::new(Ipv4Address([192, 168, 1, 5]), 24); +// Listen port for the webserver +const HTTP_LISTEN_PORT: u16 = 80; + +pub type SpeSpi = Spi<'static, peripherals::SPI2, peripherals::DMA1_CH1, peripherals::DMA1_CH2>; +pub type SpeSpiCs = ExclusiveDevice, Delay>; +pub type SpeInt = exti::ExtiInput<'static, peripherals::PB11>; +pub type SpeRst = Output<'static, peripherals::PC7>; +pub type Adin1110T = ADIN1110; +pub type TempSensI2c = I2c<'static, peripherals::I2C3, peripherals::DMA1_CH6, peripherals::DMA1_CH7>; + +static TEMP: AtomicI32 = AtomicI32::new(0); + +#[embassy_executor::main] +async fn main(spawner: Spawner) { + defmt::println!("Start main()"); + + let mut config = embassy_stm32::Config::default(); + + // 80Mhz clock (Source: 8 / SrcDiv: 1 * PLLMul 20 / ClkDiv 2) + // 80MHz highest frequency for flash 0 wait. + config.rcc.mux = ClockSrc::PLL( + PLLSource::HSE(Hertz(8_000_000)), + PLLClkDiv::Div2, + PLLSrcDiv::Div1, + PLLMul::Mul20, + None, + ); + config.rcc.hsi48 = true; // needed for rng + config.rcc.rtc_mux = rcc::RtcClockSource::LSI32; + + let dp = embassy_stm32::init(config); + + // RM0432rev9, 5.1.2: Independent I/O supply rail + // After reset, the I/Os supplied by VDDIO2 are logically and electrically isolated and + // therefore are not available. The isolation must be removed before using any I/O from + // PG[15:2], by setting the IOSV bit in the PWR_CR2 register, once the VDDIO2 supply is present + pac::PWR.cr2().modify(|w| w.set_iosv(true)); + + let reset_status = pac::RCC.bdcr().read().0; + defmt::println!("bdcr before: 0x{:X}", reset_status); + + defmt::println!("Setup IO pins"); + + // Setup LEDs + let _led_uc1_green = Output::new(dp.PC13, Level::Low, Speed::Low); + let mut led_uc2_red = Output::new(dp.PE2, Level::High, Speed::Low); + let led_uc3_yellow = Output::new(dp.PE6, Level::High, Speed::Low); + let led_uc4_blue = Output::new(dp.PG15, Level::High, Speed::Low); + + // Read the uc_cfg switches + let uc_cfg0 = Input::new(dp.PB2, Pull::None); + let _uc_cfg1 = Input::new(dp.PF11, Pull::None); + let _uc_cfg2 = Input::new(dp.PG6, Pull::None); + let _uc_cfg3 = Input::new(dp.PG11, Pull::None); + + // Setup I2C pins + let temp_sens_i2c = I2c::new( + dp.I2C3, + dp.PG7, + dp.PG8, + Irqs, + dp.DMA1_CH6, + dp.DMA1_CH7, + Hertz(100_000), + I2C_Config::default(), + ); + + // Setup IO and SPI for the SPE chip + let spe_reset_n = Output::new(dp.PC7, Level::Low, Speed::Low); + let spe_cfg0 = Input::new(dp.PC8, Pull::None); + let spe_cfg1 = Input::new(dp.PC9, Pull::None); + let _spe_ts_capt = Output::new(dp.PC6, Level::Low, Speed::Low); + + let spe_int = Input::new(dp.PB11, Pull::None); + let spe_int = exti::ExtiInput::new(spe_int, dp.EXTI11); + + let spe_spi_cs_n = Output::new(dp.PB12, Level::High, Speed::High); + let spe_spi_sclk = dp.PB13; + let spe_spi_miso = dp.PB14; + let spe_spi_mosi = dp.PB15; + + // Don't turn the clock to high, clock must fit within the system clock as we get a runtime panic. + let mut spi_config = SPI_Config::default(); + spi_config.frequency = Hertz(25_000_000); + + let spe_spi: SpeSpi = Spi::new( + dp.SPI2, + spe_spi_sclk, + spe_spi_mosi, + spe_spi_miso, + dp.DMA1_CH1, + dp.DMA1_CH2, + spi_config, + ); + let spe_spi = SpeSpiCs::new(spe_spi, spe_spi_cs_n, Delay); + + let cfg0_without_crc = spe_cfg0.is_high(); + let cfg1_spi_mode = spe_cfg1.is_high(); + + defmt::println!( + "ADIN1110: CFG SPI-MODE 1-{}, CRC-bit 0-{}", + cfg1_spi_mode, + cfg0_without_crc + ); + + // Check the SPI mode selected with the "HW CFG" dip-switch + if !cfg1_spi_mode { + error!("Driver doesn´t support SPI Protolcol \"OPEN Alliance\".\nplease use the \"Generic SPI\"! Turn On \"HW CFG\": \"SPI_CFG1\""); + loop { + led_uc2_red.toggle(); + Timer::after(Duration::from_hz(10)).await; + } + }; + + let state = make_static!(embassy_net_adin1110::State::<8, 8>::new()); + + let (device, runner) = + embassy_net_adin1110::new(MAC, state, spe_spi, spe_int, spe_reset_n, !cfg0_without_crc).await; + + // Start task blink_led + unwrap!(spawner.spawn(heartbeat_led(led_uc3_yellow))); + // Start task temperature measurement + unwrap!(spawner.spawn(temp_task(temp_sens_i2c, led_uc4_blue))); + // Start ethernet task + unwrap!(spawner.spawn(ethernet_task(runner))); + + let mut rng = Rng::new(dp.RNG, Irqs); + // Generate random seed + let seed = rng.next_u64(); + + let ip_cfg = if uc_cfg0.is_low() { + println!("Waiting for DHCP..."); + let dhcp4_config = embassy_net::DhcpConfig::default(); + embassy_net::Config::dhcpv4(dhcp4_config) + } else { + embassy_net::Config::ipv4_static(StaticConfigV4 { + address: IP_ADDRESS, + gateway: None, + dns_servers: Vec::new(), + }) + }; + + // Init network stack + let stack = &*make_static!(Stack::new( + device, + ip_cfg, + make_static!(StackResources::<2>::new()), + seed + )); + + // Launch network task + unwrap!(spawner.spawn(net_task(stack))); + + let cfg = wait_for_config(stack).await; + let local_addr = cfg.address.address(); + + // Then we can use it! + let mut rx_buffer = [0; 4096]; + let mut tx_buffer = [0; 4096]; + let mut mb_buf = [0; 4096]; + loop { + let mut socket = TcpSocket::new(stack, &mut rx_buffer, &mut tx_buffer); + socket.set_timeout(Some(Duration::from_secs(1))); + + info!("Listening on http://{}:{}...", local_addr, HTTP_LISTEN_PORT); + if let Err(e) = socket.accept(HTTP_LISTEN_PORT).await { + defmt::error!("accept error: {:?}", e); + continue; + } + + loop { + let _n = match socket.read(&mut mb_buf).await { + Ok(0) => { + defmt::info!("read EOF"); + break; + } + Ok(n) => n, + Err(e) => { + defmt::error!("{:?}", e); + break; + } + }; + led_uc2_red.set_low(); + + let status_line = "HTTP/1.1 200 OK"; + let contents = PAGE; + let length = contents.len(); + + let _ = write!( + &mut mb_buf[..], + "{status_line}\r\nContent-Length: {length}\r\n\r\n{contents}\r\n\0" + ); + let loc = mb_buf.iter().position(|v| *v == b'#').unwrap(); + + let temp = TEMP.load(Ordering::Relaxed); + let cel = temp / 1000; + let mcel = temp % 1000; + + info!("{}.{}", cel, mcel); + + let _ = write!(&mut mb_buf[loc..loc + 7], "{cel}.{mcel}"); + + let n = mb_buf.iter().position(|v| *v == 0).unwrap(); + + if let Err(e) = socket.write_all(&mb_buf[..n]).await { + error!("write error: {:?}", e); + break; + } + + led_uc2_red.set_high(); + } + } +} + +async fn wait_for_config(stack: &'static Stack>) -> embassy_net::StaticConfigV4 { + loop { + if let Some(config) = stack.config_v4() { + return config; + } + yield_now().await; + } +} + +#[embassy_executor::task] +async fn heartbeat_led(mut led: Output<'static, peripherals::PE6>) { + let mut tmr = Ticker::every(Duration::from_hz(3)); + loop { + led.toggle(); + tmr.next().await; + } +} + +// ADT7422 +#[embassy_executor::task] +async fn temp_task(temp_dev_i2c: TempSensI2c, mut led: Output<'static, peripherals::PG15>) -> ! { + let mut tmr = Ticker::every(Duration::from_hz(1)); + let mut temp_sens = ADT7422::new(temp_dev_i2c, 0x48).unwrap(); + + loop { + led.set_low(); + match select(temp_sens.read_temp(), Timer::after(Duration::from_millis(500))).await { + Either::First(i2c_ret) => match i2c_ret { + Ok(value) => { + led.set_high(); + let temp = i32::from(value); + println!("TEMP: {:04x}, {}", temp, temp * 78 / 10); + TEMP.store(temp * 78 / 10, Ordering::Relaxed); + } + Err(e) => defmt::println!("ADT7422: {}", e), + }, + Either::Second(_) => println!("Timeout"), + } + + tmr.next().await; + } +} + +#[embassy_executor::task] +async fn ethernet_task(runner: Runner<'static, SpeSpiCs, SpeInt, SpeRst>) -> ! { + runner.run().await +} + +#[embassy_executor::task] +async fn net_task(stack: &'static Stack>) -> ! { + stack.run().await +} + +// same panicking *behavior* as `panic-probe` but doesn't print a panic message +// this prevents the panic message being printed *twice* when `defmt::panic` is invoked +#[defmt::panic_handler] +fn panic() -> ! { + cortex_m::asm::udf() +} + +#[allow(non_camel_case_types)] +#[repr(C)] +pub enum Registers { + Temp_MSB = 0x00, + Temp_LSB, + Status, + Cfg, + T_HIGH_MSB, + T_HIGH_LSB, + T_LOW_MSB, + T_LOW_LSB, + T_CRIT_MSB, + T_CRIT_LSB, + T_HYST, + ID, + SW_RESET = 0x2F, +} + +pub struct ADT7422<'d, BUS: I2cBus> { + addr: u8, + phantom: PhantomData<&'d ()>, + bus: BUS, +} + +#[derive(Debug, Format)] +pub enum Error { + I2c(I2cError), + Address, +} + +impl<'d, BUS> ADT7422<'d, BUS> +where + BUS: I2cBus, + BUS::Error: Format, +{ + pub fn new(bus: BUS, addr: u8) -> Result> { + if !(0x48..=0x4A).contains(&addr) { + return Err(Error::Address); + } + + Ok(Self { + bus, + phantom: PhantomData, + addr, + }) + } + + pub async fn init(&mut self) -> Result<(), Error> { + let mut cfg = 0b000_0000; + // if self.int.is_some() { + // // Set 1 SPS mode + // cfg |= 0b10 << 5; + // } else { + // One shot mode + cfg |= 0b01 << 5; + // } + + self.write_cfg(cfg).await + } + + pub async fn read(&mut self, reg: Registers) -> Result> { + let mut buffer = [0u8; 1]; + self.bus + .write_read(self.addr, &[reg as u8], &mut buffer) + .await + .map_err(Error::I2c)?; + Ok(buffer[0]) + } + + pub async fn write_cfg(&mut self, cfg: u8) -> Result<(), Error> { + let buf = [Registers::Cfg as u8, cfg]; + self.bus.write(self.addr, &buf).await.map_err(Error::I2c) + } + + pub async fn read_temp(&mut self) -> Result> { + let mut buffer = [0u8; 2]; + + // if let Some(int) = &mut self.int { + // // Wait for interrupt + // int.wait_for_low().await.unwrap(); + // } else { + // Start: One shot + let cfg = 0b01 << 5; + self.write_cfg(cfg).await?; + Timer::after(Duration::from_millis(250)).await; + self.bus + .write_read(self.addr, &[Registers::Temp_MSB as u8], &mut buffer) + .await + .map_err(Error::I2c)?; + Ok(i16::from_be_bytes(buffer)) + } +} + +// Web page +const PAGE: &str = r#" + + + + + ADIN1110 with Rust + + +

EVAL-ADIN1110EBZ

+
Temp Sensor ADT7422: #00.00 °C
+ +"#; From 577d644e2272efc81ae452aa0af9ca092b71fbd3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20van=20Dorst?= Date: Fri, 18 Aug 2023 00:46:58 +0200 Subject: [PATCH 030/106] fix warning --- embassy-net-adin1110/src/lib.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/embassy-net-adin1110/src/lib.rs b/embassy-net-adin1110/src/lib.rs index a4010d25..4ce8a189 100644 --- a/embassy-net-adin1110/src/lib.rs +++ b/embassy-net-adin1110/src/lib.rs @@ -508,17 +508,20 @@ impl<'d, SPI: SpiDevice, INT: Wait, RST: OutputPin> Runner<'d, SPI, INT, RST> { } if status0.phyint() { + #[cfg_attr(not(feature = "defmt"), allow(unused_variables))] let crsm_irq_st = self .mac .read_cl45(MDIO_PHY_ADDR, RegsC45::DA1E::CRSM_IRQ_STATUS.into()) .await .unwrap(); + #[cfg_attr(not(feature = "defmt"), allow(unused_variables))] let phy_irq_st = self .mac .read_cl45(MDIO_PHY_ADDR, RegsC45::DA1F::PHY_SYBSYS_IRQ_STATUS.into()) .await .unwrap(); + #[cfg(feature = "defmt")] defmt::warn!( "SPE CHIP PHY CRSM_IRQ_STATUS {:04x} PHY_SUBSYS_IRQ_STATUS {:04x}", From 46ddf7013a426f67eb737ae8436d1032a3ec9d77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20van=20Dorst?= Date: Fri, 18 Aug 2023 23:08:51 +0200 Subject: [PATCH 031/106] update README.md after review --- embassy-net-adin1110/README.md | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/embassy-net-adin1110/README.md b/embassy-net-adin1110/README.md index 9b7b4e0e..3c280418 100644 --- a/embassy-net-adin1110/README.md +++ b/embassy-net-adin1110/README.md @@ -4,18 +4,18 @@ ## What is SPE or Single Pair Ethernet / 10 BASE-T1L -SPE is Single Pair Ethernet, what the names implies, it uses a single twisted/differancial pair (only 2 wires) to transmit ethernet packet in full-duplex. -SPE is still ethernet, only the phissical layer is different. +SPE stands for Single Pair Ethernet. As the names implies, SPE uses differential signalling with 2 wires (a twisted-pair) in a cable as the physical medium. +SPE is full-duplex - it can transmit and receive ethernet packets at the same time. SPE is still ethernet, only the physical layer is different. -SPE also supports [`PoDL(Power over Data Line)`](https://www.ti.com/lit/an/snla395/snla395.pdf), power delivery from 0.5 up to 50 Watts, similair to [`PoE`](https://en.wikipedia.org/wiki/Power_over_Ethernet), but additional hardware and handshake protocol is needed. +SPE also supports [`PoDL (Power over Data Line)`](https://www.ti.com/lit/an/snla395/snla395.pdf), power delivery from 0.5 up to 50 Watts, similar to [`PoE`](https://en.wikipedia.org/wiki/Power_over_Ethernet), but an additional hardware and handshake protocol are needed. -SPE has many link speeds but only `10 BASE-T1L` is able to reach cable length up to 1000 meters in `2.4 Vpp` transmit amplitude. -Currently in 2023, none of the standards are compatiable with eachother. -So `10 BASE-T1L` don't work with a `10 BASE-T1S` or `100 BASE-T1`. +SPE has many link speeds but only `10 BASE-T1L` is able to reach cable lengths up to 1000 meters in `2.4 Vpp` transmit amplitude. +Currently in 2023, none of the standards are compatible with each other. +Thus `10 BASE-T1L` won't work with a `10 BASE-T1S`, `100 BASE-T1` or any standard `x BASE-T`. -In the industry SPE is also called [`APL(Advanced Physical Layer)`](https://www.ethernet-apl.org), it is based on the `10 BASE-T1L` standard. +In the industry SPE is also called [`APL (Advanced Physical Layer)`](https://www.ethernet-apl.org), and is based on the `10 BASE-T1L` standard. -APL can be use in [`intrinsic safety applications/explosion hazardous areas`](https://en.wikipedia.org/wiki/Electrical_equipment_in_hazardous_areas) which has it's own name and standard [`2-WISE(2-wire intrinsically safe ethernet) IEC TS 60079-47:2021`](https://webstore.iec.ch/publication/64292). +APL can be used in [`intrinsic safety applications/explosion hazardous areas`](https://en.wikipedia.org/wiki/Electrical_equipment_in_hazardous_areas) which has its own name and standard called [`2-WISE (2-wire intrinsically safe ethernet) IEC TS 60079-47:2021`](https://webstore.iec.ch/publication/64292). `10 BASE-T1L` and `ADIN1110` are designed to support intrinsic safety applications. The power supply energy is fixed and PDoL is not supported. @@ -30,8 +30,8 @@ Currently only `Generic` SPI with or without CRC is supported. ## Hardware -- Testen on [`Analog Devices EVAL-ADIN1110EBZ`](https://www.analog.com/en/design-center/evaluation-hardware-and-software/evaluation-boards-kits/eval-adin1110.html) with a `STM32L4S5QII3P`, see [`spe_adin1110_http_server`](../examples/stm32l4/src/bin/spe_adin1110_http_server.rs) example. -- [`SparkFun MicroMod Single Pair Ethernet Function Board`](https://www.sparkfun.com/products/19038) or [`SparkFun MicroMod Single Pair Ethernet Kit`](https://www.sparkfun.com/products/19628), the kit supports multiple microcontrollers, please check if get the right microcontroller that is supported by Embassy! +- Tested on [`Analog Devices EVAL-ADIN1110EBZ`](https://www.analog.com/en/design-center/evaluation-hardware-and-software/evaluation-boards-kits/eval-adin1110.html) with an `STM32L4S5QII3P`, see [`spe_adin1110_http_server`](../examples/stm32l4/src/bin/spe_adin1110_http_server.rs) dor an example. +- [`SparkFun MicroMod Single Pair Ethernet Function Board`](https://www.sparkfun.com/products/19038) or [`SparkFun MicroMod Single Pair Ethernet Kit`](https://www.sparkfun.com/products/19628), supporting multiple microcontrollers. **Make sure to check if it's a microcontroller that is supported by Embassy!** ## Other SPE chips @@ -40,7 +40,7 @@ Currently only `Generic` SPI with or without CRC is supported. ## Testing -ADIN1110 library can tested on the host with a mock SPI driver +ADIN1110 library can tested on the host with a mock SPI driver. $ `cargo test --target x86_64-unknown-linux-gnu` From 10bf33dcacd162f0ab92a37bdc439cbac9fa437c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20van=20Dorst?= Date: Sun, 20 Aug 2023 16:28:57 +0200 Subject: [PATCH 032/106] Fix linting. I like program with deny(clippy::pedantic) but it was set as allowed, so I did get less linting errors/hints. Now it is corrected and also fix the lint errors and hints. Also fixes some comment and demagic some values. Rename `FEC` to more appropriate name `FSC`. --- embassy-net-adin1110/src/crc32.rs | 68 +++++++-------- embassy-net-adin1110/src/lib.rs | 138 ++++++++++++++++-------------- embassy-net-adin1110/src/mdio.rs | 13 +-- embassy-net-adin1110/src/phy.rs | 14 +-- embassy-net-adin1110/src/regs.rs | 15 ++-- 5 files changed, 128 insertions(+), 120 deletions(-) diff --git a/embassy-net-adin1110/src/crc32.rs b/embassy-net-adin1110/src/crc32.rs index 75a7d65b..906c9aad 100644 --- a/embassy-net-adin1110/src/crc32.rs +++ b/embassy-net-adin1110/src/crc32.rs @@ -1,33 +1,33 @@ pub const CRC32R_LOOKUP_TABLE: [u32; 256] = [ - 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, 0x0EDB8832, - 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2, - 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, 0x136C9856, 0x646BA8C0, 0xFD62F97A, - 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, - 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, - 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, - 0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, - 0xB6662D3D, 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, - 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, 0x6B6B51F4, - 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950, - 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, 0x4DB26158, 0x3AB551CE, 0xA3BC0074, - 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, - 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, - 0x206F85B3, 0xB966D409, 0xCE61E49F, 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, - 0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, - 0x73DC1683, 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, - 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, 0xFED41B76, - 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E, - 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, - 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, - 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, - 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, - 0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, - 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, - 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, 0xA00AE278, - 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC, - 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, 0xBDBDF21C, 0xCABAC28A, 0x53B39330, - 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, - 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D, + 0x0000_0000, 0x7707_3096, 0xEE0E_612C, 0x9909_51BA, 0x076D_C419, 0x706A_F48F, 0xE963_A535, 0x9E64_95A3, 0x0EDB_8832, + 0x79DC_B8A4, 0xE0D5_E91E, 0x97D2_D988, 0x09B6_4C2B, 0x7EB1_7CBD, 0xE7B8_2D07, 0x90BF_1D91, 0x1DB7_1064, 0x6AB0_20F2, + 0xF3B9_7148, 0x84BE_41DE, 0x1ADA_D47D, 0x6DDD_E4EB, 0xF4D4_B551, 0x83D3_85C7, 0x136C_9856, 0x646B_A8C0, 0xFD62_F97A, + 0x8A65_C9EC, 0x1401_5C4F, 0x6306_6CD9, 0xFA0F_3D63, 0x8D08_0DF5, 0x3B6E_20C8, 0x4C69_105E, 0xD560_41E4, 0xA267_7172, + 0x3C03_E4D1, 0x4B04_D447, 0xD20D_85FD, 0xA50A_B56B, 0x35B5_A8FA, 0x42B2_986C, 0xDBBB_C9D6, 0xACBC_F940, 0x32D8_6CE3, + 0x45DF_5C75, 0xDCD6_0DCF, 0xABD1_3D59, 0x26D9_30AC, 0x51DE_003A, 0xC8D7_5180, 0xBFD0_6116, 0x21B4_F4B5, 0x56B3_C423, + 0xCFBA_9599, 0xB8BD_A50F, 0x2802_B89E, 0x5F05_8808, 0xC60C_D9B2, 0xB10B_E924, 0x2F6F_7C87, 0x5868_4C11, 0xC161_1DAB, + 0xB666_2D3D, 0x76DC_4190, 0x01DB_7106, 0x98D2_20BC, 0xEFD5_102A, 0x71B1_8589, 0x06B6_B51F, 0x9FBF_E4A5, 0xE8B8_D433, + 0x7807_C9A2, 0x0F00_F934, 0x9609_A88E, 0xE10E_9818, 0x7F6A_0DBB, 0x086D_3D2D, 0x9164_6C97, 0xE663_5C01, 0x6B6B_51F4, + 0x1C6C_6162, 0x8565_30D8, 0xF262_004E, 0x6C06_95ED, 0x1B01_A57B, 0x8208_F4C1, 0xF50F_C457, 0x65B0_D9C6, 0x12B7_E950, + 0x8BBE_B8EA, 0xFCB9_887C, 0x62DD_1DDF, 0x15DA_2D49, 0x8CD3_7CF3, 0xFBD4_4C65, 0x4DB2_6158, 0x3AB5_51CE, 0xA3BC_0074, + 0xD4BB_30E2, 0x4ADF_A541, 0x3DD8_95D7, 0xA4D1_C46D, 0xD3D6_F4FB, 0x4369_E96A, 0x346E_D9FC, 0xAD67_8846, 0xDA60_B8D0, + 0x4404_2D73, 0x3303_1DE5, 0xAA0A_4C5F, 0xDD0D_7CC9, 0x5005_713C, 0x2702_41AA, 0xBE0B_1010, 0xC90C_2086, 0x5768_B525, + 0x206F_85B3, 0xB966_D409, 0xCE61_E49F, 0x5EDE_F90E, 0x29D9_C998, 0xB0D0_9822, 0xC7D7_A8B4, 0x59B3_3D17, 0x2EB4_0D81, + 0xB7BD_5C3B, 0xC0BA_6CAD, 0xEDB8_8320, 0x9ABF_B3B6, 0x03B6_E20C, 0x74B1_D29A, 0xEAD5_4739, 0x9DD2_77AF, 0x04DB_2615, + 0x73DC_1683, 0xE363_0B12, 0x9464_3B84, 0x0D6D_6A3E, 0x7A6A_5AA8, 0xE40E_CF0B, 0x9309_FF9D, 0x0A00_AE27, 0x7D07_9EB1, + 0xF00F_9344, 0x8708_A3D2, 0x1E01_F268, 0x6906_C2FE, 0xF762_575D, 0x8065_67CB, 0x196C_3671, 0x6E6B_06E7, 0xFED4_1B76, + 0x89D3_2BE0, 0x10DA_7A5A, 0x67DD_4ACC, 0xF9B9_DF6F, 0x8EBE_EFF9, 0x17B7_BE43, 0x60B0_8ED5, 0xD6D6_A3E8, 0xA1D1_937E, + 0x38D8_C2C4, 0x4FDF_F252, 0xD1BB_67F1, 0xA6BC_5767, 0x3FB5_06DD, 0x48B2_364B, 0xD80D_2BDA, 0xAF0A_1B4C, 0x3603_4AF6, + 0x4104_7A60, 0xDF60_EFC3, 0xA867_DF55, 0x316E_8EEF, 0x4669_BE79, 0xCB61_B38C, 0xBC66_831A, 0x256F_D2A0, 0x5268_E236, + 0xCC0C_7795, 0xBB0B_4703, 0x2202_16B9, 0x5505_262F, 0xC5BA_3BBE, 0xB2BD_0B28, 0x2BB4_5A92, 0x5CB3_6A04, 0xC2D7_FFA7, + 0xB5D0_CF31, 0x2CD9_9E8B, 0x5BDE_AE1D, 0x9B64_C2B0, 0xEC63_F226, 0x756A_A39C, 0x026D_930A, 0x9C09_06A9, 0xEB0E_363F, + 0x7207_6785, 0x0500_5713, 0x95BF_4A82, 0xE2B8_7A14, 0x7BB1_2BAE, 0x0CB6_1B38, 0x92D2_8E9B, 0xE5D5_BE0D, 0x7CDC_EFB7, + 0x0BDB_DF21, 0x86D3_D2D4, 0xF1D4_E242, 0x68DD_B3F8, 0x1FDA_836E, 0x81BE_16CD, 0xF6B9_265B, 0x6FB0_77E1, 0x18B7_4777, + 0x8808_5AE6, 0xFF0F_6A70, 0x6606_3BCA, 0x1101_0B5C, 0x8F65_9EFF, 0xF862_AE69, 0x616B_FFD3, 0x166C_CF45, 0xA00A_E278, + 0xD70D_D2EE, 0x4E04_8354, 0x3903_B3C2, 0xA767_2661, 0xD060_16F7, 0x4969_474D, 0x3E6E_77DB, 0xAED1_6A4A, 0xD9D6_5ADC, + 0x40DF_0B66, 0x37D8_3BF0, 0xA9BC_AE53, 0xDEBB_9EC5, 0x47B2_CF7F, 0x30B5_FFE9, 0xBDBD_F21C, 0xCABA_C28A, 0x53B3_9330, + 0x24B4_A3A6, 0xBAD0_3605, 0xCDD7_0693, 0x54DE_5729, 0x23D9_67BF, 0xB366_7A2E, 0xC461_4AB8, 0x5D68_1B02, 0x2A6F_2B94, + 0xB40B_BE37, 0xC30C_8EA1, 0x5A05_DF1B, 0x2D02_EF8D, ]; #[allow(non_camel_case_types)] @@ -35,9 +35,9 @@ pub const CRC32R_LOOKUP_TABLE: [u32; 256] = [ pub struct ETH_FSC(pub u32); impl ETH_FSC { - pub const CRC32_OK: u32 = 0x2144df1c; + pub const CRC32_OK: u32 = 0x2144_df1c; - pub fn new(data: &[u8]) -> Self { + #[must_use] pub fn new(data: &[u8]) -> Self { let fsc = data.iter().fold(u32::MAX, |crc, byte| { let idx = u8::try_from(crc & 0xFF).unwrap() ^ byte; CRC32R_LOOKUP_TABLE[usize::from(idx)] ^ (crc >> 8) @@ -45,15 +45,15 @@ impl ETH_FSC { Self(fsc) } - pub fn crc_ok(&self) -> bool { + #[must_use] pub fn crc_ok(&self) -> bool { self.0 == Self::CRC32_OK } - pub fn hton_bytes(&self) -> [u8; 4] { + #[must_use] pub fn hton_bytes(&self) -> [u8; 4] { self.0.to_le_bytes() } - pub fn hton(&self) -> u32 { + #[must_use] pub fn hton(&self) -> u32 { self.0.to_le() } } diff --git a/embassy-net-adin1110/src/lib.rs b/embassy-net-adin1110/src/lib.rs index 4ce8a189..c7464893 100644 --- a/embassy-net-adin1110/src/lib.rs +++ b/embassy-net-adin1110/src/lib.rs @@ -1,16 +1,10 @@ -#![allow(clippy::pedantic)] +#![deny(clippy::pedantic)] #![feature(type_alias_impl_trait)] #![feature(async_fn_in_trait)] #![cfg_attr(not(any(test, feature = "std")), no_std)] - -use ch::driver::LinkState; -use embassy_futures::select::{select, Either}; -use embassy_net_driver_channel as ch; -use embassy_time::{Duration, Timer}; -use embedded_hal_1::digital::OutputPin; -use embedded_hal_async::digital::Wait; -use embedded_hal_async::spi::{Operation, SpiDevice}; -use heapless::Vec; +#![allow(clippy::module_name_repetitions)] +#![allow(clippy::missing_errors_doc)] +#![allow(clippy::missing_panics_doc)] mod crc32; mod crc8; @@ -18,15 +12,23 @@ mod mdio; mod phy; mod regs; +use ch::driver::LinkState; pub use crc32::ETH_FSC; use crc8::crc8; +use embassy_futures::select::{select, Either}; +use embassy_net_driver_channel as ch; +use embassy_time::{Duration, Timer}; +use embedded_hal_1::digital::OutputPin; +use embedded_hal_async::digital::Wait; +use embedded_hal_async::spi::{Operation, SpiDevice}; +use heapless::Vec; pub use mdio::MdioBus; pub use phy::{Phy10BaseT1x, RegsC22, RegsC45}; pub use regs::{Config0, Config2, SpiRegisters as sr, Status0, Status1}; use crate::regs::{LedCntrl, LedFunc, LedPol, LedPolarity, SpiHeader}; -pub const PHYID: u32 = 0x0283BC91; +pub const PHYID: u32 = 0x0283_BC91; /// Error values ADIN1110 #[derive(Debug)] @@ -44,21 +46,28 @@ pub enum AdinError { pub type AEResult = core::result::Result>; pub const MDIO_PHY_ADDR: u8 = 0x01; -pub const MTU: usize = 1500; + +/// Maximum Transmission Unit +pub const MTU: usize = 1514; + /// Max SPI/Frame buffer size pub const MAX_BUFF: usize = 2048; const DONT_CARE_BYTE: u8 = 0x00; const TURN_AROUND_BYTE: u8 = 0x00; -const FEC_LEN: usize = 4; +/// Packet minimal frame/packet length +const ETH_MIN_LEN: usize = 64; + +/// Ethernet `Frame Check Sequence` length +const FSC_LEN: usize = 4; const FRAME_HEADER_LEN: usize = 2; const WR_HEADER_LEN: usize = 2; // P1 = 0x00, P2 = 0x01 const PORT_ID_BYTE: u8 = 0x00; -pub type Packet = Vec; +pub type Packet = Vec; /// Type alias for the embassy-net driver for ADIN1110 pub type Device<'d> = embassy_net_driver_channel::Device<'d, MTU>; @@ -69,6 +78,7 @@ pub struct State { } impl State { /// Create a new `State`. + #[must_use] pub const fn new() -> Self { Self { ch_state: ch::State::new(), @@ -81,11 +91,11 @@ pub struct ADIN1110 { /// SPI bus spi: SPI, /// Enable CRC on SPI transfer. - /// This must match with the hardware pin SPI_CFG0 were 0 = CRC enable, 1 CRC disabled. + /// This must match with the hardware pin `SPI_CFG0` were low = CRC enable, high = CRC disabled. crc: bool, } -// Round size up the N u32; +/// Round size up the N u32; pub(crate) fn size_align_u32(size: u32) -> u32 { (size + 3) & 0xFFFF_FFFC } @@ -166,7 +176,7 @@ where self.spi.write(&tx_buf).await.map_err(AdinError::Spi) } - // helper function for write to MDIO_ACC register and wait for ready! + /// helper function for write to `MDIO_ACC` register and wait for ready! async fn write_mdio_acc_reg(&mut self, mdio_acc_val: u32) -> AEResult { self.write_reg(sr::MDIO_ACC, mdio_acc_val).await?; @@ -181,6 +191,7 @@ where Err(AdinError::MDIO_ACC_TIMEOUT) } + /// Read out fifo ethernet packet memory received via the wire. pub async fn read_fifo(&mut self, packet: &mut [u8]) -> AEResult { let mut tx_buf = Vec::::new(); @@ -190,7 +201,7 @@ where // Packet read of write to the MAC packet buffer must be a multipul of 4! let read_size = size_align_u32(packet_size); - if packet_size < u32::try_from(FRAME_HEADER_LEN + FEC_LEN).unwrap() + if packet_size < u32::try_from(FRAME_HEADER_LEN + FSC_LEN).unwrap() || read_size > u32::try_from(packet.len()).unwrap() { return Err(AdinError::PACKET_TOO_BIG); @@ -226,11 +237,9 @@ where Ok(packet_size as usize) } + /// Write to fifo ethernet packet memory send over the wire. pub async fn write_fifo(&mut self, frame: &[u8]) -> AEResult<(), SpiE> { let header_len = self.header_write_len(); - // if packet.len() < header_len { - // return Err(AdinError::PACKET_TOO_SMALL); - // } let mut packet = Packet::new(); @@ -244,37 +253,33 @@ where .map_err(|_| AdinError::PACKET_TOO_BIG)?; if self.crc { - assert_eq!(header_len, 5); // Add CRC for header data packet .push(crc8(&packet[0..2])) .map_err(|_| AdinError::PACKET_TOO_BIG)?; } - // Add port number - // packet[header_len - FRAME_HEADER_LEN..header_len] - // .copy_from_slice(u16::from(PORT_ID_BYTE).to_be_bytes().as_slice()); + // Add port number, ADIN1110 its fixed to zero/P1, but for ADIN2111 has two ports. packet .extend_from_slice(u16::from(PORT_ID_BYTE).to_be_bytes().as_slice()) .map_err(|_| AdinError::PACKET_TOO_BIG)?; + // Copy packet data to spi buffer. packet.extend_from_slice(frame).map_err(|_| AdinError::PACKET_TOO_BIG)?; - // Pad data up to 64 - for _ in packet.len()..(64 - FEC_LEN + header_len) { + // Pad data up to ETH_MIN_LEN - FCS_LEN + for _ in packet.len()..(ETH_MIN_LEN - FSC_LEN + header_len) { let _ = packet.push(0x00); } - // // add ethernet crc32 + // add ethernet FCS only over the ethernet packet. let crc = ETH_FSC::new(&packet[header_len..]); let _ = packet.extend_from_slice(crc.hton_bytes().as_slice()); - let crc = ETH_FSC::new(&packet[header_len..]); - assert!(crc.crc_ok()); + let send_len = + u32::try_from(packet.len() - header_len + FRAME_HEADER_LEN).map_err(|_| AdinError::PACKET_TOO_BIG)?; - let send_len = packet.len() - header_len + FRAME_HEADER_LEN; - - // Packet read of write to the MAC packet buffer must be a multipul of 4! + // Packet read of write to the MAC packet buffer must be a multipul of 4 bytes! while packet.len() & 0x3 != 0 { let _ = packet.push(DONT_CARE_BYTE); } @@ -288,7 +293,7 @@ where send_len, ); - self.write_reg(sr::TX_FSIZE, send_len as u32).await?; + self.write_reg(sr::TX_FSIZE, send_len).await?; // Spi packet must be half word / even length if send_len & 1 != 0 { @@ -346,17 +351,21 @@ where let mdio_acc_val: u32 = (0x1 << 28) | u32::from(phy_id & 0x1F) << 21 | u32::from(reg & 0x1F) << 16 | (0x3 << 26); + // Result is in the lower half of the answer. + #[allow(clippy::cast_possible_truncation)] self.write_mdio_acc_reg(mdio_acc_val).await.map(|val| val as u16) } /// Read from the PHY Registers as Clause 45. async fn read_cl45(&mut self, phy_id: u8, regc45: (u8, u16)) -> Result { - let mdio_acc_val: u32 = u32::from(phy_id & 0x1F) << 21 | u32::from(regc45.0 & 0x1F) << 16 | u32::from(regc45.1); + let mdio_acc_val = u32::from(phy_id & 0x1F) << 21 | u32::from(regc45.0 & 0x1F) << 16 | u32::from(regc45.1); self.write_mdio_acc_reg(mdio_acc_val).await?; - let mdio_acc_val: u32 = u32::from(phy_id & 0x1F) << 21 | u32::from(regc45.0 & 0x1F) << 16 | (0x03 << 26); + let mdio_acc_val = u32::from(phy_id & 0x1F) << 21 | u32::from(regc45.0 & 0x1F) << 16 | (0x03 << 26); + // Result is in the lower half of the answer. + #[allow(clippy::cast_possible_truncation)] self.write_mdio_acc_reg(mdio_acc_val).await.map(|val| val as u16) } @@ -394,6 +403,7 @@ pub struct Runner<'d, SPI, INT, RST> { } impl<'d, SPI: SpiDevice, INT: Wait, RST: OutputPin> Runner<'d, SPI, INT, RST> { + #[allow(clippy::too_many_lines)] pub async fn run(mut self) -> ! { loop { let (state_chan, mut rx_chan, mut tx_chan) = self.ch.split(); @@ -566,6 +576,7 @@ pub async fn new assert_eq!(val, 0x0283BC91), - Err(_e) => panic!("Error:"), - }; + let val = spe.read_reg(sr::PHYID).await.expect("Error"); + assert_eq!(val, 0x0283_BC91); // Read CAPAVILITY - match spe.read_reg(sr::CAPABILITY).await { - Ok(val) => assert_eq!(val, 0x000006C3), - Err(_e) => panic!("Error:"), - }; + let val = spe.read_reg(sr::CAPABILITY).await.expect("Error"); + assert_eq!(val, 0x0000_06C3); spi.done(); } @@ -778,20 +786,16 @@ mod tests { let mut spe = ADIN1110::new(spi_dev, true); - assert_eq!(crc8(0x0283BC91_u32.to_be_bytes().as_slice()), 215); - assert_eq!(crc8(0x000006C3_u32.to_be_bytes().as_slice()), 57); + assert_eq!(crc8(0x0283_BC91_u32.to_be_bytes().as_slice()), 215); + assert_eq!(crc8(0x0000_06C3_u32.to_be_bytes().as_slice()), 57); // Read PHIID - match spe.read_reg(sr::PHYID).await { - Ok(val) => assert_eq!(val, 0x0283BC91), - Err(e) => panic!("Error: {e:?}"), - }; + let val = spe.read_reg(sr::PHYID).await.expect("Error"); + assert_eq!(val, 0x0283_BC91); // Read CAPAVILITY - match spe.read_reg(sr::CAPABILITY).await { - Ok(val) => assert_eq!(val, 0x000006C3), - Err(_e) => panic!("Error:"), - }; + let val = spe.read_reg(sr::CAPABILITY).await.expect("Error"); + assert_eq!(val, 0x0000_06C3); spi.done(); } @@ -885,7 +889,7 @@ mod tests { // ]; // let mut packet = Packet::new(); - // packet.resize(64, 0).unwrap(); + // packet.resize(ETH_MIN_LEN, 0).unwrap(); // for &byte in &packet[4..] { // expectations.push(SpiTransaction::send(byte)); @@ -893,7 +897,7 @@ mod tests { // } // // padding - // for _ in packet.len() as u32..65 { + // for _ in packet.len()..65 { // expectations.push(SpiTransaction::send(0x00)); // expectations.push(SpiTransaction::read(DONT_CARE_BYTE)); // } @@ -943,7 +947,7 @@ mod tests { // ]; // let mut packet = Packet::new(); - // packet.resize(64, 0).unwrap(); + // packet.resize(ETH_MIN_LEN, 0).unwrap(); // for &byte in &packet[4..] { // expectations.push(SpiTransaction::send(byte)); @@ -951,7 +955,7 @@ mod tests { // } // // padding - // for _ in packet.len() as u32..64 { + // for _ in packet.len() as u32..ETH_MIN_LEN { // expectations.push(SpiTransaction::send(0x00)); // expectations.push(SpiTransaction::read(DONT_CARE_BYTE)); // } @@ -1061,7 +1065,7 @@ mod tests { // } // // padding - // for _ in packet.len() as u32..64 { + // for _ in packet.len()..ETH_MIN_LEN { // expectations.push(SpiTransaction::send(0x00)); // expectations.push(SpiTransaction::read(DONT_CARE_BYTE)); // } @@ -1119,7 +1123,7 @@ mod tests { // } // // padding - // for _ in packet.len() as u32..64 { + // for _ in packet.len()..ETH_MIN_LEN { // expectations.push(SpiTransaction::send(0x00)); // expectations.push(SpiTransaction::read(DONT_CARE_BYTE)); // } @@ -1176,7 +1180,7 @@ mod tests { // } // // padding - // for _ in packet.len() as u32..64 { + // for _ in packet.len()..ETH_MIN_LEN { // expectations.push(SpiTransaction::send(0x00)); // expectations.push(SpiTransaction::read(DONT_CARE_BYTE)); // } @@ -1219,15 +1223,17 @@ mod tests { spi_packet.extend_from_slice(&[160, 49, 143, 0, 0]).unwrap(); // Packet data spi_packet.extend_from_slice(&packet).unwrap(); - // Packet padding up to 60 (64 - FCS) - for _ in packet.len() as u32..60 { + // Packet padding up to 60 (ETH_MIN_LEN - FCS) + for _ in packet.len()..(ETH_MIN_LEN - FSC_LEN) { spi_packet.push(0x00).unwrap(); } // Packet FCS spi_packet.extend_from_slice(&[147, 149, 213, 68]).unwrap(); + let spi_packet_len = u32::try_from(spi_packet.len()).unwrap(); + // SPI HEADER Padding of u32 - for _ in spi_packet.len() as u32..size_align_u32(spi_packet.len() as u32) { + for _ in spi_packet_len..size_align_u32(spi_packet_len) { spi_packet.push(0x00).unwrap(); } @@ -1242,7 +1248,7 @@ mod tests { let mut spe = ADIN1110::new(spi_dev, true); - assert!(spe.write_fifo(&mut packet).await.is_ok()); + assert!(spe.write_fifo(&packet).await.is_ok()); spi.done(); } diff --git a/embassy-net-adin1110/src/mdio.rs b/embassy-net-adin1110/src/mdio.rs index ab7629d3..68477006 100644 --- a/embassy-net-adin1110/src/mdio.rs +++ b/embassy-net-adin1110/src/mdio.rs @@ -32,11 +32,11 @@ enum Reg13Op { PostReadIncAddr = 0b10 << 14, Read = 0b11 << 14, } -/// MdioBus trait -/// Driver needs to implemnt the Claus 22 +/// `MdioBus` trait +/// Driver needs to implement the Clause 22 /// Optional Clause 45 is the device supports this. /// -/// Claus 45 methodes are bases on https://www.ieee802.org/3/efm/public/nov02/oam/pannell_oam_1_1102.pdf +/// Claus 45 methodes are bases on pub trait MdioBus { type Error; @@ -52,13 +52,14 @@ pub trait MdioBus { /// Implement this function when your hardware supports it. async fn read_cl45(&mut self, phy_id: PhyAddr, regc45: (u8, RegC45)) -> Result { // Write FN - let val = (Reg13Op::Addr as RegVal) | (regc45.0 & DEV_MASK) as RegVal; + let val = (Reg13Op::Addr as RegVal) | RegVal::from(regc45.0 & DEV_MASK); + self.write_cl22(phy_id, REG13, val).await?; // Write Addr self.write_cl22(phy_id, REG14, regc45.1).await?; // Write FN - let val = (Reg13Op::Read as RegVal) | (regc45.0 & DEV_MASK) as RegVal; + let val = (Reg13Op::Read as RegVal) | RegVal::from(regc45.0 & DEV_MASK); self.write_cl22(phy_id, REG13, val).await?; // Write Addr self.read_cl22(phy_id, REG14).await @@ -69,7 +70,7 @@ pub trait MdioBus { /// Many hardware these days support direct Clause 45 operations. /// Implement this function when your hardware supports it. async fn write_cl45(&mut self, phy_id: PhyAddr, regc45: (u8, RegC45), reg_val: RegVal) -> Result<(), Self::Error> { - let dev_addr = (regc45.0 & DEV_MASK) as RegVal; + let dev_addr = RegVal::from(regc45.0 & DEV_MASK); let reg = regc45.1; // Write FN diff --git a/embassy-net-adin1110/src/phy.rs b/embassy-net-adin1110/src/phy.rs index 78d3fdf7..70060a0c 100644 --- a/embassy-net-adin1110/src/phy.rs +++ b/embassy-net-adin1110/src/phy.rs @@ -30,7 +30,7 @@ pub mod RegsC45 { } impl DA1 { - pub fn into(self) -> (u8, u16) { + #[must_use] pub fn into(self) -> (u8, u16) { (0x01, self as u16) } } @@ -48,7 +48,7 @@ pub mod RegsC45 { } impl DA3 { - pub fn into(self) -> (u8, u16) { + #[must_use] pub fn into(self) -> (u8, u16) { (0x03, self as u16) } } @@ -62,7 +62,7 @@ pub mod RegsC45 { } impl DA7 { - pub fn into(self) -> (u8, u16) { + #[must_use] pub fn into(self) -> (u8, u16) { (0x07, self as u16) } } @@ -84,7 +84,7 @@ pub mod RegsC45 { } impl DA1E { - pub fn into(self) -> (u8, u16) { + #[must_use] pub fn into(self) -> (u8, u16) { (0x1e, self as u16) } } @@ -100,7 +100,7 @@ pub mod RegsC45 { } impl DA1F { - pub fn into(self) -> (u8, u16) { + #[must_use] pub fn into(self) -> (u8, u16) { (0x1f, self as u16) } } @@ -121,8 +121,8 @@ impl Phy10BaseT1x { MDIOBUS: MdioBus, MDE: core::fmt::Debug, { - let mut phyid = (mdiobus.read_cl22(self.0, RegsC22::PHY_ID1 as u8).await? as u32) << 16; - phyid |= mdiobus.read_cl22(self.0, RegsC22::PHY_ID2 as u8).await? as u32; + let mut phyid = u32::from(mdiobus.read_cl22(self.0, RegsC22::PHY_ID1 as u8).await?) << 16; + phyid |= u32::from(mdiobus.read_cl22(self.0, RegsC22::PHY_ID2 as u8).await?); Ok(phyid) } diff --git a/embassy-net-adin1110/src/regs.rs b/embassy-net-adin1110/src/regs.rs index 93ce812d..4557929f 100644 --- a/embassy-net-adin1110/src/regs.rs +++ b/embassy-net-adin1110/src/regs.rs @@ -74,7 +74,6 @@ impl From for SpiRegisters { } // Register definitions - bitfield! { /// Status0 Register bits pub struct Status0(u32); @@ -242,6 +241,7 @@ bitfield! { pub link_change_mask, set_link_change_mask : 1; } +/// LED Functions #[repr(u8)] pub enum LedFunc { LinkupTxRxActicity = 0, @@ -326,7 +326,7 @@ bitfield_bitrange! {struct LedCntrl(u16)} impl LedCntrl { bitfield_fields! { u8; - /// LED_0 Pin Function + /// LED 0 Pin Function pub from into LedFunc, led0_function, set_led0_function: 4, 0; /// LED 0 Mode Selection pub led0_mode, set_led0_mode: 5; @@ -334,7 +334,7 @@ impl LedCntrl { pub led0_link_st_qualify, set_led0_link_st_qualify: 6; /// LED 0 Enable pub led0_en, set_led0_en: 7; - /// LED_1 Pin Function + /// LED 1 Pin Function pub from into LedFunc, led1_function, set_led1_function: 12, 8; /// /// LED 1 Mode Selection pub led1_mode, set_led1_mode: 13; @@ -349,7 +349,7 @@ impl LedCntrl { } } -// #[allow(dead_code)] +// LED Polarity #[repr(u8)] pub enum LedPol { AutoSense = 0, @@ -384,12 +384,12 @@ impl LedPolarity { u8; /// LED 1 Polarity pub from into LedPol, led1_polarity, set_led1_polarity: 3, 2; - /// LED_0 Polarity + /// LED 0 Polarity pub from into LedPol, led0_polarity, set_led0_polarity: 1, 0; } } -/// LED Control Register +/// SPI Header #[derive(Copy, Clone, PartialEq, Eq, Hash)] pub struct SpiHeader(pub u16); bitfield_bitrange! {struct SpiHeader(u16)} @@ -400,8 +400,9 @@ impl SpiHeader { /// Mask Bit for TXF_ECC_ERR pub control, set_control : 15; pub full_duplex, set_full_duplex : 14; + /// Read or Write to register pub write, set_write : 13; - /// LED_0 Polarity + /// Registers ID/addr pub from into SpiRegisters, addr, set_addr: 11, 0; } } From e082cd0cda23b485f123f34efdeb3e54bcf3a616 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20van=20Dorst?= Date: Sun, 20 Aug 2023 21:21:33 +0200 Subject: [PATCH 033/106] Remove unneeded files. --- embassy-net-adin1110/.gitignore | 1 - embassy-net-adin1110/.vscode/settings.json | 8 -------- embassy-net-adin1110/rust-toolchain.toml | 3 --- 3 files changed, 12 deletions(-) delete mode 100644 embassy-net-adin1110/.gitignore delete mode 100644 embassy-net-adin1110/.vscode/settings.json delete mode 100644 embassy-net-adin1110/rust-toolchain.toml diff --git a/embassy-net-adin1110/.gitignore b/embassy-net-adin1110/.gitignore deleted file mode 100644 index c41cc9e3..00000000 --- a/embassy-net-adin1110/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/target \ No newline at end of file diff --git a/embassy-net-adin1110/.vscode/settings.json b/embassy-net-adin1110/.vscode/settings.json deleted file mode 100644 index daa2ccf0..00000000 --- a/embassy-net-adin1110/.vscode/settings.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "rust-analyzer.check.command": "clippy", - "rust-analyzer.showUnlinkedFileNotification": false, - "[rust]": { - "editor.defaultFormatter": "rust-lang.rust-analyzer", - "editor.formatOnSave": true - } -} \ No newline at end of file diff --git a/embassy-net-adin1110/rust-toolchain.toml b/embassy-net-adin1110/rust-toolchain.toml deleted file mode 100644 index d5f51a7f..00000000 --- a/embassy-net-adin1110/rust-toolchain.toml +++ /dev/null @@ -1,3 +0,0 @@ -[toolchain] -channel = "nightly" -components = [ "rustfmt", "rustc-dev" ] From 0e9524de621d338f71ba380f6036f23210365d9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20van=20Dorst?= Date: Sun, 20 Aug 2023 21:26:43 +0200 Subject: [PATCH 034/106] more clippy fixes --- embassy-net-adin1110/src/lib.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/embassy-net-adin1110/src/lib.rs b/embassy-net-adin1110/src/lib.rs index c7464893..10ed9f70 100644 --- a/embassy-net-adin1110/src/lib.rs +++ b/embassy-net-adin1110/src/lib.rs @@ -250,7 +250,7 @@ where packet .extend_from_slice(spi_hdr.0.to_be_bytes().as_slice()) - .map_err(|_| AdinError::PACKET_TOO_BIG)?; + .map_err(|_e| AdinError::PACKET_TOO_BIG)?; if self.crc { // Add CRC for header data @@ -262,10 +262,12 @@ where // Add port number, ADIN1110 its fixed to zero/P1, but for ADIN2111 has two ports. packet .extend_from_slice(u16::from(PORT_ID_BYTE).to_be_bytes().as_slice()) - .map_err(|_| AdinError::PACKET_TOO_BIG)?; + .map_err(|_e| AdinError::PACKET_TOO_BIG)?; // Copy packet data to spi buffer. - packet.extend_from_slice(frame).map_err(|_| AdinError::PACKET_TOO_BIG)?; + packet + .extend_from_slice(frame) + .map_err(|_e| AdinError::PACKET_TOO_BIG)?; // Pad data up to ETH_MIN_LEN - FCS_LEN for _ in packet.len()..(ETH_MIN_LEN - FSC_LEN + header_len) { From 1ded213ae904b90b20e15615f08873da4b4ef077 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20van=20Dorst?= Date: Sun, 20 Aug 2023 21:27:19 +0200 Subject: [PATCH 035/106] remove the type_alias_impl_trait feature --- embassy-net-adin1110/src/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/embassy-net-adin1110/src/lib.rs b/embassy-net-adin1110/src/lib.rs index 10ed9f70..113db3df 100644 --- a/embassy-net-adin1110/src/lib.rs +++ b/embassy-net-adin1110/src/lib.rs @@ -1,5 +1,4 @@ #![deny(clippy::pedantic)] -#![feature(type_alias_impl_trait)] #![feature(async_fn_in_trait)] #![cfg_attr(not(any(test, feature = "std")), no_std)] #![allow(clippy::module_name_repetitions)] From 0a7c061ddcd8db08449546a1121add8e37c6ddbb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20van=20Dorst?= Date: Sun, 20 Aug 2023 22:20:47 +0200 Subject: [PATCH 036/106] rustfmt --- embassy-net-adin1110/src/crc32.rs | 297 ++++++++++++++++++++++++++---- embassy-net-adin1110/src/phy.rs | 15 +- 2 files changed, 274 insertions(+), 38 deletions(-) diff --git a/embassy-net-adin1110/src/crc32.rs b/embassy-net-adin1110/src/crc32.rs index 906c9aad..a41fedca 100644 --- a/embassy-net-adin1110/src/crc32.rs +++ b/embassy-net-adin1110/src/crc32.rs @@ -1,33 +1,260 @@ pub const CRC32R_LOOKUP_TABLE: [u32; 256] = [ - 0x0000_0000, 0x7707_3096, 0xEE0E_612C, 0x9909_51BA, 0x076D_C419, 0x706A_F48F, 0xE963_A535, 0x9E64_95A3, 0x0EDB_8832, - 0x79DC_B8A4, 0xE0D5_E91E, 0x97D2_D988, 0x09B6_4C2B, 0x7EB1_7CBD, 0xE7B8_2D07, 0x90BF_1D91, 0x1DB7_1064, 0x6AB0_20F2, - 0xF3B9_7148, 0x84BE_41DE, 0x1ADA_D47D, 0x6DDD_E4EB, 0xF4D4_B551, 0x83D3_85C7, 0x136C_9856, 0x646B_A8C0, 0xFD62_F97A, - 0x8A65_C9EC, 0x1401_5C4F, 0x6306_6CD9, 0xFA0F_3D63, 0x8D08_0DF5, 0x3B6E_20C8, 0x4C69_105E, 0xD560_41E4, 0xA267_7172, - 0x3C03_E4D1, 0x4B04_D447, 0xD20D_85FD, 0xA50A_B56B, 0x35B5_A8FA, 0x42B2_986C, 0xDBBB_C9D6, 0xACBC_F940, 0x32D8_6CE3, - 0x45DF_5C75, 0xDCD6_0DCF, 0xABD1_3D59, 0x26D9_30AC, 0x51DE_003A, 0xC8D7_5180, 0xBFD0_6116, 0x21B4_F4B5, 0x56B3_C423, - 0xCFBA_9599, 0xB8BD_A50F, 0x2802_B89E, 0x5F05_8808, 0xC60C_D9B2, 0xB10B_E924, 0x2F6F_7C87, 0x5868_4C11, 0xC161_1DAB, - 0xB666_2D3D, 0x76DC_4190, 0x01DB_7106, 0x98D2_20BC, 0xEFD5_102A, 0x71B1_8589, 0x06B6_B51F, 0x9FBF_E4A5, 0xE8B8_D433, - 0x7807_C9A2, 0x0F00_F934, 0x9609_A88E, 0xE10E_9818, 0x7F6A_0DBB, 0x086D_3D2D, 0x9164_6C97, 0xE663_5C01, 0x6B6B_51F4, - 0x1C6C_6162, 0x8565_30D8, 0xF262_004E, 0x6C06_95ED, 0x1B01_A57B, 0x8208_F4C1, 0xF50F_C457, 0x65B0_D9C6, 0x12B7_E950, - 0x8BBE_B8EA, 0xFCB9_887C, 0x62DD_1DDF, 0x15DA_2D49, 0x8CD3_7CF3, 0xFBD4_4C65, 0x4DB2_6158, 0x3AB5_51CE, 0xA3BC_0074, - 0xD4BB_30E2, 0x4ADF_A541, 0x3DD8_95D7, 0xA4D1_C46D, 0xD3D6_F4FB, 0x4369_E96A, 0x346E_D9FC, 0xAD67_8846, 0xDA60_B8D0, - 0x4404_2D73, 0x3303_1DE5, 0xAA0A_4C5F, 0xDD0D_7CC9, 0x5005_713C, 0x2702_41AA, 0xBE0B_1010, 0xC90C_2086, 0x5768_B525, - 0x206F_85B3, 0xB966_D409, 0xCE61_E49F, 0x5EDE_F90E, 0x29D9_C998, 0xB0D0_9822, 0xC7D7_A8B4, 0x59B3_3D17, 0x2EB4_0D81, - 0xB7BD_5C3B, 0xC0BA_6CAD, 0xEDB8_8320, 0x9ABF_B3B6, 0x03B6_E20C, 0x74B1_D29A, 0xEAD5_4739, 0x9DD2_77AF, 0x04DB_2615, - 0x73DC_1683, 0xE363_0B12, 0x9464_3B84, 0x0D6D_6A3E, 0x7A6A_5AA8, 0xE40E_CF0B, 0x9309_FF9D, 0x0A00_AE27, 0x7D07_9EB1, - 0xF00F_9344, 0x8708_A3D2, 0x1E01_F268, 0x6906_C2FE, 0xF762_575D, 0x8065_67CB, 0x196C_3671, 0x6E6B_06E7, 0xFED4_1B76, - 0x89D3_2BE0, 0x10DA_7A5A, 0x67DD_4ACC, 0xF9B9_DF6F, 0x8EBE_EFF9, 0x17B7_BE43, 0x60B0_8ED5, 0xD6D6_A3E8, 0xA1D1_937E, - 0x38D8_C2C4, 0x4FDF_F252, 0xD1BB_67F1, 0xA6BC_5767, 0x3FB5_06DD, 0x48B2_364B, 0xD80D_2BDA, 0xAF0A_1B4C, 0x3603_4AF6, - 0x4104_7A60, 0xDF60_EFC3, 0xA867_DF55, 0x316E_8EEF, 0x4669_BE79, 0xCB61_B38C, 0xBC66_831A, 0x256F_D2A0, 0x5268_E236, - 0xCC0C_7795, 0xBB0B_4703, 0x2202_16B9, 0x5505_262F, 0xC5BA_3BBE, 0xB2BD_0B28, 0x2BB4_5A92, 0x5CB3_6A04, 0xC2D7_FFA7, - 0xB5D0_CF31, 0x2CD9_9E8B, 0x5BDE_AE1D, 0x9B64_C2B0, 0xEC63_F226, 0x756A_A39C, 0x026D_930A, 0x9C09_06A9, 0xEB0E_363F, - 0x7207_6785, 0x0500_5713, 0x95BF_4A82, 0xE2B8_7A14, 0x7BB1_2BAE, 0x0CB6_1B38, 0x92D2_8E9B, 0xE5D5_BE0D, 0x7CDC_EFB7, - 0x0BDB_DF21, 0x86D3_D2D4, 0xF1D4_E242, 0x68DD_B3F8, 0x1FDA_836E, 0x81BE_16CD, 0xF6B9_265B, 0x6FB0_77E1, 0x18B7_4777, - 0x8808_5AE6, 0xFF0F_6A70, 0x6606_3BCA, 0x1101_0B5C, 0x8F65_9EFF, 0xF862_AE69, 0x616B_FFD3, 0x166C_CF45, 0xA00A_E278, - 0xD70D_D2EE, 0x4E04_8354, 0x3903_B3C2, 0xA767_2661, 0xD060_16F7, 0x4969_474D, 0x3E6E_77DB, 0xAED1_6A4A, 0xD9D6_5ADC, - 0x40DF_0B66, 0x37D8_3BF0, 0xA9BC_AE53, 0xDEBB_9EC5, 0x47B2_CF7F, 0x30B5_FFE9, 0xBDBD_F21C, 0xCABA_C28A, 0x53B3_9330, - 0x24B4_A3A6, 0xBAD0_3605, 0xCDD7_0693, 0x54DE_5729, 0x23D9_67BF, 0xB366_7A2E, 0xC461_4AB8, 0x5D68_1B02, 0x2A6F_2B94, - 0xB40B_BE37, 0xC30C_8EA1, 0x5A05_DF1B, 0x2D02_EF8D, + 0x0000_0000, + 0x7707_3096, + 0xEE0E_612C, + 0x9909_51BA, + 0x076D_C419, + 0x706A_F48F, + 0xE963_A535, + 0x9E64_95A3, + 0x0EDB_8832, + 0x79DC_B8A4, + 0xE0D5_E91E, + 0x97D2_D988, + 0x09B6_4C2B, + 0x7EB1_7CBD, + 0xE7B8_2D07, + 0x90BF_1D91, + 0x1DB7_1064, + 0x6AB0_20F2, + 0xF3B9_7148, + 0x84BE_41DE, + 0x1ADA_D47D, + 0x6DDD_E4EB, + 0xF4D4_B551, + 0x83D3_85C7, + 0x136C_9856, + 0x646B_A8C0, + 0xFD62_F97A, + 0x8A65_C9EC, + 0x1401_5C4F, + 0x6306_6CD9, + 0xFA0F_3D63, + 0x8D08_0DF5, + 0x3B6E_20C8, + 0x4C69_105E, + 0xD560_41E4, + 0xA267_7172, + 0x3C03_E4D1, + 0x4B04_D447, + 0xD20D_85FD, + 0xA50A_B56B, + 0x35B5_A8FA, + 0x42B2_986C, + 0xDBBB_C9D6, + 0xACBC_F940, + 0x32D8_6CE3, + 0x45DF_5C75, + 0xDCD6_0DCF, + 0xABD1_3D59, + 0x26D9_30AC, + 0x51DE_003A, + 0xC8D7_5180, + 0xBFD0_6116, + 0x21B4_F4B5, + 0x56B3_C423, + 0xCFBA_9599, + 0xB8BD_A50F, + 0x2802_B89E, + 0x5F05_8808, + 0xC60C_D9B2, + 0xB10B_E924, + 0x2F6F_7C87, + 0x5868_4C11, + 0xC161_1DAB, + 0xB666_2D3D, + 0x76DC_4190, + 0x01DB_7106, + 0x98D2_20BC, + 0xEFD5_102A, + 0x71B1_8589, + 0x06B6_B51F, + 0x9FBF_E4A5, + 0xE8B8_D433, + 0x7807_C9A2, + 0x0F00_F934, + 0x9609_A88E, + 0xE10E_9818, + 0x7F6A_0DBB, + 0x086D_3D2D, + 0x9164_6C97, + 0xE663_5C01, + 0x6B6B_51F4, + 0x1C6C_6162, + 0x8565_30D8, + 0xF262_004E, + 0x6C06_95ED, + 0x1B01_A57B, + 0x8208_F4C1, + 0xF50F_C457, + 0x65B0_D9C6, + 0x12B7_E950, + 0x8BBE_B8EA, + 0xFCB9_887C, + 0x62DD_1DDF, + 0x15DA_2D49, + 0x8CD3_7CF3, + 0xFBD4_4C65, + 0x4DB2_6158, + 0x3AB5_51CE, + 0xA3BC_0074, + 0xD4BB_30E2, + 0x4ADF_A541, + 0x3DD8_95D7, + 0xA4D1_C46D, + 0xD3D6_F4FB, + 0x4369_E96A, + 0x346E_D9FC, + 0xAD67_8846, + 0xDA60_B8D0, + 0x4404_2D73, + 0x3303_1DE5, + 0xAA0A_4C5F, + 0xDD0D_7CC9, + 0x5005_713C, + 0x2702_41AA, + 0xBE0B_1010, + 0xC90C_2086, + 0x5768_B525, + 0x206F_85B3, + 0xB966_D409, + 0xCE61_E49F, + 0x5EDE_F90E, + 0x29D9_C998, + 0xB0D0_9822, + 0xC7D7_A8B4, + 0x59B3_3D17, + 0x2EB4_0D81, + 0xB7BD_5C3B, + 0xC0BA_6CAD, + 0xEDB8_8320, + 0x9ABF_B3B6, + 0x03B6_E20C, + 0x74B1_D29A, + 0xEAD5_4739, + 0x9DD2_77AF, + 0x04DB_2615, + 0x73DC_1683, + 0xE363_0B12, + 0x9464_3B84, + 0x0D6D_6A3E, + 0x7A6A_5AA8, + 0xE40E_CF0B, + 0x9309_FF9D, + 0x0A00_AE27, + 0x7D07_9EB1, + 0xF00F_9344, + 0x8708_A3D2, + 0x1E01_F268, + 0x6906_C2FE, + 0xF762_575D, + 0x8065_67CB, + 0x196C_3671, + 0x6E6B_06E7, + 0xFED4_1B76, + 0x89D3_2BE0, + 0x10DA_7A5A, + 0x67DD_4ACC, + 0xF9B9_DF6F, + 0x8EBE_EFF9, + 0x17B7_BE43, + 0x60B0_8ED5, + 0xD6D6_A3E8, + 0xA1D1_937E, + 0x38D8_C2C4, + 0x4FDF_F252, + 0xD1BB_67F1, + 0xA6BC_5767, + 0x3FB5_06DD, + 0x48B2_364B, + 0xD80D_2BDA, + 0xAF0A_1B4C, + 0x3603_4AF6, + 0x4104_7A60, + 0xDF60_EFC3, + 0xA867_DF55, + 0x316E_8EEF, + 0x4669_BE79, + 0xCB61_B38C, + 0xBC66_831A, + 0x256F_D2A0, + 0x5268_E236, + 0xCC0C_7795, + 0xBB0B_4703, + 0x2202_16B9, + 0x5505_262F, + 0xC5BA_3BBE, + 0xB2BD_0B28, + 0x2BB4_5A92, + 0x5CB3_6A04, + 0xC2D7_FFA7, + 0xB5D0_CF31, + 0x2CD9_9E8B, + 0x5BDE_AE1D, + 0x9B64_C2B0, + 0xEC63_F226, + 0x756A_A39C, + 0x026D_930A, + 0x9C09_06A9, + 0xEB0E_363F, + 0x7207_6785, + 0x0500_5713, + 0x95BF_4A82, + 0xE2B8_7A14, + 0x7BB1_2BAE, + 0x0CB6_1B38, + 0x92D2_8E9B, + 0xE5D5_BE0D, + 0x7CDC_EFB7, + 0x0BDB_DF21, + 0x86D3_D2D4, + 0xF1D4_E242, + 0x68DD_B3F8, + 0x1FDA_836E, + 0x81BE_16CD, + 0xF6B9_265B, + 0x6FB0_77E1, + 0x18B7_4777, + 0x8808_5AE6, + 0xFF0F_6A70, + 0x6606_3BCA, + 0x1101_0B5C, + 0x8F65_9EFF, + 0xF862_AE69, + 0x616B_FFD3, + 0x166C_CF45, + 0xA00A_E278, + 0xD70D_D2EE, + 0x4E04_8354, + 0x3903_B3C2, + 0xA767_2661, + 0xD060_16F7, + 0x4969_474D, + 0x3E6E_77DB, + 0xAED1_6A4A, + 0xD9D6_5ADC, + 0x40DF_0B66, + 0x37D8_3BF0, + 0xA9BC_AE53, + 0xDEBB_9EC5, + 0x47B2_CF7F, + 0x30B5_FFE9, + 0xBDBD_F21C, + 0xCABA_C28A, + 0x53B3_9330, + 0x24B4_A3A6, + 0xBAD0_3605, + 0xCDD7_0693, + 0x54DE_5729, + 0x23D9_67BF, + 0xB366_7A2E, + 0xC461_4AB8, + 0x5D68_1B02, + 0x2A6F_2B94, + 0xB40B_BE37, + 0xC30C_8EA1, + 0x5A05_DF1B, + 0x2D02_EF8D, ]; #[allow(non_camel_case_types)] @@ -37,7 +264,8 @@ pub struct ETH_FSC(pub u32); impl ETH_FSC { pub const CRC32_OK: u32 = 0x2144_df1c; - #[must_use] pub fn new(data: &[u8]) -> Self { + #[must_use] + pub fn new(data: &[u8]) -> Self { let fsc = data.iter().fold(u32::MAX, |crc, byte| { let idx = u8::try_from(crc & 0xFF).unwrap() ^ byte; CRC32R_LOOKUP_TABLE[usize::from(idx)] ^ (crc >> 8) @@ -45,15 +273,18 @@ impl ETH_FSC { Self(fsc) } - #[must_use] pub fn crc_ok(&self) -> bool { + #[must_use] + pub fn crc_ok(&self) -> bool { self.0 == Self::CRC32_OK } - #[must_use] pub fn hton_bytes(&self) -> [u8; 4] { + #[must_use] + pub fn hton_bytes(&self) -> [u8; 4] { self.0.to_le_bytes() } - #[must_use] pub fn hton(&self) -> u32 { + #[must_use] + pub fn hton(&self) -> u32 { self.0.to_le() } } diff --git a/embassy-net-adin1110/src/phy.rs b/embassy-net-adin1110/src/phy.rs index 70060a0c..176ad019 100644 --- a/embassy-net-adin1110/src/phy.rs +++ b/embassy-net-adin1110/src/phy.rs @@ -30,7 +30,8 @@ pub mod RegsC45 { } impl DA1 { - #[must_use] pub fn into(self) -> (u8, u16) { + #[must_use] + pub fn into(self) -> (u8, u16) { (0x01, self as u16) } } @@ -48,7 +49,8 @@ pub mod RegsC45 { } impl DA3 { - #[must_use] pub fn into(self) -> (u8, u16) { + #[must_use] + pub fn into(self) -> (u8, u16) { (0x03, self as u16) } } @@ -62,7 +64,8 @@ pub mod RegsC45 { } impl DA7 { - #[must_use] pub fn into(self) -> (u8, u16) { + #[must_use] + pub fn into(self) -> (u8, u16) { (0x07, self as u16) } } @@ -84,7 +87,8 @@ pub mod RegsC45 { } impl DA1E { - #[must_use] pub fn into(self) -> (u8, u16) { + #[must_use] + pub fn into(self) -> (u8, u16) { (0x1e, self as u16) } } @@ -100,7 +104,8 @@ pub mod RegsC45 { } impl DA1F { - #[must_use] pub fn into(self) -> (u8, u16) { + #[must_use] + pub fn into(self) -> (u8, u16) { (0x1f, self as u16) } } From 681165e84c35fcc760977c799aa1372ebdd83f46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20van=20Dorst?= Date: Sun, 20 Aug 2023 23:26:22 +0200 Subject: [PATCH 037/106] add embassy-net-adin1110 to .github/ci/test.sh --- .github/ci/test.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/ci/test.sh b/.github/ci/test.sh index 2892bcf8..04f4fc7c 100755 --- a/.github/ci/test.sh +++ b/.github/ci/test.sh @@ -28,3 +28,5 @@ cargo test --manifest-path ./embassy-rp/Cargo.toml --no-default-features --featu cargo test --manifest-path ./embassy-stm32/Cargo.toml --no-default-features --features nightly,stm32f429vg,exti,time-driver-any,exti cargo test --manifest-path ./embassy-stm32/Cargo.toml --no-default-features --features nightly,stm32f732ze,exti,time-driver-any,exti cargo test --manifest-path ./embassy-stm32/Cargo.toml --no-default-features --features nightly,stm32f769ni,exti,time-driver-any,exti + +cargo test --manifest-path ./embassy-net-adin1110/Cargo.toml From ca588f901f5987b8335f380ef8b5dddd7060f75b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20van=20Dorst?= Date: Mon, 21 Aug 2023 20:44:42 +0200 Subject: [PATCH 038/106] add embassy-net-adin1110 to .github/ci/doc.sh --- .github/ci/doc.sh | 1 + embassy-net-adin1110/src/lib.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/.github/ci/doc.sh b/.github/ci/doc.sh index 57184dc1..c317a12e 100755 --- a/.github/ci/doc.sh +++ b/.github/ci/doc.sh @@ -39,6 +39,7 @@ docserver-builder -i ./embassy-net-wiznet -o webroot/crates/embassy-net-wiznet/g docserver-builder -i ./embassy-net-enc28j60 -o webroot/crates/embassy-net-enc28j60/git.zup docserver-builder -i ./embassy-net-esp-hosted -o webroot/crates/embassy-net-esp-hosted/git.zup docserver-builder -i ./embassy-stm32-wpan -o webroot/crates/embassy-stm32-wpan/git.zup --output-static webroot/static +docserver-builder -i ./embassy-net-adin1110 -o webroot/crates/embassy-net-adin1110/git.zup export KUBECONFIG=/ci/secrets/kubeconfig.yml POD=$(kubectl -n embassy get po -l app=docserver -o jsonpath={.items[0].metadata.name}) diff --git a/embassy-net-adin1110/src/lib.rs b/embassy-net-adin1110/src/lib.rs index 113db3df..fd2bf868 100644 --- a/embassy-net-adin1110/src/lib.rs +++ b/embassy-net-adin1110/src/lib.rs @@ -4,6 +4,7 @@ #![allow(clippy::module_name_repetitions)] #![allow(clippy::missing_errors_doc)] #![allow(clippy::missing_panics_doc)] +#![doc = include_str!("../README.md")] mod crc32; mod crc8; From 4b6045d446ec52906f158d5b48c879c868629ea9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20van=20Dorst?= Date: Mon, 21 Aug 2023 20:53:17 +0200 Subject: [PATCH 039/106] Remove the `SPI::Error` as a generic parameter. --- embassy-net-adin1110/src/lib.rs | 30 +++++++++++------------------- 1 file changed, 11 insertions(+), 19 deletions(-) diff --git a/embassy-net-adin1110/src/lib.rs b/embassy-net-adin1110/src/lib.rs index fd2bf868..e917edcc 100644 --- a/embassy-net-adin1110/src/lib.rs +++ b/embassy-net-adin1110/src/lib.rs @@ -44,7 +44,7 @@ pub enum AdinError { MDIO_ACC_TIMEOUT, } -pub type AEResult = core::result::Result>; +pub type AEResult = core::result::Result>; pub const MDIO_PHY_ADDR: u8 = 0x01; /// Maximum Transmission Unit @@ -100,16 +100,12 @@ pub(crate) fn size_align_u32(size: u32) -> u32 { (size + 3) & 0xFFFF_FFFC } -impl ADIN1110 -where - SPI: SpiDevice, - SpiE: core::fmt::Debug, -{ +impl ADIN1110 { pub fn new(spi: SPI, crc: bool) -> Self { Self { spi, crc } } - pub async fn read_reg(&mut self, reg: sr) -> AEResult { + pub async fn read_reg(&mut self, reg: sr) -> AEResult { let mut tx_buf = Vec::::new(); let mut spi_hdr = SpiHeader(0); @@ -148,7 +144,7 @@ where Ok(value) } - pub async fn write_reg(&mut self, reg: sr, value: u32) -> AEResult<(), SpiE> { + pub async fn write_reg(&mut self, reg: sr, value: u32) -> AEResult<(), SPI::Error> { let mut tx_buf = Vec::::new(); let mut spi_hdr = SpiHeader(0); @@ -177,7 +173,7 @@ where } /// helper function for write to `MDIO_ACC` register and wait for ready! - async fn write_mdio_acc_reg(&mut self, mdio_acc_val: u32) -> AEResult { + async fn write_mdio_acc_reg(&mut self, mdio_acc_val: u32) -> AEResult { self.write_reg(sr::MDIO_ACC, mdio_acc_val).await?; // TODO: Add proper timeout! @@ -192,7 +188,7 @@ where } /// Read out fifo ethernet packet memory received via the wire. - pub async fn read_fifo(&mut self, packet: &mut [u8]) -> AEResult { + pub async fn read_fifo(&mut self, packet: &mut [u8]) -> AEResult { let mut tx_buf = Vec::::new(); // Size of the frame, also includes the appednded header. @@ -238,7 +234,7 @@ where } /// Write to fifo ethernet packet memory send over the wire. - pub async fn write_fifo(&mut self, frame: &[u8]) -> AEResult<(), SpiE> { + pub async fn write_fifo(&mut self, frame: &[u8]) -> AEResult<(), SPI::Error> { let header_len = self.header_write_len(); let mut packet = Packet::new(); @@ -318,7 +314,7 @@ where /// Programs the mac address in the mac filters. /// Also set the boardcast address. /// The chip supports 2 priority queues but current code doesn't support this mode. - pub async fn set_mac_addr(&mut self, mac: &[u8; 6]) -> AEResult<(), SpiE> { + pub async fn set_mac_addr(&mut self, mac: &[u8; 6]) -> AEResult<(), SPI::Error> { let mac_high_part = u16::from_be_bytes(mac[0..2].try_into().unwrap()); let mac_low_part = u32::from_be_bytes(mac[2..6].try_into().unwrap()); @@ -341,12 +337,8 @@ where } } -impl mdio::MdioBus for ADIN1110 -where - SPI: SpiDevice, - SpiE: core::fmt::Debug, -{ - type Error = AdinError; +impl mdio::MdioBus for ADIN1110 { + type Error = AdinError; /// Read from the PHY Registers as Clause 22. async fn read_cl22(&mut self, phy_id: u8, reg: u8) -> Result { @@ -380,7 +372,7 @@ where } /// Write to the PHY Registers as Clause 45. - async fn write_cl45(&mut self, phy_id: u8, regc45: (u8, u16), value: u16) -> AEResult<(), SpiE> { + async fn write_cl45(&mut self, phy_id: u8, regc45: (u8, u16), value: u16) -> AEResult<(), SPI::Error> { let phy_id = u32::from(phy_id & 0x1F) << 21; let dev_addr = u32::from(regc45.0 & 0x1F) << 16; let reg = u32::from(regc45.1); From 5f5e3bcd18040ae3c9bf23196961b804ac8831a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20van=20Dorst?= Date: Mon, 21 Aug 2023 20:58:26 +0200 Subject: [PATCH 040/106] Replace size_align_u32() with next_multiple_of() Currently next_multiple_of() is behinged a Feature gate: int_rounding. See https://github.com/rust-lang/rust/issues/88581 But it seems that this function is stablized in rust 1.73. See https://github.com/rust-lang/rust/pull/94455 Currently Embassy is still using nightly for many other unstable features. So I do see an issue to use this function. --- embassy-net-adin1110/src/lib.rs | 30 +++++------------------------- 1 file changed, 5 insertions(+), 25 deletions(-) diff --git a/embassy-net-adin1110/src/lib.rs b/embassy-net-adin1110/src/lib.rs index e917edcc..8b81065c 100644 --- a/embassy-net-adin1110/src/lib.rs +++ b/embassy-net-adin1110/src/lib.rs @@ -95,11 +95,6 @@ pub struct ADIN1110 { crc: bool, } -/// Round size up the N u32; -pub(crate) fn size_align_u32(size: u32) -> u32 { - (size + 3) & 0xFFFF_FFFC -} - impl ADIN1110 { pub fn new(spi: SPI, crc: bool) -> Self { Self { spi, crc } @@ -192,14 +187,12 @@ impl ADIN1110 { let mut tx_buf = Vec::::new(); // Size of the frame, also includes the appednded header. - let packet_size = self.read_reg(sr::RX_FSIZE).await?; + let packet_size = self.read_reg(sr::RX_FSIZE).await? as usize; // Packet read of write to the MAC packet buffer must be a multipul of 4! - let read_size = size_align_u32(packet_size); + let read_size = packet_size.next_multiple_of(4); - if packet_size < u32::try_from(FRAME_HEADER_LEN + FSC_LEN).unwrap() - || read_size > u32::try_from(packet.len()).unwrap() - { + if packet_size < (FRAME_HEADER_LEN + FSC_LEN) || read_size > packet.len() { return Err(AdinError::PACKET_TOO_BIG); } @@ -836,18 +829,6 @@ mod tests { spi.done(); } - #[test] - fn align_size() { - assert_eq!(size_align_u32(1), 4); - assert_eq!(size_align_u32(2), 4); - assert_eq!(size_align_u32(3), 4); - assert_eq!(size_align_u32(4), 4); - assert_eq!(size_align_u32(5), 8); - assert_eq!(size_align_u32(6), 8); - assert_eq!(size_align_u32(7), 8); - assert_eq!(size_align_u32(8), 8); - } - // #[test] // fn write_packet_to_fifo_less_64b_with_crc() { // // Configure expectations @@ -1224,10 +1205,9 @@ mod tests { // Packet FCS spi_packet.extend_from_slice(&[147, 149, 213, 68]).unwrap(); - let spi_packet_len = u32::try_from(spi_packet.len()).unwrap(); - // SPI HEADER Padding of u32 - for _ in spi_packet_len..size_align_u32(spi_packet_len) { + let spi_packet_len = spi_packet.len(); + for _ in spi_packet_len..spi_packet_len.next_multiple_of(4) { spi_packet.push(0x00).unwrap(); } From 1d4d11ba259b9c7174d2944b6609deeade401055 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20van=20Dorst?= Date: Thu, 24 Aug 2023 00:40:01 +0200 Subject: [PATCH 041/106] =?UTF-8?q?refactor=20write=5Ffifo(),=20don=C2=B4t?= =?UTF-8?q?=20copy=20frame=20data?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now this function uses frame data directly in the SPI transaction instead making a copy of it. Also fixing some length calculations and refactor/add tests to test this function. --- embassy-net-adin1110/src/crc32.rs | 26 ++ embassy-net-adin1110/src/lib.rs | 647 +++++++++++------------------- 2 files changed, 258 insertions(+), 415 deletions(-) diff --git a/embassy-net-adin1110/src/crc32.rs b/embassy-net-adin1110/src/crc32.rs index a41fedca..a3474f70 100644 --- a/embassy-net-adin1110/src/crc32.rs +++ b/embassy-net-adin1110/src/crc32.rs @@ -273,6 +273,15 @@ impl ETH_FSC { Self(fsc) } + #[must_use] + pub fn update(self, data: &[u8]) -> Self { + let fsc = data.iter().fold(self.0 ^ u32::MAX, |crc, byte| { + let idx = u8::try_from(crc & 0xFF).unwrap() ^ byte; + CRC32R_LOOKUP_TABLE[usize::from(idx)] ^ (crc >> 8) + }) ^ u32::MAX; + Self(fsc) + } + #[must_use] pub fn crc_ok(&self) -> bool { self.0 == Self::CRC32_OK @@ -329,4 +338,21 @@ mod tests { println!("{:08x}", own_crc.0); assert_eq!(own_crc.0, ETH_FSC::CRC32_OK); } + + #[test] + fn crc32_update() { + let full_data = &[ + 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0x00, 0xe0, 0x4c, 0x68, 0xee, 0xee, 0xdd, 0x06, 0x00, 0x01, 0x08, 0x00, + 0x06, 0x04, 0x00, 0x02, 0x00, 0xe0, 0x4c, 0x68, 0x09, 0xde, 0xc0, 0xa8, 0x01, 0x02, 0x12, 0x34, 0x56, 0x78, + 0x9a, 0xbc, 0xc0, 0xa8, 0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x3d, 0x67, 0x7c, + ]; + + let (part_a, part_b) = full_data.split_at(16); + let crc_partially = ETH_FSC::new(part_a).update(part_b); + + let crc_full = ETH_FSC::new(full_data); + + assert_eq!(crc_full.0, crc_partially.0); + } } diff --git a/embassy-net-adin1110/src/lib.rs b/embassy-net-adin1110/src/lib.rs index 8b81065c..c0a9b44e 100644 --- a/embassy-net-adin1110/src/lib.rs +++ b/embassy-net-adin1110/src/lib.rs @@ -61,13 +61,17 @@ const ETH_MIN_LEN: usize = 64; /// Ethernet `Frame Check Sequence` length const FSC_LEN: usize = 4; +/// SPI Header, contains SPI action and register id. +const SPI_HEADER_LEN: usize = 2; +/// SPI Header CRC length +const SPI_HEADER_CRC_LEN: usize = 1; +/// Frame Header, const FRAME_HEADER_LEN: usize = 2; -const WR_HEADER_LEN: usize = 2; // P1 = 0x00, P2 = 0x01 const PORT_ID_BYTE: u8 = 0x00; -pub type Packet = Vec; +pub type Packet = Vec; /// Type alias for the embassy-net driver for ADIN1110 pub type Device<'d> = embassy_net_driver_channel::Device<'d, MTU>; @@ -192,7 +196,13 @@ impl ADIN1110 { // Packet read of write to the MAC packet buffer must be a multipul of 4! let read_size = packet_size.next_multiple_of(4); - if packet_size < (FRAME_HEADER_LEN + FSC_LEN) || read_size > packet.len() { + if packet_size < (SPI_HEADER_LEN + FSC_LEN) { + return Err(AdinError::PACKET_TOO_SMALL); + } + + if read_size > packet.len() { + #[cfg(feature = "defmt")] + defmt::trace!("MAX: {} WANT: {}", packet.len(), read_size); return Err(AdinError::PACKET_TOO_BIG); } @@ -209,16 +219,18 @@ impl ADIN1110 { // Turn around byte, TODO: Unknown that this is. let _ = tx_buf.push(TURN_AROUND_BYTE); - let spi_packet = &mut packet[0..read_size as usize]; + let spi_packet = &mut packet[0..read_size]; assert_eq!(spi_packet.len() & 0x03, 0x00); let mut pkt_header = [0, 0]; + let mut fsc = [0, 0, 0, 0]; let mut spi_op = [ Operation::Write(&tx_buf), Operation::Read(&mut pkt_header), Operation::Read(spi_packet), + Operation::Read(&mut fsc), ]; self.spi.transaction(&mut spi_op).await.map_err(AdinError::Spi)?; @@ -228,80 +240,86 @@ impl ADIN1110 { /// Write to fifo ethernet packet memory send over the wire. pub async fn write_fifo(&mut self, frame: &[u8]) -> AEResult<(), SPI::Error> { - let header_len = self.header_write_len(); + const HEAD_LEN: usize = SPI_HEADER_LEN + SPI_HEADER_CRC_LEN + FRAME_HEADER_LEN; + const TAIL_LEN: usize = ETH_MIN_LEN - FSC_LEN + FSC_LEN + 1; - let mut packet = Packet::new(); + if frame.len() < (6 + 6 + 2) { + return Err(AdinError::PACKET_TOO_SMALL); + } + if frame.len() > (MAX_BUFF - FRAME_HEADER_LEN) { + return Err(AdinError::PACKET_TOO_BIG); + } + + // SPI HEADER + [OPTIONAL SPI CRC] + FRAME HEADER + let mut head_data = Vec::::new(); + // [OPTIONAL PAD DATA] + FCS + [OPTINAL BYTES MAKE SPI FRAME EVEN] + let mut tail_data = Vec::::new(); let mut spi_hdr = SpiHeader(0); spi_hdr.set_control(true); spi_hdr.set_write(true); spi_hdr.set_addr(sr::TX); - packet + head_data .extend_from_slice(spi_hdr.0.to_be_bytes().as_slice()) .map_err(|_e| AdinError::PACKET_TOO_BIG)?; if self.crc { // Add CRC for header data - packet - .push(crc8(&packet[0..2])) + head_data + .push(crc8(&head_data[0..2])) .map_err(|_| AdinError::PACKET_TOO_BIG)?; } // Add port number, ADIN1110 its fixed to zero/P1, but for ADIN2111 has two ports. - packet + head_data .extend_from_slice(u16::from(PORT_ID_BYTE).to_be_bytes().as_slice()) .map_err(|_e| AdinError::PACKET_TOO_BIG)?; - // Copy packet data to spi buffer. - packet - .extend_from_slice(frame) - .map_err(|_e| AdinError::PACKET_TOO_BIG)?; + let mut frame_fcs = ETH_FSC::new(frame); - // Pad data up to ETH_MIN_LEN - FCS_LEN - for _ in packet.len()..(ETH_MIN_LEN - FSC_LEN + header_len) { - let _ = packet.push(0x00); + // ADIN1110 MAC and PHY don´t accept ethernet packet smaller than 64 bytes. + // So padded the data minus the FCS, FCS is automatilly added to by the MAC. + if let Some(pad_len) = (ETH_MIN_LEN - FSC_LEN).checked_sub(frame.len()) { + let _ = tail_data.resize(pad_len, 0x00); + frame_fcs = frame_fcs.update(&tail_data); } - // add ethernet FCS only over the ethernet packet. - let crc = ETH_FSC::new(&packet[header_len..]); - let _ = packet.extend_from_slice(crc.hton_bytes().as_slice()); + // Add ethernet FCS only over the ethernet packet. + // Only usefull when `CONFIG0`, `Transmit Frame Check Sequence Validation Enable` bit is enabled. + let _ = tail_data.extend_from_slice(frame_fcs.hton_bytes().as_slice()); - let send_len = - u32::try_from(packet.len() - header_len + FRAME_HEADER_LEN).map_err(|_| AdinError::PACKET_TOO_BIG)?; + // len = frame_size + optional padding + 2 bytes Frame header + let send_len_orig = frame.len() + tail_data.len() + FRAME_HEADER_LEN; + let spi_pad_len = send_len_orig.next_multiple_of(4); + let send_len = u32::try_from(send_len_orig).map_err(|_| AdinError::PACKET_TOO_BIG)?; // Packet read of write to the MAC packet buffer must be a multipul of 4 bytes! - while packet.len() & 0x3 != 0 { - let _ = packet.push(DONT_CARE_BYTE); + if spi_pad_len != send_len_orig { + let spi_pad_len = spi_pad_len - send_len_orig; + let _ = tail_data.extend_from_slice(&[DONT_CARE_BYTE, DONT_CARE_BYTE, DONT_CARE_BYTE][..spi_pad_len]); } #[cfg(feature = "defmt")] defmt::trace!( - "TX: hdr {} [{}] {:02x} SIZE: {}", - header_len, - packet.len(), - &packet, + "TX: hdr {} [{}] {:02x}-{:02x}-{:02x} SIZE: {}", + head_data.len(), + frame.len(), + head_data.as_slice(), + frame, + tail_data.as_slice(), send_len, ); self.write_reg(sr::TX_FSIZE, send_len).await?; - // Spi packet must be half word / even length - if send_len & 1 != 0 { - let _ = packet.push(0x00); - } + let mut transaction = [ + Operation::Write(head_data.as_slice()), + Operation::Write(frame), + Operation::Write(tail_data.as_slice()), + ]; - self.spi.write(&packet).await.map_err(AdinError::Spi) - } - - pub fn header_write_len(&self) -> usize { - // u16 + [CRC] + PORT - WR_HEADER_LEN + FRAME_HEADER_LEN + usize::from(self.crc) - } - - pub fn header_len_read(&self) -> usize { - // u16 + [CRC] + u8 - WR_HEADER_LEN + 1 + usize::from(self.crc) + self.spi.transaction(&mut transaction).await.map_err(AdinError::Spi) } /// Programs the mac address in the mac filters. @@ -815,12 +833,12 @@ mod tests { SpiTransaction::write_vec(vec![0xA0, 0x09, 39, 0x12, 0x34, 0x56, 0x78, 28]), SpiTransaction::flush(), ]; - let mut spi = SpiMock::new(&expectations); + // Basic test init block + let mut spi = SpiMock::new(&expectations); let cs = CsPinMock::default(); let delay = MockDelay {}; let spi_dev = ExclusiveDevice::new(spi.clone(), cs, delay); - let mut spe = ADIN1110::new(spi_dev, true); // Write reg: 0x1FFF @@ -829,389 +847,31 @@ mod tests { spi.done(); } - // #[test] - // fn write_packet_to_fifo_less_64b_with_crc() { - // // Configure expectations - // let mut expectations = vec![ - // // HEADER - // SpiTransaction::send(0xA0), - // SpiTransaction::read(DONT_CARE_BYTE), - // SpiTransaction::send(0x30), - // SpiTransaction::read(DONT_CARE_BYTE), - // SpiTransaction::send(136), - // SpiTransaction::read(DONT_CARE_BYTE), - // // Frame Size - // SpiTransaction::send(0x00), - // SpiTransaction::read(DONT_CARE_BYTE), - // SpiTransaction::send(0x00), - // SpiTransaction::read(DONT_CARE_BYTE), - // SpiTransaction::send(0x00), - // SpiTransaction::read(DONT_CARE_BYTE), - // SpiTransaction::send(66), - // SpiTransaction::read(DONT_CARE_BYTE), - // SpiTransaction::send(201), - // SpiTransaction::read(DONT_CARE_BYTE), - // // HEADER - // SpiTransaction::send(0xA0), - // SpiTransaction::read(DONT_CARE_BYTE), - // SpiTransaction::send(0x31), - // SpiTransaction::read(DONT_CARE_BYTE), - // // Port - // SpiTransaction::send(0x00), - // SpiTransaction::read(DONT_CARE_BYTE), - // SpiTransaction::send(PORT_ID_BYTE), - // SpiTransaction::read(DONT_CARE_BYTE), - // ]; - - // let mut packet = Packet::new(); - // packet.resize(ETH_MIN_LEN, 0).unwrap(); - - // for &byte in &packet[4..] { - // expectations.push(SpiTransaction::send(byte)); - // expectations.push(SpiTransaction::read(DONT_CARE_BYTE)); - // } - - // // padding - // for _ in packet.len()..65 { - // expectations.push(SpiTransaction::send(0x00)); - // expectations.push(SpiTransaction::read(DONT_CARE_BYTE)); - // } - - // // fcs - // for &byte in &[8, 137, 18, 4] { - // expectations.push(SpiTransaction::send(byte)); - // expectations.push(SpiTransaction::read(DONT_CARE_BYTE)); - // } - - // let spi = SpiMock::new(&expectations); - - // let cs = CsPinMock {}; - // let mut spe = Adin1110::new(spi, cs, true); - - // assert!(spe.write_fifo(&mut packet).is_ok()); - // } - - // #[test] - // fn write_packet_to_fifo_less_64b_no_crc() { - // // Configure expectations - // let mut expectations = vec![ - // // HEADER - // SpiTransaction::send(0xA0), - // SpiTransaction::read(DONT_CARE_BYTE), - // SpiTransaction::send(0x30), - // SpiTransaction::read(DONT_CARE_BYTE), - // // Frame Size - // SpiTransaction::send(0x00), - // SpiTransaction::read(DONT_CARE_BYTE), - // SpiTransaction::send(0x00), - // SpiTransaction::read(DONT_CARE_BYTE), - // SpiTransaction::send(0x00), - // SpiTransaction::read(DONT_CARE_BYTE), - // SpiTransaction::send(66), - // SpiTransaction::read(DONT_CARE_BYTE), - // // HEADER - // SpiTransaction::send(0xA0), - // SpiTransaction::read(DONT_CARE_BYTE), - // SpiTransaction::send(0x31), - // SpiTransaction::read(DONT_CARE_BYTE), - // // Port - // SpiTransaction::send(0x00), - // SpiTransaction::read(DONT_CARE_BYTE), - // SpiTransaction::send(PORT_ID_BYTE), - // SpiTransaction::read(DONT_CARE_BYTE), - // ]; - - // let mut packet = Packet::new(); - // packet.resize(ETH_MIN_LEN, 0).unwrap(); - - // for &byte in &packet[4..] { - // expectations.push(SpiTransaction::send(byte)); - // expectations.push(SpiTransaction::read(DONT_CARE_BYTE)); - // } - - // // padding - // for _ in packet.len() as u32..ETH_MIN_LEN { - // expectations.push(SpiTransaction::send(0x00)); - // expectations.push(SpiTransaction::read(DONT_CARE_BYTE)); - // } - - // // fcs - // for &byte in &[8, 137, 18, 4] { - // expectations.push(SpiTransaction::send(byte)); - // expectations.push(SpiTransaction::read(DONT_CARE_BYTE)); - // } - - // let spi = SpiMock::new(&expectations); - - // let cs = CsPinMock {}; - // let mut spe = Adin1110::new(spi, cs, false); - - // assert!(spe.write_fifo(&mut packet).is_ok()); - // } - - // #[test] - // fn write_packet_to_fifo_1500b() { - // // Configure expectations - // let mut expectations = vec![ - // // HEADER - // SpiTransaction::send(0xA0), - // SpiTransaction::read(DONT_CARE_BYTE), - // SpiTransaction::send(0x30), - // SpiTransaction::read(DONT_CARE_BYTE), - // // Frame Size - // SpiTransaction::send(0x00), - // SpiTransaction::read(DONT_CARE_BYTE), - // SpiTransaction::send(0x00), - // SpiTransaction::read(DONT_CARE_BYTE), - // SpiTransaction::send(0x05), - // SpiTransaction::read(DONT_CARE_BYTE), - // SpiTransaction::send(0xDE), - // SpiTransaction::read(DONT_CARE_BYTE), - // // HEADER - // SpiTransaction::send(0xA0), - // SpiTransaction::read(DONT_CARE_BYTE), - // SpiTransaction::send(0x31), - // SpiTransaction::read(DONT_CARE_BYTE), - // // Port - // SpiTransaction::send(0x00), - // SpiTransaction::read(DONT_CARE_BYTE), - // SpiTransaction::send(PORT_ID_BYTE), - // SpiTransaction::read(DONT_CARE_BYTE), - // ]; - - // let mut packet = Packet::new(); - // packet.resize(1500, 0).unwrap(); - - // for &byte in &packet[4..] { - // expectations.push(SpiTransaction::send(byte)); - // expectations.push(SpiTransaction::read(DONT_CARE_BYTE)); - // } - - // // fcs - // for &byte in &[212, 114, 18, 50] { - // expectations.push(SpiTransaction::send(byte)); - // expectations.push(SpiTransaction::read(DONT_CARE_BYTE)); - // } - - // let spi = SpiMock::new(&expectations); - - // let cs = CsPinMock {}; - // let mut spe = Adin1110::new(spi, cs, false); - - // assert!(spe.write_fifo(&mut packet).is_ok()); - // } - - // #[test] - // fn write_packet_to_fifo_65b() { - // // Configure expectations - // let mut expectations = vec![ - // // HEADER - // SpiTransaction::send(0xA0), - // SpiTransaction::read(DONT_CARE_BYTE), - // SpiTransaction::send(0x30), - // SpiTransaction::read(DONT_CARE_BYTE), - // // Frame Size - // SpiTransaction::send(0x00), - // SpiTransaction::read(DONT_CARE_BYTE), - // SpiTransaction::send(0x00), - // SpiTransaction::read(DONT_CARE_BYTE), - // SpiTransaction::send(0x00), - // SpiTransaction::read(DONT_CARE_BYTE), - // SpiTransaction::send(67), - // SpiTransaction::read(DONT_CARE_BYTE), - // // HEADER - // SpiTransaction::send(0xA0), - // SpiTransaction::read(DONT_CARE_BYTE), - // SpiTransaction::send(0x31), - // SpiTransaction::read(DONT_CARE_BYTE), - // // Port - // SpiTransaction::send(0x00), - // SpiTransaction::read(DONT_CARE_BYTE), - // SpiTransaction::send(PORT_ID_BYTE), - // SpiTransaction::read(DONT_CARE_BYTE), - // ]; - - // let mut packet = Packet::new(); - // packet.resize(65, 0).unwrap(); - - // for &byte in &packet[4..] { - // expectations.push(SpiTransaction::send(byte)); - // expectations.push(SpiTransaction::read(DONT_CARE_BYTE)); - // } - - // // padding - // for _ in packet.len()..ETH_MIN_LEN { - // expectations.push(SpiTransaction::send(0x00)); - // expectations.push(SpiTransaction::read(DONT_CARE_BYTE)); - // } - - // // fcs - // for &byte in &[54, 117, 221, 220] { - // expectations.push(SpiTransaction::send(byte)); - // expectations.push(SpiTransaction::read(DONT_CARE_BYTE)); - // } - - // let spi = SpiMock::new(&expectations); - - // let cs = CsPinMock {}; - // let mut spe = Adin1110::new(spi, cs, false); - - // assert!(spe.write_fifo(&mut packet).is_ok()); - // } - - // #[test] - // fn write_packet_to_fifo_66b() { - // // Configure expectations - // let mut expectations = vec![ - // // HEADER - // SpiTransaction::send(0xA0), - // SpiTransaction::read(DONT_CARE_BYTE), - // SpiTransaction::send(0x30), - // SpiTransaction::read(DONT_CARE_BYTE), - // // Frame Size - // SpiTransaction::send(0x00), - // SpiTransaction::read(DONT_CARE_BYTE), - // SpiTransaction::send(0x00), - // SpiTransaction::read(DONT_CARE_BYTE), - // SpiTransaction::send(0x00), - // SpiTransaction::read(DONT_CARE_BYTE), - // SpiTransaction::send(68), - // SpiTransaction::read(DONT_CARE_BYTE), - // // HEADER - // SpiTransaction::send(0xA0), - // SpiTransaction::read(DONT_CARE_BYTE), - // SpiTransaction::send(0x31), - // SpiTransaction::read(DONT_CARE_BYTE), - // // Port - // SpiTransaction::send(0x00), - // SpiTransaction::read(DONT_CARE_BYTE), - // SpiTransaction::send(PORT_ID_BYTE), - // SpiTransaction::read(DONT_CARE_BYTE), - // ]; - - // let mut packet = Packet::new(); - // packet.resize(66, 0).unwrap(); - - // for &byte in &packet[4..] { - // expectations.push(SpiTransaction::send(byte)); - // expectations.push(SpiTransaction::read(DONT_CARE_BYTE)); - // } - - // // padding - // for _ in packet.len()..ETH_MIN_LEN { - // expectations.push(SpiTransaction::send(0x00)); - // expectations.push(SpiTransaction::read(DONT_CARE_BYTE)); - // } - - // // fcs - // for &byte in &[97, 167, 100, 29] { - // expectations.push(SpiTransaction::send(byte)); - // expectations.push(SpiTransaction::read(DONT_CARE_BYTE)); - // } - // let spi = SpiMock::new(&expectations); - - // let cs = CsPinMock {}; - // let mut spe = Adin1110::new(spi, cs, false); - - // assert!(spe.write_fifo(&mut packet).is_ok()); - // } - - // #[test] - // fn write_packet_to_fifo_67b() { - // // Configure expectations - // let mut expectations = vec![ - // // HEADER - // SpiTransaction::send(0xA0), - // SpiTransaction::read(DONT_CARE_BYTE), - // SpiTransaction::send(0x30), - // SpiTransaction::read(DONT_CARE_BYTE), - // // Frame Size - // SpiTransaction::send(0x00), - // SpiTransaction::read(DONT_CARE_BYTE), - // SpiTransaction::send(0x00), - // SpiTransaction::read(DONT_CARE_BYTE), - // SpiTransaction::send(0x00), - // SpiTransaction::read(DONT_CARE_BYTE), - // SpiTransaction::send(69), - // SpiTransaction::read(DONT_CARE_BYTE), - // // HEADER - // SpiTransaction::send(0xA0), - // SpiTransaction::read(DONT_CARE_BYTE), - // SpiTransaction::send(0x31), - // SpiTransaction::read(DONT_CARE_BYTE), - // // Port - // SpiTransaction::send(0x00), - // SpiTransaction::read(DONT_CARE_BYTE), - // SpiTransaction::send(PORT_ID_BYTE), - // SpiTransaction::read(DONT_CARE_BYTE), - // ]; - - // let mut packet = Packet::new(); - // packet.resize(67, 0).unwrap(); - - // for &byte in &packet[4..] { - // expectations.push(SpiTransaction::send(byte)); - // expectations.push(SpiTransaction::read(DONT_CARE_BYTE)); - // } - - // // padding - // for _ in packet.len()..ETH_MIN_LEN { - // expectations.push(SpiTransaction::send(0x00)); - // expectations.push(SpiTransaction::read(DONT_CARE_BYTE)); - // } - - // // fcs - // for &byte in &[228, 218, 170, 232] { - // expectations.push(SpiTransaction::send(byte)); - // expectations.push(SpiTransaction::read(DONT_CARE_BYTE)); - // } - // let spi = SpiMock::new(&expectations); - - // let cs = CsPinMock {}; - // let mut spe = Adin1110::new(spi, cs, false); - - // assert!(spe.write_fifo(&mut packet).is_ok()); - // } - #[futures_test::test] - async fn write_packet_to_fifo_arp_46bytes() { + async fn write_packet_to_fifo_minimal_with_crc() { // Configure expectations let mut expectations = vec![]; - let mut packet = Packet::new(); - //arp packet; - packet - .extend_from_slice(&[ - 34, 51, 68, 85, 102, 119, 18, 52, 86, 120, 154, 188, 8, 6, 0, 1, 8, 0, 6, 4, 0, 2, 18, 52, 86, 120, - 154, 188, 192, 168, 16, 4, 34, 51, 68, 85, 102, 119, 192, 168, 16, 1, - ]) - .unwrap(); - - let mut spi_packet = Packet::new(); - // Write TX_SIZE reg expectations.push(SpiTransaction::write_vec(vec![160, 48, 136, 0, 0, 0, 66, 201])); expectations.push(SpiTransaction::flush()); // Write TX reg. - // Header - spi_packet.extend_from_slice(&[160, 49, 143, 0, 0]).unwrap(); + // SPI Header + optional CRC + Frame Header + expectations.push(SpiTransaction::write_vec(vec![160, 49, 143, 0, 0])); // Packet data - spi_packet.extend_from_slice(&packet).unwrap(); - // Packet padding up to 60 (ETH_MIN_LEN - FCS) - for _ in packet.len()..(ETH_MIN_LEN - FSC_LEN) { - spi_packet.push(0x00).unwrap(); - } - // Packet FCS - spi_packet.extend_from_slice(&[147, 149, 213, 68]).unwrap(); + let packet = [0xFF_u8; 60]; + expectations.push(SpiTransaction::write_vec(packet.to_vec())); - // SPI HEADER Padding of u32 - let spi_packet_len = spi_packet.len(); - for _ in spi_packet_len..spi_packet_len.next_multiple_of(4) { - spi_packet.push(0x00).unwrap(); + let mut tail = std::vec::Vec::::with_capacity(100); + // Padding + if let Some(padding_len) = (ETH_MIN_LEN - FSC_LEN).checked_sub(packet.len()) { + tail.resize(padding_len, 0x00); } + // Packet FCS + optinal padding + tail.extend_from_slice(&[77, 241, 140, 244, DONT_CARE_BYTE, DONT_CARE_BYTE]); - expectations.push(SpiTransaction::write_vec(spi_packet.to_vec())); + expectations.push(SpiTransaction::write_vec(tail)); expectations.push(SpiTransaction::flush()); let mut spi = SpiMock::new(&expectations); @@ -1226,4 +886,161 @@ mod tests { spi.done(); } + + #[futures_test::test] + async fn write_packet_to_fifo_max_mtu_with_crc() { + assert_eq!(MTU, 1514); + // Configure expectations + let mut expectations = vec![]; + + // Write TX_SIZE reg + expectations.push(SpiTransaction::write_vec(vec![160, 48, 136, 0, 0, 5, 240, 159])); + expectations.push(SpiTransaction::flush()); + + // Write TX reg. + // SPI Header + optional CRC + Frame Header + expectations.push(SpiTransaction::write_vec(vec![160, 49, 143, 0, 0])); + // Packet data + let packet = [0xAA_u8; MTU]; + expectations.push(SpiTransaction::write_vec(packet.to_vec())); + + let mut tail = std::vec::Vec::::with_capacity(100); + // Padding + if let Some(padding_len) = (ETH_MIN_LEN - FSC_LEN).checked_sub(packet.len()) { + tail.resize(padding_len, 0x00); + } + // Packet FCS + optinal padding + tail.extend_from_slice(&[49, 196, 205, 160]); + + expectations.push(SpiTransaction::write_vec(tail)); + expectations.push(SpiTransaction::flush()); + + let mut spi = SpiMock::new(&expectations); + + let cs = CsPinMock::default(); + let delay = MockDelay {}; + let spi_dev = ExclusiveDevice::new(spi.clone(), cs, delay); + + let mut spe = ADIN1110::new(spi_dev, true); + + assert!(spe.write_fifo(&packet).await.is_ok()); + + spi.done(); + } + + #[futures_test::test] + async fn write_packet_to_fifo_invalid_lengths() { + assert_eq!(MTU, 1514); + + // Configure expectations + let expectations = vec![]; + + // Max packet size = MAX_BUFF - FRAME_HEADER_LEN + let packet = [0xAA_u8; MAX_BUFF - FRAME_HEADER_LEN + 1]; + + let mut spi = SpiMock::new(&expectations); + + let cs = CsPinMock::default(); + let delay = MockDelay {}; + let spi_dev = ExclusiveDevice::new(spi.clone(), cs, delay); + + let mut spe = ADIN1110::new(spi_dev, true); + + // minimal + assert!(matches!( + spe.write_fifo(&packet[0..(6 + 6 + 2 - 1)]).await, + Err(AdinError::PACKET_TOO_SMALL) + )); + + // max + 1 + assert!(matches!(spe.write_fifo(&packet).await, Err(AdinError::PACKET_TOO_BIG))); + + spi.done(); + } + + #[futures_test::test] + async fn write_packet_to_fifo_arp_46bytes_with_crc() { + // Configure expectations + let mut expectations = vec![]; + + // Write TX_SIZE reg + expectations.push(SpiTransaction::write_vec(vec![160, 48, 136, 0, 0, 0, 66, 201])); + expectations.push(SpiTransaction::flush()); + + // Write TX reg. + // Header + expectations.push(SpiTransaction::write_vec(vec![160, 49, 143, 0, 0])); + // Packet data + let packet = [ + 34, 51, 68, 85, 102, 119, 18, 52, 86, 120, 154, 188, 8, 6, 0, 1, 8, 0, 6, 4, 0, 2, 18, 52, 86, 120, 154, + 188, 192, 168, 16, 4, 34, 51, 68, 85, 102, 119, 192, 168, 16, 1, + ]; + expectations.push(SpiTransaction::write_vec(packet.to_vec())); + + let mut tail = std::vec::Vec::::with_capacity(100); + // Padding + if let Some(padding_len) = (ETH_MIN_LEN - FSC_LEN).checked_sub(packet.len()) { + tail.resize(padding_len, 0x00); + } + // Packet FCS + optinal padding + tail.extend_from_slice(&[147, 149, 213, 68, DONT_CARE_BYTE, DONT_CARE_BYTE]); + + expectations.push(SpiTransaction::write_vec(tail)); + expectations.push(SpiTransaction::flush()); + + let mut spi = SpiMock::new(&expectations); + + let cs = CsPinMock::default(); + let delay = MockDelay {}; + let spi_dev = ExclusiveDevice::new(spi.clone(), cs, delay); + + let mut spe = ADIN1110::new(spi_dev, true); + + assert!(spe.write_fifo(&packet).await.is_ok()); + + spi.done(); + } + + #[futures_test::test] + async fn write_packet_to_fifo_arp_46bytes_without_crc() { + // Configure expectations + let mut expectations = vec![]; + + // Write TX_SIZE reg + expectations.push(SpiTransaction::write_vec(vec![160, 48, 0, 0, 0, 66])); + expectations.push(SpiTransaction::flush()); + + // Write TX reg. + // SPI Header + Frame Header + expectations.push(SpiTransaction::write_vec(vec![160, 49, 0, 0])); + // Packet data + let packet = [ + 34, 51, 68, 85, 102, 119, 18, 52, 86, 120, 154, 188, 8, 6, 0, 1, 8, 0, 6, 4, 0, 2, 18, 52, 86, 120, 154, + 188, 192, 168, 16, 4, 34, 51, 68, 85, 102, 119, 192, 168, 16, 1, + ]; + expectations.push(SpiTransaction::write_vec(packet.to_vec())); + + let mut tail = std::vec::Vec::::with_capacity(100); + // Padding + if let Some(padding_len) = (ETH_MIN_LEN - FSC_LEN).checked_sub(packet.len()) { + tail.resize(padding_len, 0x00); + } + // Packet FCS + optinal padding + tail.extend_from_slice(&[147, 149, 213, 68, DONT_CARE_BYTE, DONT_CARE_BYTE]); + + expectations.push(SpiTransaction::write_vec(tail)); + expectations.push(SpiTransaction::flush()); + + let mut spi = SpiMock::new(&expectations); + + let cs = CsPinMock::default(); + let delay = MockDelay {}; + let spi_dev = ExclusiveDevice::new(spi.clone(), cs, delay); + + let mut spe = ADIN1110::new(spi_dev, false); + + assert!(spe.write_fifo(&packet).await.is_ok()); + + spi.done(); + } } From fc04d2a33caa300bce38f7d0a46f1a0c814bb613 Mon Sep 17 00:00:00 2001 From: xoviat Date: Wed, 23 Aug 2023 19:52:32 -0500 Subject: [PATCH 042/106] rtc: get wakup irq working --- embassy-stm32/src/low_power.rs | 4 +++ embassy-stm32/src/rtc/v2.rs | 48 ++++++++++++++++++++-------------- 2 files changed, 32 insertions(+), 20 deletions(-) diff --git a/embassy-stm32/src/low_power.rs b/embassy-stm32/src/low_power.rs index 7d5093b6..f4bf7bbe 100644 --- a/embassy-stm32/src/low_power.rs +++ b/embassy-stm32/src/low_power.rs @@ -7,6 +7,7 @@ use embassy_time::Duration; use crate::interrupt; use crate::interrupt::typelevel::Interrupt; +use crate::pac::EXTI; const THREAD_PENDER: usize = usize::MAX; const THRESHOLD: Duration = Duration::from_millis(500); @@ -28,6 +29,9 @@ pub fn stop_with_rtc(rtc: &'static Rtc) { crate::interrupt::typelevel::RTC_WKUP::unpend(); unsafe { crate::interrupt::typelevel::RTC_WKUP::enable() }; + EXTI.rtsr(0).modify(|w| w.set_line(22, true)); + EXTI.imr(0).modify(|w| w.set_line(22, true)); + unsafe { RTC = Some(rtc) }; } diff --git a/embassy-stm32/src/rtc/v2.rs b/embassy-stm32/src/rtc/v2.rs index e03c7d2a..1d4f4df3 100644 --- a/embassy-stm32/src/rtc/v2.rs +++ b/embassy-stm32/src/rtc/v2.rs @@ -1,3 +1,4 @@ +use defmt::Format; use stm32_metapac::rtc::vals::{Init, Osel, Pol}; use super::{sealed, RtcClockSource, RtcConfig}; @@ -73,7 +74,7 @@ impl core::ops::Sub for RtcInstant { } #[allow(dead_code)] -#[derive(Clone, Copy)] +#[derive(Clone, Copy, Debug, Format)] pub(crate) enum WakeupPrescaler { Div2, Div4, @@ -185,17 +186,26 @@ impl super::Rtc { ); trace!("set wakeup timer for {} ms", duration.as_millis()); + trace!("set wakeup timer for {} ticks with pre {}", rtc_ticks, prescaler); - RTC::regs().wpr().write(|w| w.set_key(0xca)); - RTC::regs().wpr().write(|w| w.set_key(0x53)); + self.write(false, |regs| { + regs.cr().modify(|w| w.set_wutie(true)); - RTC::regs().wutr().modify(|w| w.set_wut(rtc_ticks)); + trace!("clear wute"); + regs.cr().modify(|w| w.set_wute(false)); + regs.isr().modify(|w| w.set_wutf(false)); - RTC::regs().cr().modify(|w| { - w.set_wucksel(prescaler.into()); + trace!("wait for wutwf..."); + while !regs.isr().read().wutwf() {} + trace!("wait for wutwf...done"); - w.set_wutie(true); - w.set_wute(true); + regs.cr().modify(|w| { + w.set_wucksel(prescaler.into()); + + w.set_wutie(true); + }); + + regs.cr().modify(|w| w.set_wute(true)); }); if !RTC::regs().cr().read().wute() { @@ -204,6 +214,12 @@ impl super::Rtc { trace!("wakeup timer enabled"); } + if !RTC::regs().cr().read().wutie() { + trace!("wakeup timer interrupt not enabled"); + } else { + trace!("wakeup timer interrupt enabled"); + } + RtcInstant::now() } @@ -216,19 +232,11 @@ impl super::Rtc { pub(crate) fn stop_wakeup_alarm(&self) -> RtcInstant { trace!("disable wakeup timer..."); - RTC::regs().cr().modify(|w| { - w.set_wute(false); + self.write(false, |regs| { + regs.cr().modify(|w| w.set_wute(false)); + regs.isr().modify(|w| w.set_wutf(false)); }); - trace!("wait for wakeup timer stop..."); - - // Wait for the wakeup timer to stop - // while !RTC::regs().isr().read().wutf() {} - // - // RTC::regs().isr().modify(|w| w.set_wutf(false)); - - trace!("wait for wakeup timer stop...done"); - RtcInstant::now() } @@ -380,7 +388,7 @@ impl super::Rtc { }) } - pub(super) fn write(&mut self, init_mode: bool, f: F) -> R + pub(super) fn write(&self, init_mode: bool, f: F) -> R where F: FnOnce(&crate::pac::rtc::Rtc) -> R, { From e987259716c56f9854cc4730620d7b5a8be9962d Mon Sep 17 00:00:00 2001 From: xoviat Date: Wed, 23 Aug 2023 20:01:35 -0500 Subject: [PATCH 043/106] rtc: cleanup --- embassy-stm32/src/rtc/v2.rs | 41 ++++--------------------------------- 1 file changed, 4 insertions(+), 37 deletions(-) diff --git a/embassy-stm32/src/rtc/v2.rs b/embassy-stm32/src/rtc/v2.rs index 1d4f4df3..bcb127ec 100644 --- a/embassy-stm32/src/rtc/v2.rs +++ b/embassy-stm32/src/rtc/v2.rs @@ -1,4 +1,3 @@ -use defmt::Format; use stm32_metapac::rtc::vals::{Init, Osel, Pol}; use super::{sealed, RtcClockSource, RtcConfig}; @@ -45,25 +44,15 @@ impl core::ops::Sub for RtcInstant { fn sub(self, rhs: Self) -> Self::Output { use embassy_time::{Duration, TICK_HZ}; - trace!("self st: {}", self.st); - trace!("other st: {}", rhs.st); - - trace!("self ssr: {}", self.ssr); - trace!("other ssr: {}", rhs.ssr); - let st = if self.st < rhs.st { self.st + 60 } else { self.st }; - trace!("self st: {}", st); + // TODO: read prescaler let self_ticks = st as u32 * 256 + (255 - self.ssr as u32); let other_ticks = rhs.st as u32 * 256 + (255 - rhs.ssr as u32); let rtc_ticks = self_ticks - other_ticks; - trace!("self ticks: {}", self_ticks); - trace!("other ticks: {}", other_ticks); - trace!("rtc ticks: {}", rtc_ticks); - - // TODO: read prescaler + trace!("self, other, rtc ticks: {}, {}, {}", self_ticks, other_ticks, rtc_ticks); Duration::from_ticks( ((((st as u32 * 256 + (255u32 - self.ssr as u32)) - (rhs.st as u32 * 256 + (255u32 - rhs.ssr as u32))) @@ -74,7 +63,7 @@ impl core::ops::Sub for RtcInstant { } #[allow(dead_code)] -#[derive(Clone, Copy, Debug, Format)] +#[derive(Clone, Copy, Debug)] pub(crate) enum WakeupPrescaler { Div2, Div4, @@ -186,40 +175,18 @@ impl super::Rtc { ); trace!("set wakeup timer for {} ms", duration.as_millis()); - trace!("set wakeup timer for {} ticks with pre {}", rtc_ticks, prescaler); self.write(false, |regs| { regs.cr().modify(|w| w.set_wutie(true)); - trace!("clear wute"); regs.cr().modify(|w| w.set_wute(false)); regs.isr().modify(|w| w.set_wutf(false)); - - trace!("wait for wutwf..."); while !regs.isr().read().wutwf() {} - trace!("wait for wutwf...done"); - - regs.cr().modify(|w| { - w.set_wucksel(prescaler.into()); - - w.set_wutie(true); - }); + regs.cr().modify(|w| w.set_wucksel(prescaler.into())); regs.cr().modify(|w| w.set_wute(true)); }); - if !RTC::regs().cr().read().wute() { - trace!("wakeup timer not enabled"); - } else { - trace!("wakeup timer enabled"); - } - - if !RTC::regs().cr().read().wutie() { - trace!("wakeup timer interrupt not enabled"); - } else { - trace!("wakeup timer interrupt enabled"); - } - RtcInstant::now() } From 83f224e14094488244792dc1bc6d7425d8dcd68f Mon Sep 17 00:00:00 2001 From: xoviat Date: Wed, 23 Aug 2023 20:18:34 -0500 Subject: [PATCH 044/106] stm32/lp: add refcount --- embassy-stm32/build.rs | 4 ++++ embassy-stm32/src/rcc/mod.rs | 21 +++++++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs index 8a731620..6c364f7b 100644 --- a/embassy-stm32/build.rs +++ b/embassy-stm32/build.rs @@ -356,6 +356,8 @@ fn main() { } fn enable() { critical_section::with(|_| { + #[cfg(feature = "low-power")] + crate::rcc::clock_refcount_add(); crate::pac::RCC.#en_reg().modify(|w| w.#set_en_field(true)); #after_enable }) @@ -363,6 +365,8 @@ fn main() { fn disable() { critical_section::with(|_| { crate::pac::RCC.#en_reg().modify(|w| w.#set_en_field(false)); + #[cfg(feature = "low-power")] + crate::rcc::clock_refcount_sub(); }) } fn reset() { diff --git a/embassy-stm32/src/rcc/mod.rs b/embassy-stm32/src/rcc/mod.rs index ac9ae9c6..3c75923e 100644 --- a/embassy-stm32/src/rcc/mod.rs +++ b/embassy-stm32/src/rcc/mod.rs @@ -26,6 +26,8 @@ use crate::time::Hertz; #[cfg_attr(any(rcc_h5, rcc_h50), path = "h5.rs")] mod _version; pub use _version::*; +#[cfg(feature = "low-power")] +use atomic_polyfill::{AtomicU32, Ordering}; #[derive(Clone, Copy, Debug)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] @@ -79,6 +81,25 @@ pub struct Clocks { pub rtc: Option, } +#[cfg(feature = "low-power")] +static CLOCK_REFCOUNT: AtomicU32 = AtomicU32::new(0); + +#[cfg(feature = "low-power")] +pub fn low_power_ready() -> bool { + CLOCK_REFCOUNT.load(Ordering::SeqCst) == 0 +} + +#[cfg(feature = "low-power")] +pub(crate) fn clock_refcount_add() { + // We don't check for overflow because constructing more than u32 peripherals is unlikely + CLOCK_REFCOUNT.fetch_add(1, Ordering::Relaxed); +} + +#[cfg(feature = "low-power")] +pub(crate) fn clock_refcount_sub() { + assert!(CLOCK_REFCOUNT.fetch_sub(1, Ordering::Relaxed) != 0); +} + /// Frozen clock frequencies /// /// The existence of this value indicates that the clock configuration can no longer be changed From 00aadf6085d080546ebbed91e2b1e2d6ecbbedea Mon Sep 17 00:00:00 2001 From: xoviat Date: Wed, 23 Aug 2023 20:22:11 -0500 Subject: [PATCH 045/106] stm32/lp: pipe through lp ready --- embassy-stm32/src/low_power.rs | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/embassy-stm32/src/low_power.rs b/embassy-stm32/src/low_power.rs index f4bf7bbe..7814fa38 100644 --- a/embassy-stm32/src/low_power.rs +++ b/embassy-stm32/src/low_power.rs @@ -8,6 +8,7 @@ use embassy_time::Duration; use crate::interrupt; use crate::interrupt::typelevel::Interrupt; use crate::pac::EXTI; +use crate::rcc::low_power_ready; const THREAD_PENDER: usize = usize::MAX; const THRESHOLD: Duration = Duration::from_millis(500); @@ -73,22 +74,18 @@ impl Executor { cortex_m::asm::bkpt(); } - fn low_power_ready(&self) -> bool { - true - } - fn time_until_next_alarm(&self) -> Duration { Duration::from_secs(3) } - fn get_scb(&self) -> SCB { + fn get_scb() -> SCB { unsafe { cortex_m::Peripherals::steal() }.SCB } fn configure_pwr(&self) { - trace!("low power before wfe"); + trace!("configure_pwr"); - if !self.low_power_ready() { + if !low_power_ready() { return; } @@ -106,7 +103,7 @@ impl Executor { trace!("low power wait for rtc ready..."); - self.get_scb().set_sleepdeep(); + Self::get_scb().set_sleepdeep(); }); } From ecc305bbfe1007f9daa4d6a585dfc66f6ca69218 Mon Sep 17 00:00:00 2001 From: xoviat Date: Wed, 23 Aug 2023 20:28:41 -0500 Subject: [PATCH 046/106] stm32: fix executor version --- embassy-stm32/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index 048d231d..150014af 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml @@ -38,7 +38,7 @@ embassy-hal-internal = {version = "0.1.0", path = "../embassy-hal-internal", fea embassy-embedded-hal = {version = "0.1.0", path = "../embassy-embedded-hal" } embassy-net-driver = { version = "0.1.0", path = "../embassy-net-driver" } embassy-usb-driver = {version = "0.1.0", path = "../embassy-usb-driver", optional = true } -embassy-executor = { version = "0.2.0", path = "../embassy-executor", optional = true } +embassy-executor = { version = "0.3.0", path = "../embassy-executor", optional = true } embedded-hal-02 = { package = "embedded-hal", version = "0.2.6", features = ["unproven"] } embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-rc.1", optional = true} From cda404731093015f84bad96675fdbfc712bc0215 Mon Sep 17 00:00:00 2001 From: xoviat Date: Thu, 24 Aug 2023 19:29:11 -0500 Subject: [PATCH 047/106] stm32: flesh out lp executor --- embassy-stm32/src/lib.rs | 5 +++ embassy-stm32/src/low_power.rs | 45 +++++++++++++------ embassy-stm32/src/rcc/mod.rs | 2 + embassy-stm32/src/rtc/v2.rs | 25 ++++++++--- embassy-stm32/src/time_driver.rs | 76 ++++++++++++++++++++++++++++++++ 5 files changed, 133 insertions(+), 20 deletions(-) diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs index 8c87ea7d..ec8648ee 100644 --- a/embassy-stm32/src/lib.rs +++ b/embassy-stm32/src/lib.rs @@ -197,6 +197,11 @@ pub fn init(config: Config) -> Peripherals { // must be after rcc init #[cfg(feature = "_time-driver")] time_driver::init(); + + #[cfg(feature = "low-power")] + while !crate::rcc::low_power_ready() { + crate::rcc::clock_refcount_sub(); + } } p diff --git a/embassy-stm32/src/low_power.rs b/embassy-stm32/src/low_power.rs index 7814fa38..0d9506aa 100644 --- a/embassy-stm32/src/low_power.rs +++ b/embassy-stm32/src/low_power.rs @@ -9,6 +9,7 @@ use crate::interrupt; use crate::interrupt::typelevel::Interrupt; use crate::pac::EXTI; use crate::rcc::low_power_ready; +use crate::time_driver::{pause_time, resume_time, time_until_next_alarm}; const THREAD_PENDER: usize = usize::MAX; const THRESHOLD: Duration = Duration::from_millis(500); @@ -16,6 +17,9 @@ const THRESHOLD: Duration = Duration::from_millis(500); use crate::rtc::{Rtc, RtcInstant}; static mut RTC: Option<&'static Rtc> = None; +static mut STOP_TIME: embassy_time::Duration = Duration::from_ticks(0); +static mut NEXT_ALARM: embassy_time::Duration = Duration::from_ticks(u64::MAX); +static mut RTC_INSTANT: Option = None; foreach_interrupt! { (RTC, rtc, $block:ident, WKUP, $irq:ident) => { @@ -69,13 +73,25 @@ impl Executor { } unsafe fn on_wakeup_irq() { - info!("on wakeup irq"); + trace!("on wakeup irq"); - cortex_m::asm::bkpt(); - } + let elapsed = RTC_INSTANT.take().unwrap() - stop_wakeup_alarm(); - fn time_until_next_alarm(&self) -> Duration { - Duration::from_secs(3) + STOP_TIME += elapsed; + // let to_next = NEXT_ALARM - STOP_TIME; + let to_next = Duration::from_secs(3); + + trace!("on wakeup irq: to next: {}", to_next); + if to_next > THRESHOLD { + trace!("start wakeup alarm"); + RTC_INSTANT.replace(start_wakeup_alarm(to_next)); + + trace!("set sleeponexit"); + Self::get_scb().set_sleeponexit(); + } else { + Self::get_scb().clear_sleeponexit(); + Self::get_scb().clear_sleepdeep(); + } } fn get_scb() -> SCB { @@ -86,25 +102,28 @@ impl Executor { trace!("configure_pwr"); if !low_power_ready() { + trace!("configure_pwr: low power not ready"); return; } - let time_until_next_alarm = self.time_until_next_alarm(); + let time_until_next_alarm = time_until_next_alarm(); if time_until_next_alarm < THRESHOLD { + trace!("configure_pwr: not enough time until next alarm"); return; } - trace!("low power stop required"); + unsafe { + NEXT_ALARM = time_until_next_alarm; + RTC_INSTANT = Some(start_wakeup_alarm(time_until_next_alarm)) + }; - critical_section::with(|_| { - trace!("executor: set wakeup alarm..."); + // return; - start_wakeup_alarm(time_until_next_alarm); + pause_time(); - trace!("low power wait for rtc ready..."); + trace!("enter stop..."); - Self::get_scb().set_sleepdeep(); - }); + Self::get_scb().set_sleepdeep(); } /// Run the executor. diff --git a/embassy-stm32/src/rcc/mod.rs b/embassy-stm32/src/rcc/mod.rs index 3c75923e..45a4d880 100644 --- a/embassy-stm32/src/rcc/mod.rs +++ b/embassy-stm32/src/rcc/mod.rs @@ -86,6 +86,8 @@ static CLOCK_REFCOUNT: AtomicU32 = AtomicU32::new(0); #[cfg(feature = "low-power")] pub fn low_power_ready() -> bool { + trace!("clock refcount: {}", CLOCK_REFCOUNT.load(Ordering::SeqCst)); + CLOCK_REFCOUNT.load(Ordering::SeqCst) == 0 } diff --git a/embassy-stm32/src/rtc/v2.rs b/embassy-stm32/src/rtc/v2.rs index bcb127ec..197c3b8f 100644 --- a/embassy-stm32/src/rtc/v2.rs +++ b/embassy-stm32/src/rtc/v2.rs @@ -30,9 +30,6 @@ impl RtcInstant { let _ = RTC::regs().dr().read(); - trace!("ssr: {}", ssr); - trace!("st: {}", st); - Self { ssr, st } } } @@ -52,7 +49,12 @@ impl core::ops::Sub for RtcInstant { let other_ticks = rhs.st as u32 * 256 + (255 - rhs.ssr as u32); let rtc_ticks = self_ticks - other_ticks; - trace!("self, other, rtc ticks: {}, {}, {}", self_ticks, other_ticks, rtc_ticks); + trace!( + "rtc: instant sub: self, other, rtc ticks: {}, {}, {}", + self_ticks, + other_ticks, + rtc_ticks + ); Duration::from_ticks( ((((st as u32 * 256 + (255u32 - self.ssr as u32)) - (rhs.st as u32 * 256 + (255u32 - rhs.ssr as u32))) @@ -174,10 +176,10 @@ impl super::Rtc { rtc_ticks as u64 * TICK_HZ * (>::into(prescaler) as u64) / rtc_hz, ); - trace!("set wakeup timer for {} ms", duration.as_millis()); + trace!("rtc: set wakeup timer for {} ms", duration.as_millis()); self.write(false, |regs| { - regs.cr().modify(|w| w.set_wutie(true)); + // regs.cr().modify(|w| w.set_wutie(true)); regs.cr().modify(|w| w.set_wute(false)); regs.isr().modify(|w| w.set_wutf(false)); @@ -187,6 +189,15 @@ impl super::Rtc { regs.cr().modify(|w| w.set_wute(true)); }); + self.write(false, |regs| { + regs.cr().modify(|w| w.set_wutie(false)); + + regs.isr().modify(|w| w.set_wutf(false)); + crate::pac::PWR.cr1().modify(|w| w.set_cwuf(false)); + + regs.cr().modify(|w| w.set_wutie(true)); + }); + RtcInstant::now() } @@ -197,7 +208,7 @@ impl super::Rtc { /// note: this api is exposed for testing purposes until low power is implemented. /// it is not intended to be public pub(crate) fn stop_wakeup_alarm(&self) -> RtcInstant { - trace!("disable wakeup timer..."); + trace!("rtc: stop wakeup alarm..."); self.write(false, |regs| { regs.cr().modify(|w| w.set_wute(false)); diff --git a/embassy-stm32/src/time_driver.rs b/embassy-stm32/src/time_driver.rs index 2622442f..8e05346a 100644 --- a/embassy-stm32/src/time_driver.rs +++ b/embassy-stm32/src/time_driver.rs @@ -259,6 +259,64 @@ impl RtcDriver { let f: fn(*mut ()) = unsafe { mem::transmute(alarm.callback.get()) }; f(alarm.ctx.get()); } + + #[cfg(feature = "low-power")] + /// Compute the approximate amount of time until the next alarm + pub(crate) fn time_until_next_alarm(&self) -> embassy_time::Duration { + critical_section::with(|cs| { + let now = self.now() + 32; + + embassy_time::Duration::from_ticks( + self.alarms + .borrow(cs) + .iter() + .map(|alarm: &AlarmState| alarm.timestamp.get().saturating_sub(now)) + .min() + .unwrap_or(u64::MAX), + ) + }) + } + + #[cfg(feature = "low-power")] + /// Pause the timer + pub(crate) fn pause_time(&self) { + T::regs_gp16().cr1().modify(|w| w.set_cen(false)); + } + + #[cfg(feature = "low-power")] + /// Resume the timer with the given offset + pub(crate) fn resume_time(&self, offset: embassy_time::Duration) { + let offset = offset.as_ticks(); + let cnt = T::regs_gp16().cnt().read().cnt() as u32; + let period = self.period.load(Ordering::SeqCst); + + // Correct the race, if it exists + let period = if period & 1 == 1 && cnt < u16::MAX as u32 / 2 { + period + 1 + } else { + period + }; + + // Normalize to the full overflow + let period = (period / 2) * 2; + + // Add the offset + let period = period + 2 * (offset / u16::MAX as u64) as u32; + let cnt = cnt + (offset % u16::MAX as u64) as u32; + + let (cnt, period) = if cnt > u16::MAX as u32 { + (cnt - u16::MAX as u32, period + 2) + } else { + (cnt, period) + }; + + let period = if cnt > u16::MAX as u32 / 2 { period + 1 } else { period }; + + self.period.store(period, Ordering::SeqCst); + T::regs_gp16().cnt().write(|w| w.set_cnt(cnt as u16)); + + T::regs_gp16().cr1().modify(|w| w.set_cen(true)); + } } impl Driver for RtcDriver { @@ -329,6 +387,24 @@ impl Driver for RtcDriver { } } +#[cfg(feature = "low-power")] +/// Compute the approximate amount of time until the next alarm +pub(crate) fn time_until_next_alarm() -> embassy_time::Duration { + DRIVER.time_until_next_alarm() +} + +#[cfg(feature = "low-power")] +/// Pause the timer +pub(crate) fn pause_time() { + DRIVER.pause_time(); +} + +#[cfg(feature = "low-power")] +/// Resume the timer with the given offset +pub(crate) fn resume_time(offset: embassy_time::Duration) { + DRIVER.resume_time(offset); +} + pub(crate) fn init() { DRIVER.init() } From cc8961034e53d4fc2ac4539096c2a67059eb60b7 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Fri, 25 Aug 2023 19:48:45 +0200 Subject: [PATCH 048/106] net: allow changing IP config at runtime. --- embassy-net/src/lib.rs | 346 +++++++++++++++++------------------- examples/stm32wb/Cargo.toml | 2 +- 2 files changed, 162 insertions(+), 186 deletions(-) diff --git a/embassy-net/src/lib.rs b/embassy-net/src/lib.rs index 2fb34f43..9f881289 100644 --- a/embassy-net/src/lib.rs +++ b/embassy-net/src/lib.rs @@ -3,6 +3,9 @@ #![warn(missing_docs)] #![doc = include_str!("../README.md")] +#[cfg(not(any(feature = "proto-ipv4", feature = "proto-ipv6")))] +compile_error!("You must enable at least one of the following features: proto-ipv4, proto-ipv6"); + // This mod MUST go first, so that the others see its macros. pub(crate) mod fmt; @@ -20,7 +23,7 @@ use core::future::{poll_fn, Future}; use core::task::{Context, Poll}; pub use embassy_net_driver as driver; -use embassy_net_driver::{Driver, LinkState, Medium}; +use embassy_net_driver::{Driver, LinkState}; use embassy_sync::waitqueue::WakerRegistration; use embassy_time::{Instant, Timer}; use futures::pin_mut; @@ -133,6 +136,8 @@ impl Default for DhcpConfig { } /// Network stack configuration. +#[derive(Debug, Clone, Default)] +#[non_exhaustive] pub struct Config { /// IPv4 configuration #[cfg(feature = "proto-ipv4")] @@ -181,23 +186,27 @@ impl Config { /// Network stack IPv4 configuration. #[cfg(feature = "proto-ipv4")] +#[derive(Debug, Clone, Default)] pub enum ConfigV4 { + /// Do not configure IPv4. + #[default] + None, /// Use a static IPv4 address configuration. Static(StaticConfigV4), /// Use DHCP to obtain an IP address configuration. #[cfg(feature = "dhcpv4")] Dhcp(DhcpConfig), - /// Do not configure IPv6. - None, } /// Network stack IPv6 configuration. #[cfg(feature = "proto-ipv6")] +#[derive(Debug, Clone, Default)] pub enum ConfigV6 { + /// Do not configure IPv6. + #[default] + None, /// Use a static IPv6 address configuration. Static(StaticConfigV6), - /// Do not configure IPv6. - None, } /// A network stack. @@ -276,7 +285,6 @@ impl Stack { next_local_port, }; - #[cfg_attr(feature = "medium-ieee802154", allow(unused_mut))] let mut inner = Inner { device, link_up: false, @@ -295,30 +303,11 @@ impl Stack { dns_waker: WakerRegistration::new(), }; - #[cfg(feature = "medium-ieee802154")] - let _ = config; - #[cfg(feature = "proto-ipv4")] - match config.ipv4 { - ConfigV4::Static(config) => { - inner.apply_config_v4(&mut socket, config); - } - #[cfg(feature = "dhcpv4")] - ConfigV4::Dhcp(config) => { - let mut dhcp_socket = smoltcp::socket::dhcpv4::Socket::new(); - inner.apply_dhcp_config(&mut dhcp_socket, config); - let handle = socket.sockets.add(dhcp_socket); - inner.dhcp_socket = Some(handle); - } - ConfigV4::None => {} - } + inner.set_config_v4(&mut socket, config.ipv4); #[cfg(feature = "proto-ipv6")] - match config.ipv6 { - ConfigV6::Static(config) => { - inner.apply_config_v6(&mut socket, config); - } - ConfigV6::None => {} - } + inner.set_config_v6(&mut socket, config.ipv6); + inner.apply_static_config(&mut socket); Self { socket: RefCell::new(socket), @@ -372,15 +361,36 @@ impl Stack { } /// Get the current IPv4 configuration. + /// + /// If using DHCP, this will be None if DHCP hasn't been able to + /// acquire an IP address, or Some if it has. #[cfg(feature = "proto-ipv4")] pub fn config_v4(&self) -> Option { - self.with(|_s, i| i.static_v4.clone()) + self.with(|_, i| i.static_v4.clone()) } /// Get the current IPv6 configuration. #[cfg(feature = "proto-ipv6")] pub fn config_v6(&self) -> Option { - self.with(|_s, i| i.static_v6.clone()) + self.with(|_, i| i.static_v6.clone()) + } + + /// Set the IPv4 configuration. + #[cfg(feature = "proto-ipv4")] + pub fn set_config_v4(&self, config: ConfigV4) { + self.with_mut(|s, i| { + i.set_config_v4(s, config); + i.apply_static_config(s); + }) + } + + /// Set the IPv6 configuration. + #[cfg(feature = "proto-ipv6")] + pub fn set_config_v6(&self, config: ConfigV6) { + self.with_mut(|s, i| { + i.set_config_v6(s, config); + i.apply_static_config(s); + }) } /// Run the network stack. @@ -582,166 +592,125 @@ impl SocketStack { impl Inner { #[cfg(feature = "proto-ipv4")] - fn apply_config_v4(&mut self, s: &mut SocketStack, config: StaticConfigV4) { - debug!("Acquired IP configuration:"); - - debug!(" IP address: {}", config.address); - s.iface.update_ip_addrs(|addrs| { - if let Some((index, _)) = addrs - .iter() - .enumerate() - .find(|(_, &addr)| matches!(addr, IpCidr::Ipv4(_))) - { - addrs.remove(index); - } - addrs.push(IpCidr::Ipv4(config.address)).unwrap(); - }); - - #[cfg(feature = "medium-ip")] - let skip_gateway = self.device.capabilities().medium != Medium::Ip; - #[cfg(not(feature = "medium-ip"))] - let skip_gateway = false; - - if !skip_gateway { - if let Some(gateway) = config.gateway { - debug!(" Default gateway: {}", gateway); - s.iface.routes_mut().add_default_ipv4_route(gateway).unwrap(); - } else { - debug!(" Default gateway: None"); - s.iface.routes_mut().remove_default_ipv4_route(); - } - } - for (i, s) in config.dns_servers.iter().enumerate() { - debug!(" DNS server {}: {}", i, s); - } - - self.static_v4 = Some(config); - - #[cfg(feature = "dns")] - { - self.update_dns_servers(s) - } - } - - /// Replaces the current IPv6 static configuration with a newly supplied config. - #[cfg(feature = "proto-ipv6")] - fn apply_config_v6(&mut self, s: &mut SocketStack, config: StaticConfigV6) { - #[cfg(feature = "medium-ethernet")] - let medium = self.device.capabilities().medium; - - debug!("Acquired IPv6 configuration:"); - - debug!(" IP address: {}", config.address); - s.iface.update_ip_addrs(|addrs| { - if let Some((index, _)) = addrs - .iter() - .enumerate() - .find(|(_, &addr)| matches!(addr, IpCidr::Ipv6(_))) - { - addrs.remove(index); - } - addrs.push(IpCidr::Ipv6(config.address)).unwrap(); - }); - - #[cfg(feature = "medium-ethernet")] - if Medium::Ethernet == medium { - if let Some(gateway) = config.gateway { - debug!(" Default gateway: {}", gateway); - s.iface.routes_mut().add_default_ipv6_route(gateway).unwrap(); - } else { - debug!(" Default gateway: None"); - s.iface.routes_mut().remove_default_ipv6_route(); - } - } - for (i, s) in config.dns_servers.iter().enumerate() { - debug!(" DNS server {}: {}", i, s); - } - - self.static_v6 = Some(config); - - #[cfg(feature = "dns")] - { - self.update_dns_servers(s) - } - } - - #[cfg(feature = "dns")] - fn update_dns_servers(&mut self, s: &mut SocketStack) { - let socket = s.sockets.get_mut::(self.dns_socket); - - let servers_v4; - #[cfg(feature = "proto-ipv4")] - { - servers_v4 = self - .static_v4 - .iter() - .flat_map(|cfg| cfg.dns_servers.iter().map(|c| IpAddress::Ipv4(*c))); + pub fn set_config_v4(&mut self, _s: &mut SocketStack, config: ConfigV4) { + // Handle static config. + self.static_v4 = match config.clone() { + ConfigV4::None => None, + #[cfg(feature = "dhcpv4")] + ConfigV4::Dhcp(_) => None, + ConfigV4::Static(c) => Some(c), }; - #[cfg(not(feature = "proto-ipv4"))] - { - servers_v4 = core::iter::empty(); - } - let servers_v6; - #[cfg(feature = "proto-ipv6")] - { - servers_v6 = self - .static_v6 - .iter() - .flat_map(|cfg| cfg.dns_servers.iter().map(|c| IpAddress::Ipv6(*c))); - } - #[cfg(not(feature = "proto-ipv6"))] - { - servers_v6 = core::iter::empty(); - } + // Handle DHCP config. + #[cfg(feature = "dhcpv4")] + match config { + ConfigV4::Dhcp(c) => { + // Create the socket if it doesn't exist. + if self.dhcp_socket.is_none() { + let socket = smoltcp::socket::dhcpv4::Socket::new(); + let handle = _s.sockets.add(socket); + self.dhcp_socket = Some(handle); + } - // Prefer the v6 DNS servers over the v4 servers - let servers: Vec = servers_v6.chain(servers_v4).collect(); - socket.update_servers(&servers[..]); - } - - #[cfg(feature = "dhcpv4")] - fn apply_dhcp_config(&self, socket: &mut smoltcp::socket::dhcpv4::Socket, config: DhcpConfig) { - socket.set_ignore_naks(config.ignore_naks); - socket.set_max_lease_duration(config.max_lease_duration.map(crate::time::duration_to_smoltcp)); - socket.set_ports(config.server_port, config.client_port); - socket.set_retry_config(config.retry_config); - } - - #[cfg(feature = "dhcpv4")] - fn unapply_config_v4(&mut self, s: &mut SocketStack) { - #[cfg(feature = "medium-ethernet")] - let medium = self.device.capabilities().medium; - debug!("Lost IP configuration"); - s.iface.update_ip_addrs(|ip_addrs| { - #[cfg(feature = "proto-ipv4")] - if let Some((index, _)) = ip_addrs - .iter() - .enumerate() - .find(|(_, &addr)| matches!(addr, IpCidr::Ipv4(_))) - { - ip_addrs.remove(index); + // Configure it + let socket = _s.sockets.get_mut::(self.dhcp_socket.unwrap()); + socket.set_ignore_naks(c.ignore_naks); + socket.set_max_lease_duration(c.max_lease_duration.map(crate::time::duration_to_smoltcp)); + socket.set_ports(c.server_port, c.client_port); + socket.set_retry_config(c.retry_config); + socket.reset(); } - }); - #[cfg(feature = "medium-ethernet")] - if medium == Medium::Ethernet { - #[cfg(feature = "proto-ipv4")] - { - s.iface.routes_mut().remove_default_ipv4_route(); + _ => { + // Remove DHCP socket if any. + if let Some(socket) = self.dhcp_socket { + _s.sockets.remove(socket); + self.dhcp_socket = None; + } } } + } + + #[cfg(feature = "proto-ipv6")] + pub fn set_config_v6(&mut self, _s: &mut SocketStack, config: ConfigV6) { + self.static_v6 = match config { + ConfigV6::None => None, + ConfigV6::Static(c) => Some(c), + }; + } + + fn apply_static_config(&mut self, s: &mut SocketStack) { + let mut addrs = Vec::new(); + #[cfg(feature = "dns")] + let mut dns_servers: Vec<_, 6> = Vec::new(); #[cfg(feature = "proto-ipv4")] - { - self.static_v4 = None + let mut gateway_v4 = None; + #[cfg(feature = "proto-ipv6")] + let mut gateway_v6 = None; + + #[cfg(feature = "proto-ipv4")] + if let Some(config) = &self.static_v4 { + debug!("IPv4: UP"); + debug!(" IP address: {:?}", config.address); + debug!(" Default gateway: {:?}", config.gateway); + + addrs.push(IpCidr::Ipv4(config.address)).unwrap(); + gateway_v4 = config.gateway.into(); + #[cfg(feature = "dns")] + for s in &config.dns_servers { + debug!(" DNS server: {:?}", s); + dns_servers.push(s.clone().into()).unwrap(); + } + } else { + info!("IPv4: DOWN"); } + + #[cfg(feature = "proto-ipv6")] + if let Some(config) = &self.static_v6 { + debug!("IPv6: UP"); + debug!(" IP address: {:?}", config.address); + debug!(" Default gateway: {:?}", config.gateway); + + addrs.push(IpCidr::Ipv6(config.address)).unwrap(); + gateway_v6 = config.gateway.into(); + #[cfg(feature = "dns")] + for s in &config.dns_servers { + debug!(" DNS server: {:?}", s); + dns_servers.push(s.clone().into()).unwrap(); + } + } else { + info!("IPv6: DOWN"); + } + + // Apply addresses + s.iface.update_ip_addrs(|a| *a = addrs); + + // Apply gateways + #[cfg(feature = "proto-ipv4")] + if let Some(gateway) = gateway_v4 { + s.iface.routes_mut().add_default_ipv4_route(gateway).unwrap(); + } else { + s.iface.routes_mut().remove_default_ipv4_route(); + } + #[cfg(feature = "proto-ipv6")] + if let Some(gateway) = gateway_v6 { + s.iface.routes_mut().add_default_ipv6_route(gateway).unwrap(); + } else { + s.iface.routes_mut().remove_default_ipv6_route(); + } + + // Apply DNS servers + #[cfg(feature = "dns")] + s.sockets + .get_mut::(self.dns_socket) + .update_servers(&dns_servers[..]); } fn poll(&mut self, cx: &mut Context<'_>, s: &mut SocketStack) { s.waker.register(cx.waker()); #[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))] - if self.device.capabilities().medium == Medium::Ethernet - || self.device.capabilities().medium == Medium::Ieee802154 + if self.device.capabilities().medium == embassy_net_driver::Medium::Ethernet + || self.device.capabilities().medium == embassy_net_driver::Medium::Ieee802154 { s.iface .set_hardware_addr(to_smoltcp_hardware_address(self.device.hardware_address())); @@ -763,6 +732,9 @@ impl Inner { info!("link_up = {:?}", self.link_up); } + #[allow(unused_mut)] + let mut apply_config = false; + #[cfg(feature = "dhcpv4")] if let Some(dhcp_handle) = self.dhcp_socket { let socket = s.sockets.get_mut::(dhcp_handle); @@ -770,25 +742,29 @@ impl Inner { if self.link_up { match socket.poll() { None => {} - Some(dhcpv4::Event::Deconfigured) => self.unapply_config_v4(s), + Some(dhcpv4::Event::Deconfigured) => { + self.static_v4 = None; + apply_config = true; + } Some(dhcpv4::Event::Configured(config)) => { - let config = StaticConfigV4 { + self.static_v4 = Some(StaticConfigV4 { address: config.address, gateway: config.router, dns_servers: config.dns_servers, - }; - self.apply_config_v4(s, config) + }); + apply_config = true; } } } else if old_link_up { socket.reset(); - self.unapply_config_v4(s); + self.static_v4 = None; + apply_config = true; } } - //if old_link_up || self.link_up { - // self.poll_configurator(timestamp) - //} - // + + if apply_config { + self.apply_static_config(s); + } if let Some(poll_at) = s.iface.poll_at(timestamp, &mut s.sockets) { let t = Timer::at(instant_from_smoltcp(poll_at)); diff --git a/examples/stm32wb/Cargo.toml b/examples/stm32wb/Cargo.toml index f58a5189..16db92c1 100644 --- a/examples/stm32wb/Cargo.toml +++ b/examples/stm32wb/Cargo.toml @@ -11,7 +11,7 @@ embassy-stm32-wpan = { version = "0.1.0", path = "../../embassy-stm32-wpan", fea embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.3.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-net = { version = "0.1.0", path = "../../embassy-net", features = ["defmt", "udp", "medium-ieee802154", "nightly"], optional=true } +embassy-net = { version = "0.1.0", path = "../../embassy-net", features = ["defmt", "udp", "proto-ipv6", "medium-ieee802154", "nightly"], optional=true } defmt = "0.3" defmt-rtt = "0.4" From b5748524f86f809d9c8dc2c5b4bb3f07e55dbda1 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Fri, 25 Aug 2023 01:03:24 +0200 Subject: [PATCH 049/106] net: improve error message on unsupported medium. --- embassy-net/Cargo.toml | 1 + embassy-net/src/lib.rs | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/embassy-net/Cargo.toml b/embassy-net/Cargo.toml index 0c551f20..0361f1db 100644 --- a/embassy-net/Cargo.toml +++ b/embassy-net/Cargo.toml @@ -9,6 +9,7 @@ categories = [ "embedded", "no-std", "asynchronous", + "network-programming", ] [package.metadata.embassy_docs] diff --git a/embassy-net/src/lib.rs b/embassy-net/src/lib.rs index 9f881289..3a385fad 100644 --- a/embassy-net/src/lib.rs +++ b/embassy-net/src/lib.rs @@ -249,7 +249,10 @@ fn to_smoltcp_hardware_address(addr: driver::HardwareAddress) -> HardwareAddress driver::HardwareAddress::Ip => HardwareAddress::Ip, #[allow(unreachable_patterns)] - _ => panic!("Unsupported address {:?}. Make sure to enable medium-ethernet or medium-ieee802154 in embassy-net's Cargo features.", addr), + _ => panic!( + "Unsupported medium {:?}. Make sure to enable the right medium feature in embassy-net's Cargo features.", + addr + ), } } From 100200d021bbf650f7dd569414ee52b2d5ac10f0 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Fri, 25 Aug 2023 01:03:39 +0200 Subject: [PATCH 050/106] net-driver-channel: do not hardcode medium to ethernet. --- embassy-net-driver-channel/src/lib.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/embassy-net-driver-channel/src/lib.rs b/embassy-net-driver-channel/src/lib.rs index 076238ba..f23c0441 100644 --- a/embassy-net-driver-channel/src/lib.rs +++ b/embassy-net-driver-channel/src/lib.rs @@ -8,6 +8,7 @@ use core::cell::RefCell; use core::mem::MaybeUninit; use core::task::{Context, Poll}; +use driver::HardwareAddress; pub use embassy_net_driver as driver; use embassy_net_driver::{Capabilities, LinkState, Medium}; use embassy_sync::blocking_mutex::raw::NoopRawMutex; @@ -218,7 +219,11 @@ pub fn new<'d, const MTU: usize, const N_RX: usize, const N_TX: usize>( ) -> (Runner<'d, MTU>, Device<'d, MTU>) { let mut caps = Capabilities::default(); caps.max_transmission_unit = MTU; - caps.medium = Medium::Ethernet; + caps.medium = match &hardware_address { + HardwareAddress::Ethernet(_) => Medium::Ethernet, + HardwareAddress::Ieee802154(_) => Medium::Ieee802154, + HardwareAddress::Ip => Medium::Ip, + }; // safety: this is a self-referential struct, however: // - it can't move while the `'d` borrow is active. From aacf14b62a28277599871edf74106b1cd2e01795 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Fri, 25 Aug 2023 01:04:51 +0200 Subject: [PATCH 051/106] net-ppp: Add it. --- embassy-net-ppp/Cargo.toml | 28 ++++ embassy-net-ppp/README.md | 19 +++ embassy-net-ppp/src/fmt.rs | 257 +++++++++++++++++++++++++++++++++++++ embassy-net-ppp/src/lib.rs | 165 ++++++++++++++++++++++++ 4 files changed, 469 insertions(+) create mode 100644 embassy-net-ppp/Cargo.toml create mode 100644 embassy-net-ppp/README.md create mode 100644 embassy-net-ppp/src/fmt.rs create mode 100644 embassy-net-ppp/src/lib.rs diff --git a/embassy-net-ppp/Cargo.toml b/embassy-net-ppp/Cargo.toml new file mode 100644 index 00000000..b2874c68 --- /dev/null +++ b/embassy-net-ppp/Cargo.toml @@ -0,0 +1,28 @@ +[package] +name = "embassy-net-ppp" +version = "0.1.0" +description = "embassy-net driver for PPP over Serial" +keywords = ["embedded", "ppp", "embassy-net", "embedded-hal-async", "ethernet", "async"] +categories = ["embedded", "hardware-support", "no-std", "network-programming", "async"] +license = "MIT OR Apache-2.0" +edition = "2021" + +[features] +defmt = ["dep:defmt", "ppproto/defmt"] +log = ["dep:log", "ppproto/log"] + +[dependencies] +defmt = { version = "0.3", optional = true } +log = { version = "0.4.14", optional = true } + +embedded-io-async = { version = "0.5.0" } +embassy-net-driver-channel = { version = "0.1.0", path = "../embassy-net-driver-channel" } +embassy-futures = { version = "0.1.0", path = "../embassy-futures" } +ppproto = { version = "0.1.1"} +embassy-sync = { version = "0.2.0", path = "../embassy-sync" } + +[package.metadata.embassy_docs] +src_base = "https://github.com/embassy-rs/embassy/blob/embassy-net-ppp-v$VERSION/embassy-net-ppp/src/" +src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-net-ppp/src/" +target = "thumbv7em-none-eabi" +features = ["defmt"] diff --git a/embassy-net-ppp/README.md b/embassy-net-ppp/README.md new file mode 100644 index 00000000..58d67395 --- /dev/null +++ b/embassy-net-ppp/README.md @@ -0,0 +1,19 @@ +# `embassy-net-ppp` + +[`embassy-net`](https://crates.io/crates/embassy-net) integration for PPP over Serial. + +## Interoperability + +This crate can run on any executor. + +It supports any serial port implementing [`embedded-io-async`](https://crates.io/crates/embedded-io-async). + +## License + +This work is licensed under either of + +- Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or + http://www.apache.org/licenses/LICENSE-2.0) +- MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) + +at your option. diff --git a/embassy-net-ppp/src/fmt.rs b/embassy-net-ppp/src/fmt.rs new file mode 100644 index 00000000..91984bde --- /dev/null +++ b/embassy-net-ppp/src/fmt.rs @@ -0,0 +1,257 @@ +#![macro_use] +#![allow(unused_macros)] + +use core::fmt::{Debug, Display, LowerHex}; + +#[cfg(all(feature = "defmt", feature = "log"))] +compile_error!("You may not enable both `defmt` and `log` features."); + +macro_rules! assert { + ($($x:tt)*) => { + { + #[cfg(not(feature = "defmt"))] + ::core::assert!($($x)*); + #[cfg(feature = "defmt")] + ::defmt::assert!($($x)*); + } + }; +} + +macro_rules! assert_eq { + ($($x:tt)*) => { + { + #[cfg(not(feature = "defmt"))] + ::core::assert_eq!($($x)*); + #[cfg(feature = "defmt")] + ::defmt::assert_eq!($($x)*); + } + }; +} + +macro_rules! assert_ne { + ($($x:tt)*) => { + { + #[cfg(not(feature = "defmt"))] + ::core::assert_ne!($($x)*); + #[cfg(feature = "defmt")] + ::defmt::assert_ne!($($x)*); + } + }; +} + +macro_rules! debug_assert { + ($($x:tt)*) => { + { + #[cfg(not(feature = "defmt"))] + ::core::debug_assert!($($x)*); + #[cfg(feature = "defmt")] + ::defmt::debug_assert!($($x)*); + } + }; +} + +macro_rules! debug_assert_eq { + ($($x:tt)*) => { + { + #[cfg(not(feature = "defmt"))] + ::core::debug_assert_eq!($($x)*); + #[cfg(feature = "defmt")] + ::defmt::debug_assert_eq!($($x)*); + } + }; +} + +macro_rules! debug_assert_ne { + ($($x:tt)*) => { + { + #[cfg(not(feature = "defmt"))] + ::core::debug_assert_ne!($($x)*); + #[cfg(feature = "defmt")] + ::defmt::debug_assert_ne!($($x)*); + } + }; +} + +macro_rules! todo { + ($($x:tt)*) => { + { + #[cfg(not(feature = "defmt"))] + ::core::todo!($($x)*); + #[cfg(feature = "defmt")] + ::defmt::todo!($($x)*); + } + }; +} + +#[cfg(not(feature = "defmt"))] +macro_rules! unreachable { + ($($x:tt)*) => { + ::core::unreachable!($($x)*) + }; +} + +#[cfg(feature = "defmt")] +macro_rules! unreachable { + ($($x:tt)*) => { + ::defmt::unreachable!($($x)*); + }; +} + +macro_rules! panic { + ($($x:tt)*) => { + { + #[cfg(not(feature = "defmt"))] + ::core::panic!($($x)*); + #[cfg(feature = "defmt")] + ::defmt::panic!($($x)*); + } + }; +} + +macro_rules! trace { + ($s:literal $(, $x:expr)* $(,)?) => { + { + #[cfg(feature = "log")] + ::log::trace!($s $(, $x)*); + #[cfg(feature = "defmt")] + ::defmt::trace!($s $(, $x)*); + #[cfg(not(any(feature = "log", feature="defmt")))] + let _ = ($( & $x ),*); + } + }; +} + +macro_rules! debug { + ($s:literal $(, $x:expr)* $(,)?) => { + { + #[cfg(feature = "log")] + ::log::debug!($s $(, $x)*); + #[cfg(feature = "defmt")] + ::defmt::debug!($s $(, $x)*); + #[cfg(not(any(feature = "log", feature="defmt")))] + let _ = ($( & $x ),*); + } + }; +} + +macro_rules! info { + ($s:literal $(, $x:expr)* $(,)?) => { + { + #[cfg(feature = "log")] + ::log::info!($s $(, $x)*); + #[cfg(feature = "defmt")] + ::defmt::info!($s $(, $x)*); + #[cfg(not(any(feature = "log", feature="defmt")))] + let _ = ($( & $x ),*); + } + }; +} + +macro_rules! warn { + ($s:literal $(, $x:expr)* $(,)?) => { + { + #[cfg(feature = "log")] + ::log::warn!($s $(, $x)*); + #[cfg(feature = "defmt")] + ::defmt::warn!($s $(, $x)*); + #[cfg(not(any(feature = "log", feature="defmt")))] + let _ = ($( & $x ),*); + } + }; +} + +macro_rules! error { + ($s:literal $(, $x:expr)* $(,)?) => { + { + #[cfg(feature = "log")] + ::log::error!($s $(, $x)*); + #[cfg(feature = "defmt")] + ::defmt::error!($s $(, $x)*); + #[cfg(not(any(feature = "log", feature="defmt")))] + let _ = ($( & $x ),*); + } + }; +} + +#[cfg(feature = "defmt")] +macro_rules! unwrap { + ($($x:tt)*) => { + ::defmt::unwrap!($($x)*) + }; +} + +#[cfg(not(feature = "defmt"))] +macro_rules! unwrap { + ($arg:expr) => { + match $crate::fmt::Try::into_result($arg) { + ::core::result::Result::Ok(t) => t, + ::core::result::Result::Err(e) => { + ::core::panic!("unwrap of `{}` failed: {:?}", ::core::stringify!($arg), e); + } + } + }; + ($arg:expr, $($msg:expr),+ $(,)? ) => { + match $crate::fmt::Try::into_result($arg) { + ::core::result::Result::Ok(t) => t, + ::core::result::Result::Err(e) => { + ::core::panic!("unwrap of `{}` failed: {}: {:?}", ::core::stringify!($arg), ::core::format_args!($($msg,)*), e); + } + } + } +} + +#[derive(Debug, Copy, Clone, Eq, PartialEq)] +pub struct NoneError; + +pub trait Try { + type Ok; + type Error; + fn into_result(self) -> Result; +} + +impl Try for Option { + type Ok = T; + type Error = NoneError; + + #[inline] + fn into_result(self) -> Result { + self.ok_or(NoneError) + } +} + +impl Try for Result { + type Ok = T; + type Error = E; + + #[inline] + fn into_result(self) -> Self { + self + } +} + +pub struct Bytes<'a>(pub &'a [u8]); + +impl<'a> Debug for Bytes<'a> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{:#02x?}", self.0) + } +} + +impl<'a> Display for Bytes<'a> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{:#02x?}", self.0) + } +} + +impl<'a> LowerHex for Bytes<'a> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{:#02x?}", self.0) + } +} + +#[cfg(feature = "defmt")] +impl<'a> defmt::Format for Bytes<'a> { + fn format(&self, fmt: defmt::Formatter) { + defmt::write!(fmt, "{:02x}", self.0) + } +} diff --git a/embassy-net-ppp/src/lib.rs b/embassy-net-ppp/src/lib.rs new file mode 100644 index 00000000..7853e04a --- /dev/null +++ b/embassy-net-ppp/src/lib.rs @@ -0,0 +1,165 @@ +#![no_std] +#![warn(missing_docs)] +#![doc = include_str!("../README.md")] + +// must be first +mod fmt; + +use core::convert::Infallible; +use core::mem::MaybeUninit; + +use embassy_futures::select::{select3, Either3}; +use embassy_net_driver_channel as ch; +use embassy_net_driver_channel::driver::LinkState; +use embassy_sync::blocking_mutex::raw::NoopRawMutex; +use embassy_sync::signal::Signal; +use embedded_io_async::{BufRead, Write, WriteAllError}; +use ppproto::pppos::{BufferFullError, PPPoS, PPPoSAction}; + +const MTU: usize = 1500; + +/// Type alias for the embassy-net driver. +pub type Device<'d> = embassy_net_driver_channel::Device<'d, MTU>; + +/// Internal state for the embassy-net integration. +pub struct State { + ch_state: ch::State, +} + +impl State { + /// Create a new `State`. + pub const fn new() -> Self { + Self { + ch_state: ch::State::new(), + } + } +} + +/// Background runner for the driver. +/// +/// You must call `.run()` in a background task for the driver to operate. +pub struct Runner<'d, R: BufRead, W: Write> { + ch: ch::Runner<'d, MTU>, + r: R, + w: W, +} + +/// Error returned by [`Runner::run`]. +#[derive(Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub enum RunError { + /// Reading from the serial port failed. + Read(RE), + /// Writing to the serial port failed. + Write(WE), + /// Writing to the serial port wrote zero bytes, indicating it can't accept more data. + WriteZero, + /// Writing to the serial got EOF. + Eof, +} + +impl<'d, R: BufRead, W: Write> Runner<'d, R, W> { + /// You must call this in a background task for the driver to operate. + pub async fn run(mut self) -> Result> { + let config = ppproto::Config { + username: b"myuser", + password: b"mypass", + }; + let mut ppp = PPPoS::new(config); + ppp.open().unwrap(); + + let (state_chan, mut rx_chan, mut tx_chan) = self.ch.split(); + state_chan.set_link_state(LinkState::Down); + let _ondrop = OnDrop::new(|| state_chan.set_link_state(LinkState::Down)); + + let mut rx_buf = [0; 2048]; + let mut tx_buf = [0; 2048]; + + let poll_signal: Signal = Signal::new(); + poll_signal.signal(()); + + loop { + let mut poll = false; + match select3(self.r.fill_buf(), tx_chan.tx_buf(), poll_signal.wait()).await { + Either3::First(r) => { + let data = r.map_err(RunError::Read)?; + if data.is_empty() { + return Err(RunError::Eof); + } + let n = ppp.consume(data, &mut rx_buf); + self.r.consume(n); + poll = true; + } + Either3::Second(pkt) => { + match ppp.send(pkt, &mut tx_buf) { + Ok(n) => match self.w.write_all(&tx_buf[..n]).await { + Ok(()) => {} + Err(WriteAllError::WriteZero) => return Err(RunError::WriteZero), + Err(WriteAllError::Other(e)) => return Err(RunError::Write(e)), + }, + Err(BufferFullError) => unreachable!(), + } + tx_chan.tx_done(); + } + Either3::Third(_) => poll = true, + } + + if poll { + match ppp.poll(&mut tx_buf, &mut rx_buf) { + PPPoSAction::None => {} + PPPoSAction::Received(rg) => { + let pkt = &rx_buf[rg]; + let buf = rx_chan.rx_buf().await; // TODO: fix possible deadlock + buf[..pkt.len()].copy_from_slice(pkt); + rx_chan.rx_done(pkt.len()); + + poll_signal.signal(()); + } + PPPoSAction::Transmit(n) => { + match self.w.write_all(&tx_buf[..n]).await { + Ok(()) => {} + Err(WriteAllError::WriteZero) => return Err(RunError::WriteZero), + Err(WriteAllError::Other(e)) => return Err(RunError::Write(e)), + } + poll_signal.signal(()); + } + } + + match ppp.status().phase { + ppproto::Phase::Open => state_chan.set_link_state(LinkState::Up), + _ => state_chan.set_link_state(LinkState::Down), + } + } + } + } +} + +/// Create a PPP embassy-net driver instance. +/// +/// This returns two structs: +/// - a `Device` that you must pass to the `embassy-net` stack. +/// - a `Runner`. You must call `.run()` on it in a background task. +pub fn new<'a, const N_RX: usize, const N_TX: usize, R: BufRead, W: Write>( + state: &'a mut State, + r: R, + w: W, +) -> (Device<'a>, Runner<'a, R, W>) { + let (runner, device) = ch::new(&mut state.ch_state, ch::driver::HardwareAddress::Ip); + (device, Runner { ch: runner, r, w }) +} + +struct OnDrop { + f: MaybeUninit, +} + +impl OnDrop { + fn new(f: F) -> Self { + Self { f: MaybeUninit::new(f) } + } +} + +impl Drop for OnDrop { + fn drop(&mut self) { + unsafe { self.f.as_ptr().read()() } + } +} From 2303382dfd6f4e6275a699b938f465a1e6170449 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Fri, 25 Aug 2023 15:39:25 +0200 Subject: [PATCH 052/106] net-ppp: nicer processing loop structure that can't deadlock. --- embassy-net-ppp/src/lib.rs | 84 +++++++++++++++++++------------------- 1 file changed, 41 insertions(+), 43 deletions(-) diff --git a/embassy-net-ppp/src/lib.rs b/embassy-net-ppp/src/lib.rs index 7853e04a..af216c96 100644 --- a/embassy-net-ppp/src/lib.rs +++ b/embassy-net-ppp/src/lib.rs @@ -8,11 +8,9 @@ mod fmt; use core::convert::Infallible; use core::mem::MaybeUninit; -use embassy_futures::select::{select3, Either3}; +use embassy_futures::select::{select, Either}; use embassy_net_driver_channel as ch; use embassy_net_driver_channel::driver::LinkState; -use embassy_sync::blocking_mutex::raw::NoopRawMutex; -use embassy_sync::signal::Signal; use embedded_io_async::{BufRead, Write, WriteAllError}; use ppproto::pppos::{BufferFullError, PPPoS, PPPoSAction}; @@ -75,22 +73,50 @@ impl<'d, R: BufRead, W: Write> Runner<'d, R, W> { let mut rx_buf = [0; 2048]; let mut tx_buf = [0; 2048]; - let poll_signal: Signal = Signal::new(); - poll_signal.signal(()); + let mut needs_poll = true; loop { - let mut poll = false; - match select3(self.r.fill_buf(), tx_chan.tx_buf(), poll_signal.wait()).await { - Either3::First(r) => { - let data = r.map_err(RunError::Read)?; - if data.is_empty() { - return Err(RunError::Eof); - } - let n = ppp.consume(data, &mut rx_buf); + let rx_fut = async { + let buf = rx_chan.rx_buf().await; + let rx_data = match needs_poll { + true => &[][..], + false => match self.r.fill_buf().await { + Ok(rx_data) if rx_data.len() == 0 => return Err(RunError::Eof), + Ok(rx_data) => rx_data, + Err(e) => return Err(RunError::Read(e)), + }, + }; + Ok((buf, rx_data)) + }; + let tx_fut = tx_chan.tx_buf(); + match select(rx_fut, tx_fut).await { + Either::First(r) => { + needs_poll = false; + + let (buf, rx_data) = r?; + let n = ppp.consume(rx_data, &mut rx_buf); self.r.consume(n); - poll = true; + + match ppp.poll(&mut tx_buf, &mut rx_buf) { + PPPoSAction::None => {} + PPPoSAction::Received(rg) => { + let pkt = &rx_buf[rg]; + buf[..pkt.len()].copy_from_slice(pkt); + rx_chan.rx_done(pkt.len()); + } + PPPoSAction::Transmit(n) => match self.w.write_all(&tx_buf[..n]).await { + Ok(()) => {} + Err(WriteAllError::WriteZero) => return Err(RunError::WriteZero), + Err(WriteAllError::Other(e)) => return Err(RunError::Write(e)), + }, + } + + match ppp.status().phase { + ppproto::Phase::Open => state_chan.set_link_state(LinkState::Up), + _ => state_chan.set_link_state(LinkState::Down), + } } - Either3::Second(pkt) => { + Either::Second(pkt) => { match ppp.send(pkt, &mut tx_buf) { Ok(n) => match self.w.write_all(&tx_buf[..n]).await { Ok(()) => {} @@ -101,34 +127,6 @@ impl<'d, R: BufRead, W: Write> Runner<'d, R, W> { } tx_chan.tx_done(); } - Either3::Third(_) => poll = true, - } - - if poll { - match ppp.poll(&mut tx_buf, &mut rx_buf) { - PPPoSAction::None => {} - PPPoSAction::Received(rg) => { - let pkt = &rx_buf[rg]; - let buf = rx_chan.rx_buf().await; // TODO: fix possible deadlock - buf[..pkt.len()].copy_from_slice(pkt); - rx_chan.rx_done(pkt.len()); - - poll_signal.signal(()); - } - PPPoSAction::Transmit(n) => { - match self.w.write_all(&tx_buf[..n]).await { - Ok(()) => {} - Err(WriteAllError::WriteZero) => return Err(RunError::WriteZero), - Err(WriteAllError::Other(e)) => return Err(RunError::Write(e)), - } - poll_signal.signal(()); - } - } - - match ppp.status().phase { - ppproto::Phase::Open => state_chan.set_link_state(LinkState::Up), - _ => state_chan.set_link_state(LinkState::Down), - } } } } From c2d601abeff6f9f911b8140f3ceb6806971dc7dd Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Fri, 25 Aug 2023 15:57:02 +0200 Subject: [PATCH 053/106] net-ppp: take serial port and config in run(), allow calling it multiple times. --- embassy-net-driver-channel/src/lib.rs | 12 +++++++ embassy-net-ppp/src/lib.rs | 50 +++++++++++++++------------ 2 files changed, 39 insertions(+), 23 deletions(-) diff --git a/embassy-net-driver-channel/src/lib.rs b/embassy-net-driver-channel/src/lib.rs index f23c0441..f2aa6b25 100644 --- a/embassy-net-driver-channel/src/lib.rs +++ b/embassy-net-driver-channel/src/lib.rs @@ -74,6 +74,18 @@ impl<'d, const MTU: usize> Runner<'d, MTU> { ) } + pub fn borrow_split(&mut self) -> (StateRunner<'_>, RxRunner<'_, MTU>, TxRunner<'_, MTU>) { + ( + StateRunner { shared: self.shared }, + RxRunner { + rx_chan: self.rx_chan.borrow(), + }, + TxRunner { + tx_chan: self.tx_chan.borrow(), + }, + ) + } + pub fn state_runner(&self) -> StateRunner<'d> { StateRunner { shared: self.shared } } diff --git a/embassy-net-ppp/src/lib.rs b/embassy-net-ppp/src/lib.rs index af216c96..df583fb3 100644 --- a/embassy-net-ppp/src/lib.rs +++ b/embassy-net-ppp/src/lib.rs @@ -13,6 +13,7 @@ use embassy_net_driver_channel as ch; use embassy_net_driver_channel::driver::LinkState; use embedded_io_async::{BufRead, Write, WriteAllError}; use ppproto::pppos::{BufferFullError, PPPoS, PPPoSAction}; +pub use ppproto::Config; const MTU: usize = 1500; @@ -36,37 +37,44 @@ impl State { /// Background runner for the driver. /// /// You must call `.run()` in a background task for the driver to operate. -pub struct Runner<'d, R: BufRead, W: Write> { +pub struct Runner<'d> { ch: ch::Runner<'d, MTU>, - r: R, - w: W, } /// Error returned by [`Runner::run`]. #[derive(Debug)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] -pub enum RunError { +pub enum RunError { /// Reading from the serial port failed. - Read(RE), + Read(E), /// Writing to the serial port failed. - Write(WE), + Write(E), /// Writing to the serial port wrote zero bytes, indicating it can't accept more data. WriteZero, /// Writing to the serial got EOF. Eof, } -impl<'d, R: BufRead, W: Write> Runner<'d, R, W> { +impl<'d> Runner<'d> { /// You must call this in a background task for the driver to operate. - pub async fn run(mut self) -> Result> { - let config = ppproto::Config { - username: b"myuser", - password: b"mypass", - }; + /// + /// If reading/writing to the underlying serial port fails, the link state + /// is set to Down and the error is returned. + /// + /// It is allowed to cancel this function's future (i.e. drop it). This will terminate + /// the PPP connection and set the link state to Down. + /// + /// After this function returns or is canceled, you can call it again to establish + /// a new PPP connection. + pub async fn run( + &mut self, + mut rw: RW, + config: ppproto::Config<'_>, + ) -> Result> { let mut ppp = PPPoS::new(config); ppp.open().unwrap(); - let (state_chan, mut rx_chan, mut tx_chan) = self.ch.split(); + let (state_chan, mut rx_chan, mut tx_chan) = self.ch.borrow_split(); state_chan.set_link_state(LinkState::Down); let _ondrop = OnDrop::new(|| state_chan.set_link_state(LinkState::Down)); @@ -80,7 +88,7 @@ impl<'d, R: BufRead, W: Write> Runner<'d, R, W> { let buf = rx_chan.rx_buf().await; let rx_data = match needs_poll { true => &[][..], - false => match self.r.fill_buf().await { + false => match rw.fill_buf().await { Ok(rx_data) if rx_data.len() == 0 => return Err(RunError::Eof), Ok(rx_data) => rx_data, Err(e) => return Err(RunError::Read(e)), @@ -95,7 +103,7 @@ impl<'d, R: BufRead, W: Write> Runner<'d, R, W> { let (buf, rx_data) = r?; let n = ppp.consume(rx_data, &mut rx_buf); - self.r.consume(n); + rw.consume(n); match ppp.poll(&mut tx_buf, &mut rx_buf) { PPPoSAction::None => {} @@ -104,7 +112,7 @@ impl<'d, R: BufRead, W: Write> Runner<'d, R, W> { buf[..pkt.len()].copy_from_slice(pkt); rx_chan.rx_done(pkt.len()); } - PPPoSAction::Transmit(n) => match self.w.write_all(&tx_buf[..n]).await { + PPPoSAction::Transmit(n) => match rw.write_all(&tx_buf[..n]).await { Ok(()) => {} Err(WriteAllError::WriteZero) => return Err(RunError::WriteZero), Err(WriteAllError::Other(e)) => return Err(RunError::Write(e)), @@ -118,7 +126,7 @@ impl<'d, R: BufRead, W: Write> Runner<'d, R, W> { } Either::Second(pkt) => { match ppp.send(pkt, &mut tx_buf) { - Ok(n) => match self.w.write_all(&tx_buf[..n]).await { + Ok(n) => match rw.write_all(&tx_buf[..n]).await { Ok(()) => {} Err(WriteAllError::WriteZero) => return Err(RunError::WriteZero), Err(WriteAllError::Other(e)) => return Err(RunError::Write(e)), @@ -137,13 +145,9 @@ impl<'d, R: BufRead, W: Write> Runner<'d, R, W> { /// This returns two structs: /// - a `Device` that you must pass to the `embassy-net` stack. /// - a `Runner`. You must call `.run()` on it in a background task. -pub fn new<'a, const N_RX: usize, const N_TX: usize, R: BufRead, W: Write>( - state: &'a mut State, - r: R, - w: W, -) -> (Device<'a>, Runner<'a, R, W>) { +pub fn new<'a, const N_RX: usize, const N_TX: usize>(state: &'a mut State) -> (Device<'a>, Runner<'a>) { let (runner, device) = ch::new(&mut state.ch_state, ch::driver::HardwareAddress::Ip); - (device, Runner { ch: runner, r, w }) + (device, Runner { ch: runner }) } struct OnDrop { From a026db3f570cae504dc5da6c7055afc52e122930 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Fri, 25 Aug 2023 16:04:22 +0200 Subject: [PATCH 054/106] net-ppp: use From and ? to handle write errors. --- embassy-net-ppp/src/lib.rs | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/embassy-net-ppp/src/lib.rs b/embassy-net-ppp/src/lib.rs index df583fb3..e3b208ee 100644 --- a/embassy-net-ppp/src/lib.rs +++ b/embassy-net-ppp/src/lib.rs @@ -55,6 +55,15 @@ pub enum RunError { Eof, } +impl From> for RunError { + fn from(value: WriteAllError) -> Self { + match value { + WriteAllError::Other(e) => Self::Write(e), + WriteAllError::WriteZero => Self::WriteZero, + } + } +} + impl<'d> Runner<'d> { /// You must call this in a background task for the driver to operate. /// @@ -112,11 +121,7 @@ impl<'d> Runner<'d> { buf[..pkt.len()].copy_from_slice(pkt); rx_chan.rx_done(pkt.len()); } - PPPoSAction::Transmit(n) => match rw.write_all(&tx_buf[..n]).await { - Ok(()) => {} - Err(WriteAllError::WriteZero) => return Err(RunError::WriteZero), - Err(WriteAllError::Other(e)) => return Err(RunError::Write(e)), - }, + PPPoSAction::Transmit(n) => rw.write_all(&tx_buf[..n]).await?, } match ppp.status().phase { @@ -126,11 +131,7 @@ impl<'d> Runner<'d> { } Either::Second(pkt) => { match ppp.send(pkt, &mut tx_buf) { - Ok(n) => match rw.write_all(&tx_buf[..n]).await { - Ok(()) => {} - Err(WriteAllError::WriteZero) => return Err(RunError::WriteZero), - Err(WriteAllError::Other(e)) => return Err(RunError::Write(e)), - }, + Ok(n) => rw.write_all(&tx_buf[..n]).await?, Err(BufferFullError) => unreachable!(), } tx_chan.tx_done(); From 623f37a27368c53d782cc9819c180bdf45f15612 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Fri, 25 Aug 2023 19:49:28 +0200 Subject: [PATCH 055/106] net-ppp: add callback for IP configuration. --- embassy-net-ppp/src/lib.rs | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/embassy-net-ppp/src/lib.rs b/embassy-net-ppp/src/lib.rs index e3b208ee..ca87fbae 100644 --- a/embassy-net-ppp/src/lib.rs +++ b/embassy-net-ppp/src/lib.rs @@ -13,7 +13,7 @@ use embassy_net_driver_channel as ch; use embassy_net_driver_channel::driver::LinkState; use embedded_io_async::{BufRead, Write, WriteAllError}; use ppproto::pppos::{BufferFullError, PPPoS, PPPoSAction}; -pub use ppproto::Config; +pub use ppproto::{Config, Ipv4Status}; const MTU: usize = 1500; @@ -79,6 +79,7 @@ impl<'d> Runner<'d> { &mut self, mut rw: RW, config: ppproto::Config<'_>, + mut on_ipv4_up: impl FnMut(Ipv4Status), ) -> Result> { let mut ppp = PPPoS::new(config); ppp.open().unwrap(); @@ -91,6 +92,7 @@ impl<'d> Runner<'d> { let mut tx_buf = [0; 2048]; let mut needs_poll = true; + let mut was_up = false; loop { let rx_fut = async { @@ -124,9 +126,19 @@ impl<'d> Runner<'d> { PPPoSAction::Transmit(n) => rw.write_all(&tx_buf[..n]).await?, } - match ppp.status().phase { - ppproto::Phase::Open => state_chan.set_link_state(LinkState::Up), - _ => state_chan.set_link_state(LinkState::Down), + let status = ppp.status(); + match status.phase { + ppproto::Phase::Open => { + if !was_up { + on_ipv4_up(status.ipv4.unwrap()); + } + was_up = true; + state_chan.set_link_state(LinkState::Up); + } + _ => { + was_up = false; + state_chan.set_link_state(LinkState::Down); + } } } Either::Second(pkt) => { From d812cc574571e60a092f10727046c494face09c9 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Fri, 25 Aug 2023 19:49:43 +0200 Subject: [PATCH 056/106] net-ppp: add std example. --- examples/std/Cargo.toml | 4 +- examples/std/src/bin/net_ppp.rs | 218 ++++++++++++++++++++++++++++++++ 2 files changed, 221 insertions(+), 1 deletion(-) create mode 100644 examples/std/src/bin/net_ppp.rs diff --git a/examples/std/Cargo.toml b/examples/std/Cargo.toml index 0d4d5fa1..7b0d0bda 100644 --- a/examples/std/Cargo.toml +++ b/examples/std/Cargo.toml @@ -8,11 +8,13 @@ license = "MIT OR Apache-2.0" embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["log"] } embassy-executor = { version = "0.3.0", path = "../../embassy-executor", features = ["arch-std", "executor-thread", "log", "nightly", "integrated-timers"] } embassy-time = { version = "0.1.2", path = "../../embassy-time", features = ["log", "std", "nightly"] } -embassy-net = { version = "0.1.0", path = "../../embassy-net", features=[ "std", "nightly", "log", "medium-ethernet", "tcp", "udp", "dns", "dhcpv4", "proto-ipv6"] } +embassy-net = { version = "0.1.0", path = "../../embassy-net", features=[ "std", "nightly", "log", "medium-ethernet", "medium-ip", "tcp", "udp", "dns", "dhcpv4", "proto-ipv6"] } embassy-net-tuntap = { version = "0.1.0", path = "../../embassy-net-tuntap" } +embassy-net-ppp = { version = "0.1.0", path = "../../embassy-net-ppp", features = ["log"]} embedded-io-async = { version = "0.5.0" } embedded-io-adapters = { version = "0.5.0", features = ["futures-03"] } critical-section = { version = "1.1", features = ["std"] } +smoltcp = { version = "0.10.0", features = ["dns-max-server-count-4"] } async-io = "1.6.0" env_logger = "0.9.0" diff --git a/examples/std/src/bin/net_ppp.rs b/examples/std/src/bin/net_ppp.rs new file mode 100644 index 00000000..9cf6e19d --- /dev/null +++ b/examples/std/src/bin/net_ppp.rs @@ -0,0 +1,218 @@ +//! Testing against pppd: +//! +//! echo myuser $(hostname) mypass 192.168.7.10 >> /etc/ppp/pap-secrets +//! socat -v -x PTY,link=pty1,rawer PTY,link=pty2,rawer +//! sudo pppd $PWD/pty1 115200 192.168.7.1: ms-dns 8.8.4.4 ms-dns 8.8.8.8 nodetach debug local persist silent noproxyarp +//! RUST_LOG=trace cargo run --bin net_ppp -- --device pty2 +//! ping 192.168.7.10 +//! nc 192.168.7.10 1234 + +#![feature(type_alias_impl_trait)] +#![feature(async_fn_in_trait, impl_trait_projections)] + +#[path = "../serial_port.rs"] +mod serial_port; + +use async_io::Async; +use clap::Parser; +use embassy_executor::{Executor, Spawner}; +use embassy_net::tcp::TcpSocket; +use embassy_net::{Config, ConfigV4, Ipv4Address, Ipv4Cidr, Stack, StackResources}; +use embassy_net_ppp::Runner; +use embedded_io_async::Write; +use futures::io::BufReader; +use heapless::Vec; +use log::*; +use nix::sys::termios; +use rand_core::{OsRng, RngCore}; +use static_cell::{make_static, StaticCell}; + +use crate::serial_port::SerialPort; + +#[derive(Parser)] +#[clap(version = "1.0")] +struct Opts { + /// Serial port device name + #[clap(short, long)] + device: String, +} + +#[embassy_executor::task] +async fn net_task(stack: &'static Stack>) -> ! { + stack.run().await +} + +#[embassy_executor::task] +async fn ppp_task( + stack: &'static Stack>, + mut runner: Runner<'static>, + port: SerialPort, +) -> ! { + let port = Async::new(port).unwrap(); + let port = BufReader::new(port); + let port = adapter::FromFutures::new(port); + + let config = embassy_net_ppp::Config { + username: b"myuser", + password: b"mypass", + }; + + runner + .run(port, config, |ipv4| { + let Some(addr) = ipv4.address else { + warn!("PPP did not provide an IP address."); + return; + }; + let mut dns_servers = Vec::new(); + for s in ipv4.dns_servers.iter().flatten() { + let _ = dns_servers.push(Ipv4Address::from_bytes(&s.0)); + } + let config = ConfigV4::Static(embassy_net::StaticConfigV4 { + address: Ipv4Cidr::new(Ipv4Address::from_bytes(&addr.0), 0), + gateway: None, + dns_servers, + }); + stack.set_config_v4(config); + }) + .await + .unwrap(); + unreachable!() +} + +#[embassy_executor::task] +async fn main_task(spawner: Spawner) { + let opts: Opts = Opts::parse(); + + // Open serial port + let baudrate = termios::BaudRate::B115200; + let port = SerialPort::new(opts.device.as_str(), baudrate).unwrap(); + + // Init network device + let state = make_static!(embassy_net_ppp::State::<4, 4>::new()); + let (device, runner) = embassy_net_ppp::new(state); + + // Generate random seed + let mut seed = [0; 8]; + OsRng.fill_bytes(&mut seed); + let seed = u64::from_le_bytes(seed); + + // Init network stack + let stack = &*make_static!(Stack::new( + device, + Config::default(), // don't configure IP yet + make_static!(StackResources::<3>::new()), + seed + )); + + // Launch network task + spawner.spawn(net_task(stack)).unwrap(); + spawner.spawn(ppp_task(stack, runner, port)).unwrap(); + + // Then we can use it! + let mut rx_buffer = [0; 4096]; + let mut tx_buffer = [0; 4096]; + let mut buf = [0; 4096]; + + loop { + let mut socket = TcpSocket::new(stack, &mut rx_buffer, &mut tx_buffer); + socket.set_timeout(Some(embassy_time::Duration::from_secs(10))); + + info!("Listening on TCP:1234..."); + if let Err(e) = socket.accept(1234).await { + warn!("accept error: {:?}", e); + continue; + } + + info!("Received connection from {:?}", socket.remote_endpoint()); + + loop { + let n = match socket.read(&mut buf).await { + Ok(0) => { + warn!("read EOF"); + break; + } + Ok(n) => n, + Err(e) => { + warn!("read error: {:?}", e); + break; + } + }; + + info!("rxd {:02x?}", &buf[..n]); + + match socket.write_all(&buf[..n]).await { + Ok(()) => {} + Err(e) => { + warn!("write error: {:?}", e); + break; + } + }; + } + } +} + +static EXECUTOR: StaticCell = StaticCell::new(); + +fn main() { + env_logger::builder() + .filter_level(log::LevelFilter::Trace) + .filter_module("polling", log::LevelFilter::Info) + .filter_module("async_io", log::LevelFilter::Info) + .format_timestamp_nanos() + .init(); + + let executor = EXECUTOR.init(Executor::new()); + executor.run(|spawner| { + spawner.spawn(main_task(spawner)).unwrap(); + }); +} + +mod adapter { + use core::future::poll_fn; + use core::pin::Pin; + + use futures::AsyncBufReadExt; + + /// Adapter from `futures::io` traits. + #[derive(Clone)] + pub struct FromFutures { + inner: T, + } + + impl FromFutures { + /// Create a new adapter. + pub fn new(inner: T) -> Self { + Self { inner } + } + } + + impl embedded_io_async::ErrorType for FromFutures { + type Error = std::io::Error; + } + + impl embedded_io_async::Read for FromFutures { + async fn read(&mut self, buf: &mut [u8]) -> Result { + poll_fn(|cx| Pin::new(&mut self.inner).poll_read(cx, buf)).await + } + } + + impl embedded_io_async::BufRead for FromFutures { + async fn fill_buf(&mut self) -> Result<&[u8], Self::Error> { + self.inner.fill_buf().await + } + + fn consume(&mut self, amt: usize) { + Pin::new(&mut self.inner).consume(amt) + } + } + + impl embedded_io_async::Write for FromFutures { + async fn write(&mut self, buf: &[u8]) -> Result { + poll_fn(|cx| Pin::new(&mut self.inner).poll_write(cx, buf)).await + } + + async fn flush(&mut self) -> Result<(), Self::Error> { + poll_fn(|cx| Pin::new(&mut self.inner).poll_flush(cx)).await + } + } +} From f8299d10f7c0387416989e00acc02d99661537fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Buga?= Date: Fri, 25 Aug 2023 23:32:00 +0200 Subject: [PATCH 057/106] Prepare executor and macros for release (#1825) * Set release date, bump macros version * Add pool_size change to changelog --- embassy-executor/CHANGELOG.md | 3 ++- embassy-executor/Cargo.toml | 2 +- embassy-macros/Cargo.toml | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/embassy-executor/CHANGELOG.md b/embassy-executor/CHANGELOG.md index 4853ba29..ccbca1eb 100644 --- a/embassy-executor/CHANGELOG.md +++ b/embassy-executor/CHANGELOG.md @@ -5,11 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## 0.3.0 - TBD +## 0.3.0 - 2023-08-25 - Replaced Pender. Implementations now must define an extern function called `__pender`. - Made `raw::AvailableTask` public - Made `SpawnToken::new_failed` public +- You can now use arbitrary expressions to specify `#[task(pool_size = X)]` ## 0.2.1 - 2023-08-10 diff --git a/embassy-executor/Cargo.toml b/embassy-executor/Cargo.toml index 2a67f70d..5bf68fc6 100644 --- a/embassy-executor/Cargo.toml +++ b/embassy-executor/Cargo.toml @@ -58,7 +58,7 @@ log = { version = "0.4.14", optional = true } rtos-trace = { version = "0.1.2", optional = true } futures-util = { version = "0.3.17", default-features = false } -embassy-macros = { version = "0.2.0", path = "../embassy-macros" } +embassy-macros = { version = "0.2.1", path = "../embassy-macros" } embassy-time = { version = "0.1.2", path = "../embassy-time", optional = true} atomic-polyfill = "1.0.1" critical-section = "1.1" diff --git a/embassy-macros/Cargo.toml b/embassy-macros/Cargo.toml index 3b8fe8b4..a893cd30 100644 --- a/embassy-macros/Cargo.toml +++ b/embassy-macros/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "embassy-macros" -version = "0.2.0" +version = "0.2.1" edition = "2021" license = "MIT OR Apache-2.0" description = "macros for creating the entry point and tasks for embassy-executor" From 3023e70ccf14157c6a9c1315b987951cb6138e0d Mon Sep 17 00:00:00 2001 From: xoviat Date: Fri, 25 Aug 2023 18:41:51 -0500 Subject: [PATCH 058/106] stm32: clenaup lp executor --- embassy-stm32/src/low_power.rs | 154 +++++++++++++++++++-------------- 1 file changed, 91 insertions(+), 63 deletions(-) diff --git a/embassy-stm32/src/low_power.rs b/embassy-stm32/src/low_power.rs index 0d9506aa..cf12a1ea 100644 --- a/embassy-stm32/src/low_power.rs +++ b/embassy-stm32/src/low_power.rs @@ -16,36 +16,30 @@ const THRESHOLD: Duration = Duration::from_millis(500); use crate::rtc::{Rtc, RtcInstant}; -static mut RTC: Option<&'static Rtc> = None; -static mut STOP_TIME: embassy_time::Duration = Duration::from_ticks(0); -static mut NEXT_ALARM: embassy_time::Duration = Duration::from_ticks(u64::MAX); -static mut RTC_INSTANT: Option = None; +static mut EXECUTOR: Option = None; foreach_interrupt! { (RTC, rtc, $block:ident, WKUP, $irq:ident) => { #[interrupt] unsafe fn $irq() { - Executor::on_wakeup_irq(); + unsafe { EXECUTOR.as_mut().unwrap() }.on_wakeup_irq(); } }; } pub fn stop_with_rtc(rtc: &'static Rtc) { - crate::interrupt::typelevel::RTC_WKUP::unpend(); - unsafe { crate::interrupt::typelevel::RTC_WKUP::enable() }; - - EXTI.rtsr(0).modify(|w| w.set_line(22, true)); - EXTI.imr(0).modify(|w| w.set_line(22, true)); - - unsafe { RTC = Some(rtc) }; + unsafe { EXECUTOR.as_mut().unwrap() }.stop_with_rtc(rtc) } pub fn start_wakeup_alarm(requested_duration: embassy_time::Duration) -> RtcInstant { - unsafe { RTC }.unwrap().start_wakeup_alarm(requested_duration) + unsafe { EXECUTOR.as_mut().unwrap() } + .rtc + .unwrap() + .start_wakeup_alarm(requested_duration) } pub fn stop_wakeup_alarm() -> RtcInstant { - unsafe { RTC }.unwrap().stop_wakeup_alarm() + unsafe { EXECUTOR.as_mut().unwrap() }.rtc.unwrap().stop_wakeup_alarm() } /// Thread mode executor, using WFE/SEV. @@ -61,69 +55,103 @@ pub fn stop_wakeup_alarm() -> RtcInstant { pub struct Executor { inner: raw::Executor, not_send: PhantomData<*mut ()>, + scb: SCB, + pub(self) rtc: Option<&'static Rtc>, + stop_time: embassy_time::Duration, + next_alarm: embassy_time::Duration, + last_stop: Option, } impl Executor { /// Create a new Executor. - pub fn new() -> Self { - Self { - inner: raw::Executor::new(THREAD_PENDER as *mut ()), - not_send: PhantomData, + pub fn new() -> &'static mut Self { + unsafe { + assert!(EXECUTOR.is_none()); + + EXECUTOR = Some(Self { + inner: raw::Executor::new(THREAD_PENDER as *mut ()), + not_send: PhantomData, + scb: cortex_m::Peripherals::steal().SCB, + rtc: None, + stop_time: Duration::from_ticks(0), + next_alarm: Duration::from_ticks(u64::MAX), + last_stop: None, + }); + + EXECUTOR.as_mut().unwrap() } } - unsafe fn on_wakeup_irq() { - trace!("on wakeup irq"); + unsafe fn on_wakeup_irq(&mut self) { + trace!("low power: one wakekup irq"); - let elapsed = RTC_INSTANT.take().unwrap() - stop_wakeup_alarm(); - - STOP_TIME += elapsed; - // let to_next = NEXT_ALARM - STOP_TIME; - let to_next = Duration::from_secs(3); - - trace!("on wakeup irq: to next: {}", to_next); - if to_next > THRESHOLD { - trace!("start wakeup alarm"); - RTC_INSTANT.replace(start_wakeup_alarm(to_next)); - - trace!("set sleeponexit"); - Self::get_scb().set_sleeponexit(); - } else { - Self::get_scb().clear_sleeponexit(); - Self::get_scb().clear_sleepdeep(); - } + self.rtc.unwrap().clear_wakeup_alarm(); + // Self::get_scb().set_sleeponexit(); + // + // return; + // + // let elapsed = RTC_INSTANT.take().unwrap() - stop_wakeup_alarm(); + // + // STOP_TIME += elapsed; + // // let to_next = NEXT_ALARM - STOP_TIME; + // let to_next = Duration::from_secs(3); + // + // trace!("on wakeup irq: to next: {}", to_next); + // if to_next > THRESHOLD { + // trace!("start wakeup alarm"); + // RTC_INSTANT.replace(start_wakeup_alarm(to_next)); + // + // trace!("set sleeponexit"); + // Self::get_scb().set_sleeponexit(); + // } else { + // Self::get_scb().clear_sleeponexit(); + // Self::get_scb().clear_sleepdeep(); + // } } - fn get_scb() -> SCB { - unsafe { cortex_m::Peripherals::steal() }.SCB + pub(self) fn stop_with_rtc(&mut self, rtc: &'static Rtc) { + assert!(self.rtc.is_none()); + + crate::interrupt::typelevel::RTC_WKUP::unpend(); + unsafe { crate::interrupt::typelevel::RTC_WKUP::enable() }; + + EXTI.rtsr(0).modify(|w| w.set_line(22, true)); + EXTI.imr(0).modify(|w| w.set_line(22, true)); + + self.rtc = Some(rtc); } fn configure_pwr(&self) { - trace!("configure_pwr"); + // defeat the borrow checker + let s = unsafe { EXECUTOR.as_mut().unwrap() }; - if !low_power_ready() { - trace!("configure_pwr: low power not ready"); - return; - } - - let time_until_next_alarm = time_until_next_alarm(); - if time_until_next_alarm < THRESHOLD { - trace!("configure_pwr: not enough time until next alarm"); - return; - } - - unsafe { - NEXT_ALARM = time_until_next_alarm; - RTC_INSTANT = Some(start_wakeup_alarm(time_until_next_alarm)) - }; - - // return; - - pause_time(); - - trace!("enter stop..."); - - Self::get_scb().set_sleepdeep(); + // trace!("configure_pwr"); + // + // if !low_power_ready() { + // trace!("configure_pwr: low power not ready"); + // return; + // } + // + // let time_until_next_alarm = time_until_next_alarm(); + // if time_until_next_alarm < THRESHOLD { + // trace!("configure_pwr: not enough time until next alarm"); + // return; + // } + // + // unsafe { + // NEXT_ALARM = time_until_next_alarm; + // if RTC_INSTANT.is_none() { + // RTC_INSTANT = Some(start_wakeup_alarm(time_until_next_alarm)) + // } + // }; + // + // // return; + // + // pause_time(); + // + // trace!("enter stop..."); + // + // Self::get_scb().set_sleepdeep(); } /// Run the executor. From 54e2e17520e678eb5f57661222670f7d891f1810 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Buga?= Date: Sat, 26 Aug 2023 05:43:16 +0200 Subject: [PATCH 059/106] Avoid dead code warning --- embassy-executor/src/arch/cortex_m.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/embassy-executor/src/arch/cortex_m.rs b/embassy-executor/src/arch/cortex_m.rs index 0806a22a..fde862f3 100644 --- a/embassy-executor/src/arch/cortex_m.rs +++ b/embassy-executor/src/arch/cortex_m.rs @@ -1,5 +1,3 @@ -const THREAD_PENDER: usize = usize::MAX; - #[export_name = "__pender"] #[cfg(any(feature = "executor-thread", feature = "executor-interrupt"))] fn __pender(context: *mut ()) { @@ -48,13 +46,14 @@ fn __pender(context: *mut ()) { pub use thread::*; #[cfg(feature = "executor-thread")] mod thread { + pub(super) const THREAD_PENDER: usize = usize::MAX; + use core::arch::asm; use core::marker::PhantomData; #[cfg(feature = "nightly")] pub use embassy_macros::main_cortex_m as main; - use crate::arch::THREAD_PENDER; use crate::{raw, Spawner}; /// Thread mode executor, using WFE/SEV. From d33246b072f222bd221471da7d498593ef8c6211 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Buga?= Date: Sat, 26 Aug 2023 12:40:57 +0200 Subject: [PATCH 060/106] Add new feature/arch combinations to executor CI check --- ci.sh | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/ci.sh b/ci.sh index e83b3b84..db00c406 100755 --- a/ci.sh +++ b/ci.sh @@ -19,6 +19,19 @@ cargo batch \ --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features nightly,log \ --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features nightly,defmt \ --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv6m-none-eabi --features nightly,defmt \ + --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv6m-none-eabi --features nightly,defmt,arch-cortex-m,executor-thread,executor-interrupt,integrated-timers \ + --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features nightly,arch-cortex-m \ + --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features nightly,arch-cortex-m,integrated-timers \ + --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features nightly,arch-cortex-m,executor-thread \ + --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features nightly,arch-cortex-m,executor-thread,integrated-timers \ + --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features nightly,arch-cortex-m,executor-interrupt \ + --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features nightly,arch-cortex-m,executor-interrupt,integrated-timers \ + --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features nightly,arch-cortex-m,executor-thread,executor-interrupt \ + --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features nightly,arch-cortex-m,executor-thread,executor-interrupt,integrated-timers \ + --- build --release --manifest-path embassy-executor/Cargo.toml --target riscv32imac-unknown-none-elf --features nightly,arch-riscv32 \ + --- build --release --manifest-path embassy-executor/Cargo.toml --target riscv32imac-unknown-none-elf --features nightly,arch-riscv32,integrated-timers \ + --- build --release --manifest-path embassy-executor/Cargo.toml --target riscv32imac-unknown-none-elf --features nightly,arch-riscv32,executor-thread \ + --- build --release --manifest-path embassy-executor/Cargo.toml --target riscv32imac-unknown-none-elf --features nightly,arch-riscv32,executor-thread,integrated-timers \ --- build --release --manifest-path embassy-sync/Cargo.toml --target thumbv6m-none-eabi --features nightly,defmt \ --- build --release --manifest-path embassy-time/Cargo.toml --target thumbv6m-none-eabi --features nightly,defmt,defmt-timestamp-uptime,tick-hz-32_768,generic-queue-8 \ --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,proto-ipv4,medium-ethernet \ From 2897670f2438525bc128cf016ee8f8a948edfbb7 Mon Sep 17 00:00:00 2001 From: xoviat Date: Sat, 26 Aug 2023 19:23:25 -0500 Subject: [PATCH 061/106] stm32: get the basic lp working --- embassy-stm32/src/low_power.rs | 126 +++++++++++++++++-------------- embassy-stm32/src/rtc/v2.rs | 55 +++++++++++--- embassy-stm32/src/time_driver.rs | 107 ++++++++++++++++++++------ 3 files changed, 196 insertions(+), 92 deletions(-) diff --git a/embassy-stm32/src/low_power.rs b/embassy-stm32/src/low_power.rs index cf12a1ea..964819ab 100644 --- a/embassy-stm32/src/low_power.rs +++ b/embassy-stm32/src/low_power.rs @@ -9,12 +9,11 @@ use crate::interrupt; use crate::interrupt::typelevel::Interrupt; use crate::pac::EXTI; use crate::rcc::low_power_ready; -use crate::time_driver::{pause_time, resume_time, time_until_next_alarm}; +use crate::time_driver::{get_driver, RtcDriver}; const THREAD_PENDER: usize = usize::MAX; -const THRESHOLD: Duration = Duration::from_millis(500); -use crate::rtc::{Rtc, RtcInstant}; +use crate::rtc::Rtc; static mut EXECUTOR: Option = None; @@ -27,20 +26,30 @@ foreach_interrupt! { }; } +// pub fn timer_driver_pause_time() { +// pause_time(); +// } + pub fn stop_with_rtc(rtc: &'static Rtc) { unsafe { EXECUTOR.as_mut().unwrap() }.stop_with_rtc(rtc) } -pub fn start_wakeup_alarm(requested_duration: embassy_time::Duration) -> RtcInstant { - unsafe { EXECUTOR.as_mut().unwrap() } - .rtc - .unwrap() - .start_wakeup_alarm(requested_duration) -} - -pub fn stop_wakeup_alarm() -> RtcInstant { - unsafe { EXECUTOR.as_mut().unwrap() }.rtc.unwrap().stop_wakeup_alarm() -} +// pub fn start_wakeup_alarm(requested_duration: embassy_time::Duration) { +// let rtc_instant = unsafe { EXECUTOR.as_mut().unwrap() } +// .rtc +// .unwrap() +// .start_wakeup_alarm(requested_duration); +// +// unsafe { EXECUTOR.as_mut().unwrap() }.last_stop = Some(rtc_instant); +// } +// +// pub fn set_sleepdeep() { +// unsafe { EXECUTOR.as_mut().unwrap() }.scb.set_sleepdeep(); +// } +// +// pub fn stop_wakeup_alarm() -> RtcInstant { +// unsafe { EXECUTOR.as_mut().unwrap() }.rtc.unwrap().stop_wakeup_alarm() +// } /// Thread mode executor, using WFE/SEV. /// @@ -56,15 +65,15 @@ pub struct Executor { inner: raw::Executor, not_send: PhantomData<*mut ()>, scb: SCB, - pub(self) rtc: Option<&'static Rtc>, + time_driver: &'static RtcDriver, stop_time: embassy_time::Duration, next_alarm: embassy_time::Duration, - last_stop: Option, + wfe: u8, } impl Executor { /// Create a new Executor. - pub fn new() -> &'static mut Self { + pub fn take() -> &'static mut Self { unsafe { assert!(EXECUTOR.is_none()); @@ -72,10 +81,10 @@ impl Executor { inner: raw::Executor::new(THREAD_PENDER as *mut ()), not_send: PhantomData, scb: cortex_m::Peripherals::steal().SCB, - rtc: None, + time_driver: get_driver(), stop_time: Duration::from_ticks(0), next_alarm: Duration::from_ticks(u64::MAX), - last_stop: None, + wfe: 0, }); EXECUTOR.as_mut().unwrap() @@ -83,9 +92,31 @@ impl Executor { } unsafe fn on_wakeup_irq(&mut self) { - trace!("low power: one wakekup irq"); + trace!("low power: on wakeup irq"); - self.rtc.unwrap().clear_wakeup_alarm(); + if crate::pac::RTC.isr().read().wutf() { + trace!("low power: wutf set"); + } else { + trace!("low power: wutf not set"); + } + + self.time_driver.resume_time(); + trace!("low power: resume time"); + + crate::interrupt::typelevel::RTC_WKUP::disable(); + + // cortex_m::asm::bkpt(); + + // let time_elasped = self.rtc.unwrap().stop_wakeup_alarm() - self.last_stop.take().unwrap(); + // + // trace!("low power: {} ms elapsed", time_elasped.as_millis()); + // + // resume_time(time_elasped); + // trace!("low power: resume time"); + // + // self.scb.clear_sleepdeep(); + + // cortex_m::asm::bkpt(); // Self::get_scb().set_sleeponexit(); // // return; @@ -110,48 +141,33 @@ impl Executor { } pub(self) fn stop_with_rtc(&mut self, rtc: &'static Rtc) { - assert!(self.rtc.is_none()); + trace!("low power: stop with rtc configured"); + + self.time_driver.set_rtc(rtc); crate::interrupt::typelevel::RTC_WKUP::unpend(); unsafe { crate::interrupt::typelevel::RTC_WKUP::enable() }; EXTI.rtsr(0).modify(|w| w.set_line(22, true)); EXTI.imr(0).modify(|w| w.set_line(22, true)); - - self.rtc = Some(rtc); } - fn configure_pwr(&self) { - // defeat the borrow checker - let s = unsafe { EXECUTOR.as_mut().unwrap() }; + fn configure_pwr(&mut self) { + trace!("low power: configure_pwr"); - // trace!("configure_pwr"); - // - // if !low_power_ready() { - // trace!("configure_pwr: low power not ready"); - // return; - // } - // - // let time_until_next_alarm = time_until_next_alarm(); - // if time_until_next_alarm < THRESHOLD { - // trace!("configure_pwr: not enough time until next alarm"); - // return; - // } - // - // unsafe { - // NEXT_ALARM = time_until_next_alarm; - // if RTC_INSTANT.is_none() { - // RTC_INSTANT = Some(start_wakeup_alarm(time_until_next_alarm)) - // } - // }; - // - // // return; - // - // pause_time(); - // - // trace!("enter stop..."); - // - // Self::get_scb().set_sleepdeep(); + self.scb.clear_sleepdeep(); + if !low_power_ready() { + trace!("low power: configure_pwr: low power not ready"); + return; + } + + if self.time_driver.pause_time().is_err() { + trace!("low power: configure_pwr: time driver failed to pause"); + return; + } + + trace!("low power: enter stop..."); + self.scb.set_sleepdeep(); } /// Run the executor. @@ -173,11 +189,11 @@ impl Executor { /// /// This function never returns. pub fn run(&'static mut self, init: impl FnOnce(Spawner)) -> ! { - init(self.inner.spawner()); + init(unsafe { EXECUTOR.as_mut().unwrap() }.inner.spawner()); loop { unsafe { - self.inner.poll(); + EXECUTOR.as_mut().unwrap().inner.poll(); self.configure_pwr(); asm!("wfe"); }; diff --git a/embassy-stm32/src/rtc/v2.rs b/embassy-stm32/src/rtc/v2.rs index 197c3b8f..525dc45a 100644 --- a/embassy-stm32/src/rtc/v2.rs +++ b/embassy-stm32/src/rtc/v2.rs @@ -30,6 +30,8 @@ impl RtcInstant { let _ = RTC::regs().dr().read(); + trace!("rtc: instant now: st, ssr: {}, {}", st, ssr); + Self { ssr, st } } } @@ -146,6 +148,21 @@ impl super::Rtc { } } + // pub(crate) fn clear_wakeup_alarm(&self) { + // use crate::interrupt::typelevel::Interrupt; + // + // self.write(false, |regs| { + // regs.cr().modify(|w| w.set_wutie(false)); + // + // regs.isr().modify(|w| w.set_wutf(false)); + // crate::pac::PWR.cr1().modify(|w| w.set_cwuf(false)); + // crate::pac::EXTI.pr(0).modify(|w| w.set_line(22, false)); + // crate::interrupt::typelevel::RTC_WKUP::unpend(); + // + // regs.cr().modify(|w| w.set_wutie(true)); + // }); + // } + #[allow(dead_code)] #[cfg(all(feature = "time", any(stm32wb, stm32f4)))] /// start the wakeup alarm and return the actual duration of the alarm @@ -157,6 +174,7 @@ impl super::Rtc { pub(crate) fn start_wakeup_alarm(&self, requested_duration: embassy_time::Duration) -> RtcInstant { use embassy_time::{Duration, TICK_HZ}; + use crate::interrupt::typelevel::Interrupt; use crate::rcc::get_freqs; let rtc_hz = unsafe { get_freqs() }.rtc.unwrap().0 as u64; @@ -176,28 +194,40 @@ impl super::Rtc { rtc_ticks as u64 * TICK_HZ * (>::into(prescaler) as u64) / rtc_hz, ); - trace!("rtc: set wakeup timer for {} ms", duration.as_millis()); - self.write(false, |regs| { - // regs.cr().modify(|w| w.set_wutie(true)); - regs.cr().modify(|w| w.set_wute(false)); regs.isr().modify(|w| w.set_wutf(false)); while !regs.isr().read().wutwf() {} regs.cr().modify(|w| w.set_wucksel(prescaler.into())); regs.cr().modify(|w| w.set_wute(true)); - }); - - self.write(false, |regs| { - regs.cr().modify(|w| w.set_wutie(false)); - - regs.isr().modify(|w| w.set_wutf(false)); - crate::pac::PWR.cr1().modify(|w| w.set_cwuf(false)); - regs.cr().modify(|w| w.set_wutie(true)); }); + trace!("rtc: start wakeup alarm for {} ms", duration.as_millis()); + + // self.write(false, |regs| { + // regs.cr().modify(|w| w.set_wutie(false)); + // + // regs.isr().modify(|w| w.set_wutf(false)); + // + // regs.cr().modify(|w| w.set_wutie(true)); + // }); + // + // trace!("rtc: clear wuf..."); + // crate::pac::PWR.cr1().modify(|w| w.set_cwuf(true)); + // while crate::pac::PWR.csr1().read().wuf() {} + // trace!("rtc: clear wuf...done"); + // + // crate::pac::PWR + // .cr1() + // .modify(|w| w.set_pdds(crate::pac::pwr::vals::Pdds::STANDBY_MODE)); + // + // // crate::pac::PWR.cr1().modify(|w| w.set_lpds(true)); + // + // // crate::pac::EXTI.pr(0).modify(|w| w.set_line(22, true)); + // crate::interrupt::typelevel::RTC_WKUP::unpend(); + RtcInstant::now() } @@ -211,6 +241,7 @@ impl super::Rtc { trace!("rtc: stop wakeup alarm..."); self.write(false, |regs| { + regs.cr().modify(|w| w.set_wutie(false)); regs.cr().modify(|w| w.set_wute(false)); regs.isr().modify(|w| w.set_wutf(false)); }); diff --git a/embassy-stm32/src/time_driver.rs b/embassy-stm32/src/time_driver.rs index 8e05346a..56f42aa9 100644 --- a/embassy-stm32/src/time_driver.rs +++ b/embassy-stm32/src/time_driver.rs @@ -14,6 +14,8 @@ use stm32_metapac::timer::regs; use crate::interrupt::typelevel::Interrupt; use crate::pac::timer::vals; use crate::rcc::sealed::RccPeripheral; +#[cfg(feature = "low-power")] +use crate::rtc::{Rtc, RtcInstant}; use crate::timer::sealed::{Basic16bitInstance as BasicInstance, GeneralPurpose16bitInstance as Instance}; use crate::{interrupt, peripherals}; @@ -130,12 +132,16 @@ impl AlarmState { } } -struct RtcDriver { +pub(crate) struct RtcDriver { /// Number of 2^15 periods elapsed since boot. period: AtomicU32, alarm_count: AtomicU8, /// Timestamp at which to fire alarm. u64::MAX if no alarm is scheduled. alarms: Mutex, + #[cfg(feature = "low-power")] + rtc: Mutex>>, + #[cfg(feature = "low-power")] + stop_time: Mutex>>, } const ALARM_STATE_NEW: AlarmState = AlarmState::new(); @@ -144,6 +150,10 @@ embassy_time::time_driver_impl!(static DRIVER: RtcDriver = RtcDriver { period: AtomicU32::new(0), alarm_count: AtomicU8::new(0), alarms: Mutex::const_new(CriticalSectionRawMutex::new(), [ALARM_STATE_NEW; ALARM_COUNT]), + #[cfg(feature = "low-power")] + rtc: Mutex::const_new(CriticalSectionRawMutex::new(), Cell::new(None)), + #[cfg(feature = "low-power")] + stop_time: Mutex::const_new(CriticalSectionRawMutex::new(), Cell::new(None)), }); impl RtcDriver { @@ -260,9 +270,15 @@ impl RtcDriver { f(alarm.ctx.get()); } + #[cfg(feature = "low-power")] + /// Set the rtc but panic if it's already been set + pub(crate) fn set_rtc(&self, rtc: &'static Rtc) { + critical_section::with(|cs| assert!(self.rtc.borrow(cs).replace(Some(rtc)).is_none())); + } + #[cfg(feature = "low-power")] /// Compute the approximate amount of time until the next alarm - pub(crate) fn time_until_next_alarm(&self) -> embassy_time::Duration { + fn time_until_next_alarm(&self) -> embassy_time::Duration { critical_section::with(|cs| { let now = self.now() + 32; @@ -278,14 +294,8 @@ impl RtcDriver { } #[cfg(feature = "low-power")] - /// Pause the timer - pub(crate) fn pause_time(&self) { - T::regs_gp16().cr1().modify(|w| w.set_cen(false)); - } - - #[cfg(feature = "low-power")] - /// Resume the timer with the given offset - pub(crate) fn resume_time(&self, offset: embassy_time::Duration) { + /// Add the given offset to the current time + fn add_time(&self, offset: embassy_time::Duration) { let offset = offset.as_ticks(); let cnt = T::regs_gp16().cnt().read().cnt() as u32; let period = self.period.load(Ordering::SeqCst); @@ -315,6 +325,66 @@ impl RtcDriver { self.period.store(period, Ordering::SeqCst); T::regs_gp16().cnt().write(|w| w.set_cnt(cnt as u16)); + // Now, recompute all alarms + critical_section::with(|cs| { + for i in 0..ALARM_COUNT { + let alarm_handle = unsafe { AlarmHandle::new(i as u8) }; + let alarm = self.get_alarm(cs, alarm_handle); + + self.set_alarm(alarm_handle, alarm.timestamp.get()); + } + }) + } + + #[cfg(feature = "low-power")] + /// Stop the wakeup alarm, if enabled, and add the appropriate offset + fn stop_wakeup_alarm(&self) { + critical_section::with(|cs| { + if let Some(stop_time) = self.stop_time.borrow(cs).take() { + let current_time = self.rtc.borrow(cs).get().unwrap().stop_wakeup_alarm(); + self.add_time(current_time - stop_time); + } + }); + } + + #[cfg(feature = "low-power")] + /// Pause the timer if ready; return err if not + pub(crate) fn pause_time(&self) -> Result<(), ()> { + /* + If the wakeup timer is currently running, then we need to stop it and + add the elapsed time to the current time + */ + self.stop_wakeup_alarm(); + + let time_until_next_alarm = self.time_until_next_alarm(); + if time_until_next_alarm < embassy_time::Duration::from_millis(250) { + Err(()) + } else { + critical_section::with(|cs| { + assert!(self + .stop_time + .borrow(cs) + .replace(Some( + self.rtc + .borrow(cs) + .get() + .unwrap() + .start_wakeup_alarm(time_until_next_alarm) + )) + .is_none()); + }); + + T::regs_gp16().cr1().modify(|w| w.set_cen(false)); + + Ok(()) + } + } + + #[cfg(feature = "low-power")] + /// Resume the timer with the given offset + pub(crate) fn resume_time(&self) { + self.stop_wakeup_alarm(); + T::regs_gp16().cr1().modify(|w| w.set_cen(true)); } } @@ -388,21 +458,8 @@ impl Driver for RtcDriver { } #[cfg(feature = "low-power")] -/// Compute the approximate amount of time until the next alarm -pub(crate) fn time_until_next_alarm() -> embassy_time::Duration { - DRIVER.time_until_next_alarm() -} - -#[cfg(feature = "low-power")] -/// Pause the timer -pub(crate) fn pause_time() { - DRIVER.pause_time(); -} - -#[cfg(feature = "low-power")] -/// Resume the timer with the given offset -pub(crate) fn resume_time(offset: embassy_time::Duration) { - DRIVER.resume_time(offset); +pub(crate) fn get_driver() -> &'static RtcDriver { + &DRIVER } pub(crate) fn init() { From 1e430f74133acaeb31cb689ded3da77cb7b1c0ca Mon Sep 17 00:00:00 2001 From: xoviat Date: Sat, 26 Aug 2023 20:31:12 -0500 Subject: [PATCH 062/106] stm32: complete stop impl. --- embassy-stm32/src/low_power.rs | 48 ------------- embassy-stm32/src/rtc/mod.rs | 79 ++++++++++++++++++++ embassy-stm32/src/rtc/v2.rs | 119 ++++++------------------------- embassy-stm32/src/time_driver.rs | 25 ++----- 4 files changed, 107 insertions(+), 164 deletions(-) diff --git a/embassy-stm32/src/low_power.rs b/embassy-stm32/src/low_power.rs index 964819ab..42536216 100644 --- a/embassy-stm32/src/low_power.rs +++ b/embassy-stm32/src/low_power.rs @@ -66,9 +66,6 @@ pub struct Executor { not_send: PhantomData<*mut ()>, scb: SCB, time_driver: &'static RtcDriver, - stop_time: embassy_time::Duration, - next_alarm: embassy_time::Duration, - wfe: u8, } impl Executor { @@ -82,9 +79,6 @@ impl Executor { not_send: PhantomData, scb: cortex_m::Peripherals::steal().SCB, time_driver: get_driver(), - stop_time: Duration::from_ticks(0), - next_alarm: Duration::from_ticks(u64::MAX), - wfe: 0, }); EXECUTOR.as_mut().unwrap() @@ -94,50 +88,8 @@ impl Executor { unsafe fn on_wakeup_irq(&mut self) { trace!("low power: on wakeup irq"); - if crate::pac::RTC.isr().read().wutf() { - trace!("low power: wutf set"); - } else { - trace!("low power: wutf not set"); - } - self.time_driver.resume_time(); trace!("low power: resume time"); - - crate::interrupt::typelevel::RTC_WKUP::disable(); - - // cortex_m::asm::bkpt(); - - // let time_elasped = self.rtc.unwrap().stop_wakeup_alarm() - self.last_stop.take().unwrap(); - // - // trace!("low power: {} ms elapsed", time_elasped.as_millis()); - // - // resume_time(time_elasped); - // trace!("low power: resume time"); - // - // self.scb.clear_sleepdeep(); - - // cortex_m::asm::bkpt(); - // Self::get_scb().set_sleeponexit(); - // - // return; - // - // let elapsed = RTC_INSTANT.take().unwrap() - stop_wakeup_alarm(); - // - // STOP_TIME += elapsed; - // // let to_next = NEXT_ALARM - STOP_TIME; - // let to_next = Duration::from_secs(3); - // - // trace!("on wakeup irq: to next: {}", to_next); - // if to_next > THRESHOLD { - // trace!("start wakeup alarm"); - // RTC_INSTANT.replace(start_wakeup_alarm(to_next)); - // - // trace!("set sleeponexit"); - // Self::get_scb().set_sleeponexit(); - // } else { - // Self::get_scb().clear_sleeponexit(); - // Self::get_scb().clear_sleepdeep(); - // } } pub(self) fn stop_with_rtc(&mut self, rtc: &'static Rtc) { diff --git a/embassy-stm32/src/rtc/mod.rs b/embassy-stm32/src/rtc/mod.rs index a6102077..1f1abb78 100644 --- a/embassy-stm32/src/rtc/mod.rs +++ b/embassy-stm32/src/rtc/mod.rs @@ -1,6 +1,14 @@ //! RTC peripheral abstraction mod datetime; +#[cfg(feature = "low-power")] +use core::cell::Cell; + +#[cfg(feature = "low-power")] +use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; +#[cfg(feature = "low-power")] +use embassy_sync::blocking_mutex::Mutex; + pub use self::datetime::{DateTime, DayOfWeek, Error as DateTimeError}; /// refer to AN4759 to compare features of RTC2 and RTC3 @@ -30,9 +38,73 @@ pub enum RtcError { NotRunning, } +#[cfg(feature = "low-power")] +/// Represents an instant in time that can be substracted to compute a duration +struct RtcInstant { + second: u8, + subsecond: u16, +} + +#[cfg(feature = "low-power")] +impl RtcInstant { + pub fn now() -> Self { + let tr = RTC::regs().tr().read(); + let tr2 = RTC::regs().tr().read(); + let ssr = RTC::regs().ssr().read().ss(); + let ssr2 = RTC::regs().ssr().read().ss(); + + let st = bcd2_to_byte((tr.st(), tr.su())); + let st2 = bcd2_to_byte((tr2.st(), tr2.su())); + + assert!(st == st2); + assert!(ssr == ssr2); + + let _ = RTC::regs().dr().read(); + + let subsecond = ssr; + let second = st; + + // trace!("rtc: instant now: st, ssr: {}, {}", st, ssr); + + Self { second, subsecond } + } +} + +#[cfg(feature = "low-power")] +impl core::ops::Sub for RtcInstant { + type Output = embassy_time::Duration; + + fn sub(self, rhs: Self) -> Self::Output { + use embassy_time::{Duration, TICK_HZ}; + + let second = if self.second < rhs.second { + self.second + 60 + } else { + self.second + }; + + // TODO: read prescaler + + let self_ticks = second as u32 * 256 + (255 - self.subsecond as u32); + let other_ticks = rhs.second as u32 * 256 + (255 - rhs.subsecond as u32); + let rtc_ticks = self_ticks - other_ticks; + + // trace!( + // "rtc: instant sub: self, other, rtc ticks: {}, {}, {}", + // self_ticks, + // other_ticks, + // rtc_ticks + // ); + + Duration::from_ticks(((rtc_ticks * TICK_HZ as u32) / 256u32) as u64) + } +} + /// RTC Abstraction pub struct Rtc { rtc_config: RtcConfig, + #[cfg(feature = "low-power")] + stop_time: Mutex>>, } #[derive(Copy, Clone, Debug, PartialEq)] @@ -108,8 +180,15 @@ impl Rtc { pub fn new(_rtc: impl Peripheral

, rtc_config: RtcConfig) -> Self { RTC::enable_peripheral_clk(); + #[cfg(not(feature = "low-power"))] let mut rtc_struct = Self { rtc_config }; + #[cfg(feature = "low-power")] + let mut rtc_struct = Self { + rtc_config, + stop_time: Mutex::const_new(CriticalSectionRawMutex::new(), Cell::new(None)), + }; + Self::enable(); rtc_struct.configure(rtc_config); diff --git a/embassy-stm32/src/rtc/v2.rs b/embassy-stm32/src/rtc/v2.rs index 525dc45a..d73e7083 100644 --- a/embassy-stm32/src/rtc/v2.rs +++ b/embassy-stm32/src/rtc/v2.rs @@ -1,71 +1,12 @@ use stm32_metapac::rtc::vals::{Init, Osel, Pol}; +#[cfg(feature = "low-power")] +use super::RtcInstant; use super::{sealed, RtcClockSource, RtcConfig}; use crate::pac::rtc::Rtc; use crate::peripherals::RTC; use crate::rtc::sealed::Instance; -#[cfg(all(feature = "time", any(stm32wb, stm32f4)))] -pub struct RtcInstant { - ssr: u16, - st: u8, -} - -#[cfg(all(feature = "time", any(stm32wb, stm32f4)))] -impl RtcInstant { - pub fn now() -> Self { - // TODO: read value twice - use crate::rtc::bcd2_to_byte; - - let tr = RTC::regs().tr().read(); - let tr2 = RTC::regs().tr().read(); - let ssr = RTC::regs().ssr().read().ss(); - let ssr2 = RTC::regs().ssr().read().ss(); - - let st = bcd2_to_byte((tr.st(), tr.su())); - let st2 = bcd2_to_byte((tr2.st(), tr2.su())); - - assert!(st == st2); - assert!(ssr == ssr2); - - let _ = RTC::regs().dr().read(); - - trace!("rtc: instant now: st, ssr: {}, {}", st, ssr); - - Self { ssr, st } - } -} - -#[cfg(all(feature = "time", any(stm32wb, stm32f4)))] -impl core::ops::Sub for RtcInstant { - type Output = embassy_time::Duration; - - fn sub(self, rhs: Self) -> Self::Output { - use embassy_time::{Duration, TICK_HZ}; - - let st = if self.st < rhs.st { self.st + 60 } else { self.st }; - - // TODO: read prescaler - - let self_ticks = st as u32 * 256 + (255 - self.ssr as u32); - let other_ticks = rhs.st as u32 * 256 + (255 - rhs.ssr as u32); - let rtc_ticks = self_ticks - other_ticks; - - trace!( - "rtc: instant sub: self, other, rtc ticks: {}, {}, {}", - self_ticks, - other_ticks, - rtc_ticks - ); - - Duration::from_ticks( - ((((st as u32 * 256 + (255u32 - self.ssr as u32)) - (rhs.st as u32 * 256 + (255u32 - rhs.ssr as u32))) - * TICK_HZ as u32) as u32 - / 256u32) as u64, - ) - } -} - #[allow(dead_code)] #[derive(Clone, Copy, Debug)] pub(crate) enum WakeupPrescaler { @@ -165,16 +106,11 @@ impl super::Rtc { #[allow(dead_code)] #[cfg(all(feature = "time", any(stm32wb, stm32f4)))] - /// start the wakeup alarm and return the actual duration of the alarm - /// the actual duration will be the closest value possible that is less - /// than the requested duration. - /// - /// note: this api is exposed for testing purposes until low power is implemented. - /// it is not intended to be public - pub(crate) fn start_wakeup_alarm(&self, requested_duration: embassy_time::Duration) -> RtcInstant { + /// start the wakeup alarm and wtih a duration that is as close to but less than + /// the requested duration, and record the instant the wakeup alarm was started + pub(crate) fn start_wakeup_alarm(&self, requested_duration: embassy_time::Duration) { use embassy_time::{Duration, TICK_HZ}; - use crate::interrupt::typelevel::Interrupt; use crate::rcc::get_freqs; let rtc_hz = unsafe { get_freqs() }.rtc.unwrap().0 as u64; @@ -206,47 +142,34 @@ impl super::Rtc { trace!("rtc: start wakeup alarm for {} ms", duration.as_millis()); - // self.write(false, |regs| { - // regs.cr().modify(|w| w.set_wutie(false)); - // - // regs.isr().modify(|w| w.set_wutf(false)); - // - // regs.cr().modify(|w| w.set_wutie(true)); - // }); - // - // trace!("rtc: clear wuf..."); - // crate::pac::PWR.cr1().modify(|w| w.set_cwuf(true)); - // while crate::pac::PWR.csr1().read().wuf() {} - // trace!("rtc: clear wuf...done"); - // - // crate::pac::PWR - // .cr1() - // .modify(|w| w.set_pdds(crate::pac::pwr::vals::Pdds::STANDBY_MODE)); - // - // // crate::pac::PWR.cr1().modify(|w| w.set_lpds(true)); - // - // // crate::pac::EXTI.pr(0).modify(|w| w.set_line(22, true)); - // crate::interrupt::typelevel::RTC_WKUP::unpend(); - - RtcInstant::now() + critical_section::with(|cs| assert!(self.stop_time.borrow(cs).replace(Some(RtcInstant::now())).is_none())) } #[allow(dead_code)] #[cfg(all(feature = "time", any(stm32wb, stm32f4)))] - /// stop the wakeup alarm and return the time remaining - /// - /// note: this api is exposed for testing purposes until low power is implemented. - /// it is not intended to be public - pub(crate) fn stop_wakeup_alarm(&self) -> RtcInstant { + /// stop the wakeup alarm and return the time elapsed since `start_wakeup_alarm` + /// was called, otherwise none + pub(crate) fn stop_wakeup_alarm(&self) -> Option { + use crate::interrupt::typelevel::Interrupt; + trace!("rtc: stop wakeup alarm..."); self.write(false, |regs| { regs.cr().modify(|w| w.set_wutie(false)); regs.cr().modify(|w| w.set_wute(false)); regs.isr().modify(|w| w.set_wutf(false)); + + crate::pac::EXTI.pr(0).modify(|w| w.set_line(22, true)); + crate::interrupt::typelevel::RTC_WKUP::unpend(); }); - RtcInstant::now() + critical_section::with(|cs| { + if let Some(stop_time) = self.stop_time.borrow(cs).take() { + Some(RtcInstant::now() - stop_time) + } else { + None + } + }) } #[allow(dead_code)] diff --git a/embassy-stm32/src/time_driver.rs b/embassy-stm32/src/time_driver.rs index 56f42aa9..99d423d0 100644 --- a/embassy-stm32/src/time_driver.rs +++ b/embassy-stm32/src/time_driver.rs @@ -15,7 +15,7 @@ use crate::interrupt::typelevel::Interrupt; use crate::pac::timer::vals; use crate::rcc::sealed::RccPeripheral; #[cfg(feature = "low-power")] -use crate::rtc::{Rtc, RtcInstant}; +use crate::rtc::Rtc; use crate::timer::sealed::{Basic16bitInstance as BasicInstance, GeneralPurpose16bitInstance as Instance}; use crate::{interrupt, peripherals}; @@ -140,8 +140,6 @@ pub(crate) struct RtcDriver { alarms: Mutex, #[cfg(feature = "low-power")] rtc: Mutex>>, - #[cfg(feature = "low-power")] - stop_time: Mutex>>, } const ALARM_STATE_NEW: AlarmState = AlarmState::new(); @@ -152,8 +150,6 @@ embassy_time::time_driver_impl!(static DRIVER: RtcDriver = RtcDriver { alarms: Mutex::const_new(CriticalSectionRawMutex::new(), [ALARM_STATE_NEW; ALARM_COUNT]), #[cfg(feature = "low-power")] rtc: Mutex::const_new(CriticalSectionRawMutex::new(), Cell::new(None)), - #[cfg(feature = "low-power")] - stop_time: Mutex::const_new(CriticalSectionRawMutex::new(), Cell::new(None)), }); impl RtcDriver { @@ -340,9 +336,8 @@ impl RtcDriver { /// Stop the wakeup alarm, if enabled, and add the appropriate offset fn stop_wakeup_alarm(&self) { critical_section::with(|cs| { - if let Some(stop_time) = self.stop_time.borrow(cs).take() { - let current_time = self.rtc.borrow(cs).get().unwrap().stop_wakeup_alarm(); - self.add_time(current_time - stop_time); + if let Some(offset) = self.rtc.borrow(cs).get().unwrap().stop_wakeup_alarm() { + self.add_time(offset); } }); } @@ -361,17 +356,11 @@ impl RtcDriver { Err(()) } else { critical_section::with(|cs| { - assert!(self - .stop_time + self.rtc .borrow(cs) - .replace(Some( - self.rtc - .borrow(cs) - .get() - .unwrap() - .start_wakeup_alarm(time_until_next_alarm) - )) - .is_none()); + .get() + .unwrap() + .start_wakeup_alarm(time_until_next_alarm); }); T::regs_gp16().cr1().modify(|w| w.set_cen(false)); From db71887817e665c5c226e8775ad2d5814babac6e Mon Sep 17 00:00:00 2001 From: xoviat Date: Sat, 26 Aug 2023 20:37:01 -0500 Subject: [PATCH 063/106] tests/stm32: add stop and cleanpu --- embassy-stm32/src/low_power.rs | 1 - tests/stm32/Cargo.toml | 9 +++++- tests/stm32/src/bin/stop.rs | 53 ++++++++++++++++++++++++++++++++++ 3 files changed, 61 insertions(+), 2 deletions(-) create mode 100644 tests/stm32/src/bin/stop.rs diff --git a/embassy-stm32/src/low_power.rs b/embassy-stm32/src/low_power.rs index 42536216..65b93f8a 100644 --- a/embassy-stm32/src/low_power.rs +++ b/embassy-stm32/src/low_power.rs @@ -3,7 +3,6 @@ use core::marker::PhantomData; use cortex_m::peripheral::SCB; use embassy_executor::*; -use embassy_time::Duration; use crate::interrupt; use crate::interrupt::typelevel::Interrupt; diff --git a/tests/stm32/Cargo.toml b/tests/stm32/Cargo.toml index 754356cb..1f8c7373 100644 --- a/tests/stm32/Cargo.toml +++ b/tests/stm32/Cargo.toml @@ -7,7 +7,7 @@ autobins = false [features] stm32f103c8 = ["embassy-stm32/stm32f103c8", "not-gpdma"] # Blue Pill -stm32f429zi = ["embassy-stm32/stm32f429zi", "chrono", "can", "not-gpdma", "dac-adc-pin"] # Nucleo "sdmmc" +stm32f429zi = ["embassy-stm32/stm32f429zi", "chrono", "stop", "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 @@ -17,6 +17,7 @@ stm32h563zi = ["embassy-stm32/stm32h563zi"] # Nucleo stm32u585ai = ["embassy-stm32/stm32u585ai"] # IoT board sdmmc = [] +stop = ["embassy-stm32/low-power"] chrono = ["embassy-stm32/chrono", "dep:chrono"] can = [] ble = ["dep:embassy-stm32-wpan", "embassy-stm32-wpan/ble"] @@ -47,6 +48,7 @@ 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 } +static_cell = {version = "1.1", features = ["nightly"] } chrono = { version = "^0.4", default-features = false, optional = true} @@ -87,6 +89,11 @@ name = "spi_dma" path = "src/bin/spi_dma.rs" required-features = [] +[[bin]] +name = "stop" +path = "src/bin/stop.rs" +required-features = [ "stop", "chrono",] + [[bin]] name = "timer" path = "src/bin/timer.rs" diff --git a/tests/stm32/src/bin/stop.rs b/tests/stm32/src/bin/stop.rs new file mode 100644 index 00000000..4a49bde9 --- /dev/null +++ b/tests/stm32/src/bin/stop.rs @@ -0,0 +1,53 @@ +// required-features: stop,chrono + +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] +#[path = "../common.rs"] +mod common; + +use chrono::NaiveDate; +use common::*; +use cortex_m_rt::entry; +use embassy_executor::Spawner; +use embassy_stm32::low_power::{stop_with_rtc, Executor}; +use embassy_stm32::rtc::{Rtc, RtcClockSource, RtcConfig}; +use embassy_time::{Duration, Timer}; +use static_cell::make_static; + +#[entry] +fn main() -> ! { + let executor = Executor::take(); + executor.run(|spawner| { + unwrap!(spawner.spawn(async_main(spawner))); + }); +} + +#[embassy_executor::task] +async fn async_main(_spawner: Spawner) { + let mut config = config(); + + config.rcc.rtc = Some(RtcClockSource::LSI); + + let p = embassy_stm32::init(config); + info!("Hello World!"); + + let now = NaiveDate::from_ymd_opt(2020, 5, 15) + .unwrap() + .and_hms_opt(10, 30, 15) + .unwrap(); + + let mut rtc = Rtc::new(p.RTC, RtcConfig::default()); + + rtc.set_datetime(now.into()).expect("datetime not set"); + + let rtc = make_static!(rtc); + + stop_with_rtc(rtc); + + info!("Waiting 5 seconds"); + Timer::after(Duration::from_secs(5)).await; + + info!("Test OK"); + cortex_m::asm::bkpt(); +} From 94de1a53530d58cf6db38dffcf434ba19a576d40 Mon Sep 17 00:00:00 2001 From: xoviat Date: Sat, 26 Aug 2023 20:40:21 -0500 Subject: [PATCH 064/106] stm32: feature-gate wakeup alarm --- embassy-stm32/src/rtc/v2.rs | 21 ++------------------- 1 file changed, 2 insertions(+), 19 deletions(-) diff --git a/embassy-stm32/src/rtc/v2.rs b/embassy-stm32/src/rtc/v2.rs index d73e7083..bf926f98 100644 --- a/embassy-stm32/src/rtc/v2.rs +++ b/embassy-stm32/src/rtc/v2.rs @@ -89,23 +89,7 @@ impl super::Rtc { } } - // pub(crate) fn clear_wakeup_alarm(&self) { - // use crate::interrupt::typelevel::Interrupt; - // - // self.write(false, |regs| { - // regs.cr().modify(|w| w.set_wutie(false)); - // - // regs.isr().modify(|w| w.set_wutf(false)); - // crate::pac::PWR.cr1().modify(|w| w.set_cwuf(false)); - // crate::pac::EXTI.pr(0).modify(|w| w.set_line(22, false)); - // crate::interrupt::typelevel::RTC_WKUP::unpend(); - // - // regs.cr().modify(|w| w.set_wutie(true)); - // }); - // } - - #[allow(dead_code)] - #[cfg(all(feature = "time", any(stm32wb, stm32f4)))] + #[cfg(feature = "low-power")] /// start the wakeup alarm and wtih a duration that is as close to but less than /// the requested duration, and record the instant the wakeup alarm was started pub(crate) fn start_wakeup_alarm(&self, requested_duration: embassy_time::Duration) { @@ -145,8 +129,7 @@ impl super::Rtc { critical_section::with(|cs| assert!(self.stop_time.borrow(cs).replace(Some(RtcInstant::now())).is_none())) } - #[allow(dead_code)] - #[cfg(all(feature = "time", any(stm32wb, stm32f4)))] + #[cfg(feature = "low-power")] /// stop the wakeup alarm and return the time elapsed since `start_wakeup_alarm` /// was called, otherwise none pub(crate) fn stop_wakeup_alarm(&self) -> Option { From 59a5e84df584faed5676de027601d09772be55f7 Mon Sep 17 00:00:00 2001 From: aidant <15520814+aidant@users.noreply.github.com> Date: Sun, 27 Aug 2023 18:36:35 +1000 Subject: [PATCH 065/106] fix day of the week conversion --- embassy-stm32/src/rtc/datetime.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/embassy-stm32/src/rtc/datetime.rs b/embassy-stm32/src/rtc/datetime.rs index a9c48d88..3efe9be5 100644 --- a/embassy-stm32/src/rtc/datetime.rs +++ b/embassy-stm32/src/rtc/datetime.rs @@ -89,7 +89,7 @@ pub enum DayOfWeek { #[cfg(feature = "chrono")] impl From for DayOfWeek { fn from(weekday: Weekday) -> Self { - day_of_week_from_u8(weekday.number_from_monday() as u8).unwrap() + day_of_week_from_u8(weekday.num_days_from_monday() as u8).unwrap() } } From db6f9afa2e4b1da47a655a59c4f09a60a3a87a50 Mon Sep 17 00:00:00 2001 From: aidant <15520814+aidant@users.noreply.github.com> Date: Sun, 27 Aug 2023 18:37:10 +1000 Subject: [PATCH 066/106] fix hanging on rtc example --- examples/stm32f4/src/bin/rtc.rs | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/examples/stm32f4/src/bin/rtc.rs b/examples/stm32f4/src/bin/rtc.rs index 0eca5820..33c4ebfd 100644 --- a/examples/stm32f4/src/bin/rtc.rs +++ b/examples/stm32f4/src/bin/rtc.rs @@ -5,13 +5,19 @@ use chrono::{NaiveDate, NaiveDateTime}; use defmt::*; use embassy_executor::Spawner; -use embassy_stm32::rtc::{Rtc, RtcConfig}; +use embassy_stm32::{ + rtc::{Rtc, RtcClockSource, RtcConfig}, + Config, +}; use embassy_time::{Duration, Timer}; use {defmt_rtt as _, panic_probe as _}; #[embassy_executor::main] async fn main(_spawner: Spawner) { - let p = embassy_stm32::init(Default::default()); + let mut config = Config::default(); + config.rcc.rtc = Option::Some(RtcClockSource::LSI); + let p = embassy_stm32::init(config); + info!("Hello World!"); let now = NaiveDate::from_ymd_opt(2020, 5, 15) @@ -23,8 +29,11 @@ async fn main(_spawner: Spawner) { rtc.set_datetime(now.into()).expect("datetime not set"); - // In reality the delay would be much longer - Timer::after(Duration::from_millis(20000)).await; + loop { + let now: NaiveDateTime = rtc.now().unwrap().into(); - let _then: NaiveDateTime = rtc.now().unwrap().into(); + info!("{}", now.timestamp()); + + Timer::after(Duration::from_millis(1000)).await; + } } From 48085939e70f31832d8b130094e34633da4f3745 Mon Sep 17 00:00:00 2001 From: xoviat Date: Sun, 27 Aug 2023 08:35:13 -0500 Subject: [PATCH 067/106] stm32/rcc: rename common to bus --- embassy-stm32/src/rcc/{common.rs => bus.rs} | 0 embassy-stm32/src/rcc/c0.rs | 2 +- embassy-stm32/src/rcc/f2.rs | 4 ++-- embassy-stm32/src/rcc/f3.rs | 6 +++--- embassy-stm32/src/rcc/g0.rs | 2 +- embassy-stm32/src/rcc/g4.rs | 2 +- embassy-stm32/src/rcc/h5.rs | 2 +- embassy-stm32/src/rcc/h7.rs | 2 +- embassy-stm32/src/rcc/l0.rs | 2 +- embassy-stm32/src/rcc/l1.rs | 2 +- embassy-stm32/src/rcc/l4.rs | 2 +- embassy-stm32/src/rcc/l5.rs | 2 +- embassy-stm32/src/rcc/mod.rs | 2 +- embassy-stm32/src/rcc/u5.rs | 4 ++-- embassy-stm32/src/rcc/wb.rs | 2 +- embassy-stm32/src/rcc/wl.rs | 2 +- 16 files changed, 19 insertions(+), 19 deletions(-) rename embassy-stm32/src/rcc/{common.rs => bus.rs} (100%) diff --git a/embassy-stm32/src/rcc/common.rs b/embassy-stm32/src/rcc/bus.rs similarity index 100% rename from embassy-stm32/src/rcc/common.rs rename to embassy-stm32/src/rcc/bus.rs diff --git a/embassy-stm32/src/rcc/c0.rs b/embassy-stm32/src/rcc/c0.rs index 6a932634..d8579079 100644 --- a/embassy-stm32/src/rcc/c0.rs +++ b/embassy-stm32/src/rcc/c0.rs @@ -1,4 +1,4 @@ -pub use super::common::{AHBPrescaler, APBPrescaler}; +pub use super::bus::{AHBPrescaler, APBPrescaler}; use crate::pac::flash::vals::Latency; use crate::pac::rcc::vals::{Hsidiv, Ppre, Sw}; use crate::pac::{FLASH, RCC}; diff --git a/embassy-stm32/src/rcc/f2.rs b/embassy-stm32/src/rcc/f2.rs index ec4ed99b..9d9bc59f 100644 --- a/embassy-stm32/src/rcc/f2.rs +++ b/embassy-stm32/src/rcc/f2.rs @@ -1,7 +1,7 @@ use core::convert::TryFrom; use core::ops::{Div, Mul}; -pub use super::common::{AHBPrescaler, APBPrescaler}; +pub use super::bus::{AHBPrescaler, APBPrescaler}; use crate::pac::flash::vals::Latency; use crate::pac::rcc::vals::{Pllp, Pllsrc, Sw}; use crate::pac::{FLASH, RCC}; @@ -201,7 +201,7 @@ pub struct PLLClocks { pub pll48_freq: Hertz, } -pub use super::common::VoltageScale; +pub use super::bus::VoltageScale; impl VoltageScale { const fn wait_states(&self, ahb_freq: Hertz) -> Option { diff --git a/embassy-stm32/src/rcc/f3.rs b/embassy-stm32/src/rcc/f3.rs index 321270a7..7480c039 100644 --- a/embassy-stm32/src/rcc/f3.rs +++ b/embassy-stm32/src/rcc/f3.rs @@ -201,9 +201,9 @@ fn calc_pll(config: &Config, Hertz(sysclk): Hertz) -> (Hertz, PllConfig) { // Calculates the Multiplier and the Divisor to arrive at // the required System clock from PLL source frequency let get_mul_div = |sysclk, pllsrcclk| { - let common_div = gcd(sysclk, pllsrcclk); - let mut multiplier = sysclk / common_div; - let mut divisor = pllsrcclk / common_div; + let bus_div = gcd(sysclk, pllsrcclk); + let mut multiplier = sysclk / bus_div; + let mut divisor = pllsrcclk / bus_div; // Minimum PLL multiplier is two if multiplier == 1 { multiplier *= 2; diff --git a/embassy-stm32/src/rcc/g0.rs b/embassy-stm32/src/rcc/g0.rs index bf2d5199..7fdbcb00 100644 --- a/embassy-stm32/src/rcc/g0.rs +++ b/embassy-stm32/src/rcc/g0.rs @@ -1,4 +1,4 @@ -pub use super::common::{AHBPrescaler, APBPrescaler}; +pub use super::bus::{AHBPrescaler, APBPrescaler}; use crate::pac::flash::vals::Latency; use crate::pac::rcc::vals::{self, Hsidiv, Ppre, Sw}; use crate::pac::{FLASH, PWR, RCC}; diff --git a/embassy-stm32/src/rcc/g4.rs b/embassy-stm32/src/rcc/g4.rs index dff04023..3b044cd1 100644 --- a/embassy-stm32/src/rcc/g4.rs +++ b/embassy-stm32/src/rcc/g4.rs @@ -2,7 +2,7 @@ use stm32_metapac::flash::vals::Latency; use stm32_metapac::rcc::vals::{Hpre, Pllsrc, Ppre, Sw}; use stm32_metapac::FLASH; -pub use super::common::{AHBPrescaler, APBPrescaler}; +pub use super::bus::{AHBPrescaler, APBPrescaler}; use crate::pac::{PWR, RCC}; use crate::rcc::sealed::RccPeripheral; use crate::rcc::{set_freqs, Clocks}; diff --git a/embassy-stm32/src/rcc/h5.rs b/embassy-stm32/src/rcc/h5.rs index 2e72b193..5741cdf9 100644 --- a/embassy-stm32/src/rcc/h5.rs +++ b/embassy-stm32/src/rcc/h5.rs @@ -26,7 +26,7 @@ const VCO_MAX: u32 = 420_000_000; const VCO_WIDE_MIN: u32 = 128_000_000; const VCO_WIDE_MAX: u32 = 560_000_000; -pub use super::common::{AHBPrescaler, APBPrescaler, VoltageScale}; +pub use super::bus::{AHBPrescaler, APBPrescaler, VoltageScale}; pub enum HseMode { /// crystal/ceramic oscillator (HSEBYP=0) diff --git a/embassy-stm32/src/rcc/h7.rs b/embassy-stm32/src/rcc/h7.rs index 7fb4fb95..a6e69461 100644 --- a/embassy-stm32/src/rcc/h7.rs +++ b/embassy-stm32/src/rcc/h7.rs @@ -24,7 +24,7 @@ pub const HSI48_FREQ: Hertz = Hertz(48_000_000); /// LSI speed pub const LSI_FREQ: Hertz = Hertz(32_000); -pub use super::common::VoltageScale; +pub use super::bus::VoltageScale; #[derive(Clone, Copy)] pub enum AdcClockSource { diff --git a/embassy-stm32/src/rcc/l0.rs b/embassy-stm32/src/rcc/l0.rs index 46b58ca7..7f9ab01f 100644 --- a/embassy-stm32/src/rcc/l0.rs +++ b/embassy-stm32/src/rcc/l0.rs @@ -1,4 +1,4 @@ -pub use super::common::{AHBPrescaler, APBPrescaler}; +pub use super::bus::{AHBPrescaler, APBPrescaler}; use crate::pac::rcc::vals::{Hpre, Msirange, Plldiv, Pllmul, Pllsrc, Ppre, Sw}; use crate::pac::RCC; #[cfg(crs)] diff --git a/embassy-stm32/src/rcc/l1.rs b/embassy-stm32/src/rcc/l1.rs index bdfc5b87..ed949ea6 100644 --- a/embassy-stm32/src/rcc/l1.rs +++ b/embassy-stm32/src/rcc/l1.rs @@ -1,4 +1,4 @@ -pub use super::common::{AHBPrescaler, APBPrescaler}; +pub use super::bus::{AHBPrescaler, APBPrescaler}; use crate::pac::rcc::vals::{Hpre, Msirange, Plldiv, Pllmul, Pllsrc, Ppre, Sw}; use crate::pac::{FLASH, RCC}; use crate::rcc::{set_freqs, Clocks}; diff --git a/embassy-stm32/src/rcc/l4.rs b/embassy-stm32/src/rcc/l4.rs index b34b8caa..4c4b4bfd 100644 --- a/embassy-stm32/src/rcc/l4.rs +++ b/embassy-stm32/src/rcc/l4.rs @@ -4,7 +4,7 @@ use embassy_hal_internal::into_ref; use stm32_metapac::rcc::regs::Cfgr; use stm32_metapac::rcc::vals::{Lsedrv, Mcopre, Mcosel}; -pub use super::common::{AHBPrescaler, APBPrescaler}; +pub use super::bus::{AHBPrescaler, APBPrescaler}; use crate::gpio::sealed::AFType; use crate::gpio::Speed; use crate::pac::rcc::vals::{Hpre, Msirange, Pllsrc, Ppre, Sw}; diff --git a/embassy-stm32/src/rcc/l5.rs b/embassy-stm32/src/rcc/l5.rs index a85e1488..9e4e0fc7 100644 --- a/embassy-stm32/src/rcc/l5.rs +++ b/embassy-stm32/src/rcc/l5.rs @@ -1,6 +1,6 @@ use stm32_metapac::PWR; -pub use super::common::{AHBPrescaler, APBPrescaler}; +pub use super::bus::{AHBPrescaler, APBPrescaler}; use crate::pac::rcc::vals::{Hpre, Msirange, Pllsrc, Ppre, Sw}; use crate::pac::{FLASH, RCC}; use crate::rcc::{set_freqs, Clocks}; diff --git a/embassy-stm32/src/rcc/mod.rs b/embassy-stm32/src/rcc/mod.rs index 45a4d880..f9ac88d9 100644 --- a/embassy-stm32/src/rcc/mod.rs +++ b/embassy-stm32/src/rcc/mod.rs @@ -1,6 +1,6 @@ #![macro_use] -pub mod common; +pub mod bus; use core::mem::MaybeUninit; diff --git a/embassy-stm32/src/rcc/u5.rs b/embassy-stm32/src/rcc/u5.rs index b5feeb0c..4aca9cd3 100644 --- a/embassy-stm32/src/rcc/u5.rs +++ b/embassy-stm32/src/rcc/u5.rs @@ -1,6 +1,6 @@ use stm32_metapac::rcc::vals::{Msirange, Msirgsel, Pllm, Pllsrc, Sw}; -pub use super::common::{AHBPrescaler, APBPrescaler}; +pub use super::bus::{AHBPrescaler, APBPrescaler}; use crate::pac::{FLASH, RCC}; use crate::rcc::{set_freqs, Clocks}; use crate::time::Hertz; @@ -11,7 +11,7 @@ pub const HSI_FREQ: Hertz = Hertz(16_000_000); /// LSI speed pub const LSI_FREQ: Hertz = Hertz(32_000); -pub use super::common::VoltageScale; +pub use super::bus::VoltageScale; #[derive(Copy, Clone)] pub enum ClockSrc { diff --git a/embassy-stm32/src/rcc/wb.rs b/embassy-stm32/src/rcc/wb.rs index ae708b37..653d4d59 100644 --- a/embassy-stm32/src/rcc/wb.rs +++ b/embassy-stm32/src/rcc/wb.rs @@ -1,4 +1,4 @@ -pub use super::common::{AHBPrescaler, APBPrescaler}; +pub use super::bus::{AHBPrescaler, APBPrescaler}; use crate::rcc::Clocks; use crate::rtc::{Rtc, RtcClockSource}; use crate::time::{khz, mhz, Hertz}; diff --git a/embassy-stm32/src/rcc/wl.rs b/embassy-stm32/src/rcc/wl.rs index f1dd2bd7..29f50dc6 100644 --- a/embassy-stm32/src/rcc/wl.rs +++ b/embassy-stm32/src/rcc/wl.rs @@ -1,4 +1,4 @@ -pub use super::common::{AHBPrescaler, APBPrescaler, VoltageScale}; +pub use super::bus::{AHBPrescaler, APBPrescaler, VoltageScale}; use crate::pac::pwr::vals::Dbp; use crate::pac::{FLASH, PWR, RCC}; use crate::rcc::{set_freqs, Clocks}; From 4caa8497fcac5099d9e885683542aca6b4f0911e Mon Sep 17 00:00:00 2001 From: xoviat Date: Sun, 27 Aug 2023 09:07:34 -0500 Subject: [PATCH 068/106] stm32: extract backupdomain into mod --- embassy-stm32/src/rcc/bd.rs | 168 +++++++++++++++++++++++++++++++++++ embassy-stm32/src/rcc/f4.rs | 4 +- embassy-stm32/src/rcc/l4.rs | 6 +- embassy-stm32/src/rcc/mod.rs | 1 + embassy-stm32/src/rcc/wb.rs | 6 +- embassy-stm32/src/rcc/wl.rs | 6 +- embassy-stm32/src/rtc/mod.rs | 16 +--- embassy-stm32/src/rtc/v2.rs | 81 +---------------- embassy-stm32/src/rtc/v3.rs | 65 +------------- 9 files changed, 185 insertions(+), 168 deletions(-) create mode 100644 embassy-stm32/src/rcc/bd.rs diff --git a/embassy-stm32/src/rcc/bd.rs b/embassy-stm32/src/rcc/bd.rs new file mode 100644 index 00000000..e0973769 --- /dev/null +++ b/embassy-stm32/src/rcc/bd.rs @@ -0,0 +1,168 @@ +#[derive(Copy, Clone, Debug, PartialEq)] +#[repr(u8)] +pub enum RtcClockSource { + /// 00: No clock + NoClock = 0b00, + /// 01: LSE oscillator clock used as RTC clock + LSE = 0b01, + /// 10: LSI oscillator clock used as RTC clock + LSI = 0b10, + /// 11: HSE oscillator clock divided by 32 used as RTC clock + HSE = 0b11, +} + +pub struct BackupDomain {} + +impl BackupDomain { + #[cfg(any( + rtc_v2f0, rtc_v2f2, rtc_v2f3, rtc_v2f4, rtc_v2f7, rtc_v2h7, rtc_v2l0, rtc_v2l1, rtc_v2l4, rtc_v2wb + ))] + fn unlock_registers() { + #[cfg(any(rtc_v2f2, rtc_v2f3, rtc_v2l1))] + let cr = crate::pac::PWR.cr(); + #[cfg(any(rtc_v2f4, rtc_v2f7, rtc_v2h7, rtc_v2l4, rtc_v2wb))] + let cr = crate::pac::PWR.cr1(); + + // TODO: Missing from PAC for l0 and f0? + #[cfg(not(any(rtc_v2f0, rtc_v2l0)))] + { + if !cr.read().dbp() { + cr.modify(|w| w.set_dbp(true)); + while !cr.read().dbp() {} + } + } + } + + #[cfg(any(rtc_v3, rtc_v3u5))] + fn unlock_registers() { + // Unlock the backup domain + #[cfg(not(any(rtc_v3u5, rcc_wl5, rcc_wle)))] + { + if !crate::pac::PWR.cr1().read().dbp() { + crate::pac::PWR.cr1().modify(|w| w.set_dbp(true)); + while !crate::pac::PWR.cr1().read().dbp() {} + } + } + #[cfg(any(rcc_wl5, rcc_wle))] + { + use crate::pac::pwr::vals::Dbp; + + if crate::pac::PWR.cr1().read().dbp() != Dbp::ENABLED { + crate::pac::PWR.cr1().modify(|w| w.set_dbp(Dbp::ENABLED)); + while crate::pac::PWR.cr1().read().dbp() != Dbp::ENABLED {} + } + } + } + + #[cfg(any( + rtc_v2f0, rtc_v2f2, rtc_v2f3, rtc_v2f4, rtc_v2f7, rtc_v2h7, rtc_v2l0, rtc_v2l1, rtc_v2l4, rtc_v2wb + ))] + pub fn set_rtc_clock_source(clock_source: RtcClockSource) { + #[cfg(not(rtc_v2wb))] + use stm32_metapac::rcc::vals::Rtcsel; + + #[cfg(not(any(rtc_v2l0, rtc_v2l1)))] + let cr = crate::pac::RCC.bdcr(); + #[cfg(any(rtc_v2l0, rtc_v2l1))] + let cr = crate::pac::RCC.csr(); + + Self::unlock_registers(); + + cr.modify(|w| { + // Select RTC source + #[cfg(not(rtc_v2wb))] + w.set_rtcsel(Rtcsel::from_bits(clock_source as u8)); + #[cfg(rtc_v2wb)] + w.set_rtcsel(clock_source as u8); + }); + } + + #[cfg(any(rtc_v3, rtc_v3u5))] + pub fn set_rtc_clock_source(clock_source: RtcClockSource) { + let clock_source = clock_source as u8; + #[cfg(not(any(rcc_wl5, rcc_wle)))] + let clock_source = crate::pac::rcc::vals::Rtcsel::from_bits(clock_source); + + Self::unlock_registers(); + + crate::pac::RCC.bdcr().modify(|w| { + // Select RTC source + w.set_rtcsel(clock_source); + }); + } + + #[cfg(any( + rtc_v2f0, rtc_v2f2, rtc_v2f3, rtc_v2f4, rtc_v2f7, rtc_v2h7, rtc_v2l0, rtc_v2l1, rtc_v2l4, rtc_v2wb + ))] + pub fn enable_rtc() { + #[cfg(not(any(rtc_v2l0, rtc_v2l1)))] + let reg = crate::pac::RCC.bdcr().read(); + #[cfg(any(rtc_v2l0, rtc_v2l1))] + let reg = crate::pac::RCC.csr().read(); + + #[cfg(any(rtc_v2h7, rtc_v2l4, rtc_v2wb))] + assert!(!reg.lsecsson(), "RTC is not compatible with LSE CSS, yet."); + + if !reg.rtcen() { + Self::unlock_registers(); + + #[cfg(not(any(rtc_v2l0, rtc_v2l1, rtc_v2f2)))] + crate::pac::RCC.bdcr().modify(|w| w.set_bdrst(true)); + #[cfg(not(any(rtc_v2l0, rtc_v2l1)))] + let cr = crate::pac::RCC.bdcr(); + #[cfg(any(rtc_v2l0, rtc_v2l1))] + let cr = crate::pac::RCC.csr(); + + cr.modify(|w| { + // Reset + #[cfg(not(any(rtc_v2l0, rtc_v2l1)))] + w.set_bdrst(false); + + w.set_rtcen(true); + w.set_rtcsel(reg.rtcsel()); + + // Restore bcdr + #[cfg(any(rtc_v2l4, rtc_v2wb))] + w.set_lscosel(reg.lscosel()); + #[cfg(any(rtc_v2l4, rtc_v2wb))] + w.set_lscoen(reg.lscoen()); + + w.set_lseon(reg.lseon()); + + #[cfg(any(rtc_v2f0, rtc_v2f7, rtc_v2h7, rtc_v2l4, rtc_v2wb))] + w.set_lsedrv(reg.lsedrv()); + w.set_lsebyp(reg.lsebyp()); + }); + } + } + + #[cfg(any(rtc_v3, rtc_v3u5))] + pub fn enable_rtc() { + let bdcr = crate::pac::RCC.bdcr(); + + let reg = bdcr.read(); + assert!(!reg.lsecsson(), "RTC is not compatible with LSE CSS, yet."); + + if !reg.rtcen() { + Self::unlock_registers(); + + bdcr.modify(|w| w.set_bdrst(true)); + + bdcr.modify(|w| { + // Reset + w.set_bdrst(false); + + w.set_rtcen(true); + w.set_rtcsel(reg.rtcsel()); + + // Restore bcdr + w.set_lscosel(reg.lscosel()); + w.set_lscoen(reg.lscoen()); + + w.set_lseon(reg.lseon()); + w.set_lsedrv(reg.lsedrv()); + w.set_lsebyp(reg.lsebyp()); + }); + } + } +} diff --git a/embassy-stm32/src/rcc/f4.rs b/embassy-stm32/src/rcc/f4.rs index ee9cb289..10d3322a 100644 --- a/embassy-stm32/src/rcc/f4.rs +++ b/embassy-stm32/src/rcc/f4.rs @@ -8,8 +8,8 @@ use crate::gpio::sealed::AFType; use crate::gpio::Speed; use crate::pac::rcc::vals::{Hpre, Ppre, Sw}; use crate::pac::{FLASH, PWR, RCC}; +use crate::rcc::bd::{BackupDomain, RtcClockSource}; use crate::rcc::{set_freqs, Clocks}; -use crate::rtc::{Rtc, RtcClockSource}; use crate::time::Hertz; use crate::{peripherals, Peripheral}; @@ -470,7 +470,7 @@ pub(crate) unsafe fn init(config: Config) { } config.rtc.map(|clock_source| { - Rtc::set_clock_source(clock_source); + BackupDomain::set_rtc_clock_source(clock_source); }); let rtc = match config.rtc { diff --git a/embassy-stm32/src/rcc/l4.rs b/embassy-stm32/src/rcc/l4.rs index 4c4b4bfd..1f02254b 100644 --- a/embassy-stm32/src/rcc/l4.rs +++ b/embassy-stm32/src/rcc/l4.rs @@ -9,8 +9,8 @@ use crate::gpio::sealed::AFType; use crate::gpio::Speed; use crate::pac::rcc::vals::{Hpre, Msirange, Pllsrc, Ppre, Sw}; use crate::pac::{FLASH, PWR, RCC}; +use crate::rcc::bd::{BackupDomain, RtcClockSource as RCS}; use crate::rcc::{set_freqs, Clocks}; -use crate::rtc::{Rtc, RtcClockSource as RCS}; use crate::time::Hertz; use crate::{peripherals, Peripheral}; @@ -429,7 +429,7 @@ pub(crate) unsafe fn init(config: Config) { // Wait until LSE is running while !RCC.bdcr().read().lserdy() {} - Rtc::set_clock_source(RCS::LSE); + BackupDomain::set_rtc_clock_source(RCS::LSE); } RtcClockSource::LSI32 => { // Turn on the internal 32 kHz LSI oscillator @@ -438,7 +438,7 @@ pub(crate) unsafe fn init(config: Config) { // Wait until LSI is running while !RCC.csr().read().lsirdy() {} - Rtc::set_clock_source(RCS::LSI); + BackupDomain::set_rtc_clock_source(RCS::LSI); } } diff --git a/embassy-stm32/src/rcc/mod.rs b/embassy-stm32/src/rcc/mod.rs index f9ac88d9..7b68495b 100644 --- a/embassy-stm32/src/rcc/mod.rs +++ b/embassy-stm32/src/rcc/mod.rs @@ -1,5 +1,6 @@ #![macro_use] +pub(crate) mod bd; pub mod bus; use core::mem::MaybeUninit; diff --git a/embassy-stm32/src/rcc/wb.rs b/embassy-stm32/src/rcc/wb.rs index 653d4d59..6a3eab70 100644 --- a/embassy-stm32/src/rcc/wb.rs +++ b/embassy-stm32/src/rcc/wb.rs @@ -1,6 +1,6 @@ pub use super::bus::{AHBPrescaler, APBPrescaler}; +use crate::rcc::bd::{BackupDomain, RtcClockSource}; use crate::rcc::Clocks; -use crate::rtc::{Rtc, RtcClockSource}; use crate::time::{khz, mhz, Hertz}; /// Most of clock setup is copied from stm32l0xx-hal, and adopted to the generated PAC, @@ -375,5 +375,7 @@ pub(crate) fn configure_clocks(config: &Config) { w.set_shdhpre(config.ahb3_pre.into()); }); - config.rtc.map(|clock_source| Rtc::set_clock_source(clock_source)); + config + .rtc + .map(|clock_source| BackupDomain::set_rtc_clock_source(clock_source)); } diff --git a/embassy-stm32/src/rcc/wl.rs b/embassy-stm32/src/rcc/wl.rs index 29f50dc6..8a9b24c9 100644 --- a/embassy-stm32/src/rcc/wl.rs +++ b/embassy-stm32/src/rcc/wl.rs @@ -1,8 +1,8 @@ pub use super::bus::{AHBPrescaler, APBPrescaler, VoltageScale}; use crate::pac::pwr::vals::Dbp; use crate::pac::{FLASH, PWR, RCC}; +use crate::rcc::bd::{BackupDomain, RtcClockSource as RCS}; use crate::rcc::{set_freqs, Clocks}; -use crate::rtc::{Rtc, RtcClockSource as RCS}; use crate::time::Hertz; /// Most of clock setup is copied from stm32l0xx-hal, and adopted to the generated PAC, @@ -231,7 +231,7 @@ pub(crate) unsafe fn init(config: Config) { // Wait until LSE is running while !RCC.bdcr().read().lserdy() {} - Rtc::set_clock_source(RCS::LSE); + BackupDomain::set_rtc_clock_source(RCS::LSE); } RtcClockSource::LSI32 => { // Turn on the internal 32 kHz LSI oscillator @@ -240,7 +240,7 @@ pub(crate) unsafe fn init(config: Config) { // Wait until LSI is running while !RCC.csr().read().lsirdy() {} - Rtc::set_clock_source(RCS::LSI); + BackupDomain::set_rtc_clock_source(RCS::LSI); } } diff --git a/embassy-stm32/src/rtc/mod.rs b/embassy-stm32/src/rtc/mod.rs index 1f1abb78..0f915951 100644 --- a/embassy-stm32/src/rtc/mod.rs +++ b/embassy-stm32/src/rtc/mod.rs @@ -10,6 +10,7 @@ use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; use embassy_sync::blocking_mutex::Mutex; pub use self::datetime::{DateTime, DayOfWeek, Error as DateTimeError}; +use crate::rcc::bd::BackupDomain; /// refer to AN4759 to compare features of RTC2 and RTC3 #[cfg_attr(any(rtc_v1), path = "v1.rs")] @@ -107,19 +108,6 @@ pub struct Rtc { stop_time: Mutex>>, } -#[derive(Copy, Clone, Debug, PartialEq)] -#[repr(u8)] -pub enum RtcClockSource { - /// 00: No clock - NoClock = 0b00, - /// 01: LSE oscillator clock used as RTC clock - LSE = 0b01, - /// 10: LSI oscillator clock used as RTC clock - LSI = 0b10, - /// 11: HSE oscillator clock divided by 32 used as RTC clock - HSE = 0b11, -} - #[derive(Copy, Clone, PartialEq)] pub struct RtcConfig { /// Asynchronous prescaler factor @@ -189,7 +177,7 @@ impl Rtc { stop_time: Mutex::const_new(CriticalSectionRawMutex::new(), Cell::new(None)), }; - Self::enable(); + BackupDomain::enable_rtc(); rtc_struct.configure(rtc_config); rtc_struct.rtc_config = rtc_config; diff --git a/embassy-stm32/src/rtc/v2.rs b/embassy-stm32/src/rtc/v2.rs index bf926f98..1e0ca9b4 100644 --- a/embassy-stm32/src/rtc/v2.rs +++ b/embassy-stm32/src/rtc/v2.rs @@ -2,7 +2,7 @@ use stm32_metapac::rtc::vals::{Init, Osel, Pol}; #[cfg(feature = "low-power")] use super::RtcInstant; -use super::{sealed, RtcClockSource, RtcConfig}; +use super::{sealed, RtcConfig}; use crate::pac::rtc::Rtc; use crate::peripherals::RTC; use crate::rtc::sealed::Instance; @@ -73,22 +73,6 @@ impl WakeupPrescaler { } impl super::Rtc { - fn unlock_registers() { - #[cfg(any(rtc_v2f2, rtc_v2f3, rtc_v2l1))] - let cr = crate::pac::PWR.cr(); - #[cfg(any(rtc_v2f4, rtc_v2f7, rtc_v2h7, rtc_v2l4, rtc_v2wb))] - let cr = crate::pac::PWR.cr1(); - - // TODO: Missing from PAC for l0 and f0? - #[cfg(not(any(rtc_v2f0, rtc_v2l0)))] - { - if !cr.read().dbp() { - cr.modify(|w| w.set_dbp(true)); - while !cr.read().dbp() {} - } - } - } - #[cfg(feature = "low-power")] /// start the wakeup alarm and wtih a duration that is as close to but less than /// the requested duration, and record the instant the wakeup alarm was started @@ -155,69 +139,6 @@ impl super::Rtc { }) } - #[allow(dead_code)] - pub(crate) fn set_clock_source(clock_source: RtcClockSource) { - #[cfg(not(rtc_v2wb))] - use stm32_metapac::rcc::vals::Rtcsel; - - #[cfg(not(any(rtc_v2l0, rtc_v2l1)))] - let cr = crate::pac::RCC.bdcr(); - #[cfg(any(rtc_v2l0, rtc_v2l1))] - let cr = crate::pac::RCC.csr(); - - Self::unlock_registers(); - - cr.modify(|w| { - // Select RTC source - #[cfg(not(rtc_v2wb))] - w.set_rtcsel(Rtcsel::from_bits(clock_source as u8)); - #[cfg(rtc_v2wb)] - w.set_rtcsel(clock_source as u8); - }); - } - - pub(super) fn enable() { - #[cfg(not(any(rtc_v2l0, rtc_v2l1)))] - let reg = crate::pac::RCC.bdcr().read(); - #[cfg(any(rtc_v2l0, rtc_v2l1))] - let reg = crate::pac::RCC.csr().read(); - - #[cfg(any(rtc_v2h7, rtc_v2l4, rtc_v2wb))] - assert!(!reg.lsecsson(), "RTC is not compatible with LSE CSS, yet."); - - if !reg.rtcen() { - Self::unlock_registers(); - - #[cfg(not(any(rtc_v2l0, rtc_v2l1, rtc_v2f2)))] - crate::pac::RCC.bdcr().modify(|w| w.set_bdrst(true)); - #[cfg(not(any(rtc_v2l0, rtc_v2l1)))] - let cr = crate::pac::RCC.bdcr(); - #[cfg(any(rtc_v2l0, rtc_v2l1))] - let cr = crate::pac::RCC.csr(); - - cr.modify(|w| { - // Reset - #[cfg(not(any(rtc_v2l0, rtc_v2l1)))] - w.set_bdrst(false); - - w.set_rtcen(true); - w.set_rtcsel(reg.rtcsel()); - - // Restore bcdr - #[cfg(any(rtc_v2l4, rtc_v2wb))] - w.set_lscosel(reg.lscosel()); - #[cfg(any(rtc_v2l4, rtc_v2wb))] - w.set_lscoen(reg.lscoen()); - - w.set_lseon(reg.lseon()); - - #[cfg(any(rtc_v2f0, rtc_v2f7, rtc_v2h7, rtc_v2l4, rtc_v2wb))] - w.set_lsedrv(reg.lsedrv()); - w.set_lsebyp(reg.lsebyp()); - }); - } - } - /// Applies the RTC config /// It this changes the RTC clock source the time will be reset pub(super) fn configure(&mut self, rtc_config: RtcConfig) { diff --git a/embassy-stm32/src/rtc/v3.rs b/embassy-stm32/src/rtc/v3.rs index 3297303e..12952b15 100644 --- a/embassy-stm32/src/rtc/v3.rs +++ b/embassy-stm32/src/rtc/v3.rs @@ -1,74 +1,11 @@ use stm32_metapac::rtc::vals::{Calp, Calw16, Calw8, Fmt, Init, Key, Osel, Pol, TampalrmPu, TampalrmType}; -use super::{sealed, RtcCalibrationCyclePeriod, RtcClockSource, RtcConfig}; +use super::{sealed, RtcCalibrationCyclePeriod, RtcConfig}; use crate::pac::rtc::Rtc; use crate::peripherals::RTC; use crate::rtc::sealed::Instance; impl super::Rtc { - fn unlock_registers() { - // Unlock the backup domain - #[cfg(not(any(rtc_v3u5, rcc_wl5, rcc_wle)))] - { - if !crate::pac::PWR.cr1().read().dbp() { - crate::pac::PWR.cr1().modify(|w| w.set_dbp(true)); - while !crate::pac::PWR.cr1().read().dbp() {} - } - } - #[cfg(any(rcc_wl5, rcc_wle))] - { - use crate::pac::pwr::vals::Dbp; - - if crate::pac::PWR.cr1().read().dbp() != Dbp::ENABLED { - crate::pac::PWR.cr1().modify(|w| w.set_dbp(Dbp::ENABLED)); - while crate::pac::PWR.cr1().read().dbp() != Dbp::ENABLED {} - } - } - } - - #[allow(dead_code)] - pub(crate) fn set_clock_source(clock_source: RtcClockSource) { - let clock_source = clock_source as u8; - #[cfg(not(any(rcc_wl5, rcc_wle)))] - let clock_source = crate::pac::rcc::vals::Rtcsel::from_bits(clock_source); - - Self::unlock_registers(); - - crate::pac::RCC.bdcr().modify(|w| { - // Select RTC source - w.set_rtcsel(clock_source); - }); - } - - pub(super) fn enable() { - let bdcr = crate::pac::RCC.bdcr(); - - let reg = bdcr.read(); - assert!(!reg.lsecsson(), "RTC is not compatible with LSE CSS, yet."); - - if !reg.rtcen() { - Self::unlock_registers(); - - bdcr.modify(|w| w.set_bdrst(true)); - - bdcr.modify(|w| { - // Reset - w.set_bdrst(false); - - w.set_rtcen(true); - w.set_rtcsel(reg.rtcsel()); - - // Restore bcdr - w.set_lscosel(reg.lscosel()); - w.set_lscoen(reg.lscoen()); - - w.set_lseon(reg.lseon()); - w.set_lsedrv(reg.lsedrv()); - w.set_lsebyp(reg.lsebyp()); - }); - } - } - /// Applies the RTC config /// It this changes the RTC clock source the time will be reset pub(super) fn configure(&mut self, rtc_config: RtcConfig) { From 10ea06802761a7aa6feb0241ebdbbe9bbaf37a7f Mon Sep 17 00:00:00 2001 From: xoviat Date: Sun, 27 Aug 2023 09:12:04 -0500 Subject: [PATCH 069/106] stm32/bd: allow dead code --- embassy-stm32/src/rcc/bd.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/embassy-stm32/src/rcc/bd.rs b/embassy-stm32/src/rcc/bd.rs index e0973769..fd1b8d45 100644 --- a/embassy-stm32/src/rcc/bd.rs +++ b/embassy-stm32/src/rcc/bd.rs @@ -1,5 +1,6 @@ #[derive(Copy, Clone, Debug, PartialEq)] #[repr(u8)] +#[allow(dead_code)] pub enum RtcClockSource { /// 00: No clock NoClock = 0b00, @@ -11,12 +12,14 @@ pub enum RtcClockSource { HSE = 0b11, } +#[allow(dead_code)] pub struct BackupDomain {} impl BackupDomain { #[cfg(any( rtc_v2f0, rtc_v2f2, rtc_v2f3, rtc_v2f4, rtc_v2f7, rtc_v2h7, rtc_v2l0, rtc_v2l1, rtc_v2l4, rtc_v2wb ))] + #[allow(dead_code)] fn unlock_registers() { #[cfg(any(rtc_v2f2, rtc_v2f3, rtc_v2l1))] let cr = crate::pac::PWR.cr(); @@ -34,6 +37,7 @@ impl BackupDomain { } #[cfg(any(rtc_v3, rtc_v3u5))] + #[allow(dead_code)] fn unlock_registers() { // Unlock the backup domain #[cfg(not(any(rtc_v3u5, rcc_wl5, rcc_wle)))] @@ -57,6 +61,7 @@ impl BackupDomain { #[cfg(any( rtc_v2f0, rtc_v2f2, rtc_v2f3, rtc_v2f4, rtc_v2f7, rtc_v2h7, rtc_v2l0, rtc_v2l1, rtc_v2l4, rtc_v2wb ))] + #[allow(dead_code)] pub fn set_rtc_clock_source(clock_source: RtcClockSource) { #[cfg(not(rtc_v2wb))] use stm32_metapac::rcc::vals::Rtcsel; @@ -78,6 +83,7 @@ impl BackupDomain { } #[cfg(any(rtc_v3, rtc_v3u5))] + #[allow(dead_code)] pub fn set_rtc_clock_source(clock_source: RtcClockSource) { let clock_source = clock_source as u8; #[cfg(not(any(rcc_wl5, rcc_wle)))] @@ -94,6 +100,7 @@ impl BackupDomain { #[cfg(any( rtc_v2f0, rtc_v2f2, rtc_v2f3, rtc_v2f4, rtc_v2f7, rtc_v2h7, rtc_v2l0, rtc_v2l1, rtc_v2l4, rtc_v2wb ))] + #[allow(dead_code)] pub fn enable_rtc() { #[cfg(not(any(rtc_v2l0, rtc_v2l1)))] let reg = crate::pac::RCC.bdcr().read(); @@ -137,6 +144,7 @@ impl BackupDomain { } #[cfg(any(rtc_v3, rtc_v3u5))] + #[allow(dead_code)] pub fn enable_rtc() { let bdcr = crate::pac::RCC.bdcr(); From fb942e6675097540b6ca3f5fa37e0696337c2fc0 Mon Sep 17 00:00:00 2001 From: xoviat Date: Sun, 27 Aug 2023 09:25:14 -0500 Subject: [PATCH 070/106] stm32: re-export rtcclocksource --- embassy-stm32/src/rcc/mod.rs | 2 +- embassy-stm32/src/rtc/mod.rs | 1 + tests/stm32/src/bin/rtc.rs | 3 ++- tests/stm32/src/bin/stop.rs | 3 ++- 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/embassy-stm32/src/rcc/mod.rs b/embassy-stm32/src/rcc/mod.rs index 7b68495b..9f1b3b66 100644 --- a/embassy-stm32/src/rcc/mod.rs +++ b/embassy-stm32/src/rcc/mod.rs @@ -2,9 +2,9 @@ pub(crate) mod bd; pub mod bus; - use core::mem::MaybeUninit; +pub use crate::rcc::bd::RtcClockSource; use crate::time::Hertz; #[cfg_attr(rcc_f0, path = "f0.rs")] diff --git a/embassy-stm32/src/rtc/mod.rs b/embassy-stm32/src/rtc/mod.rs index 0f915951..c408b2d6 100644 --- a/embassy-stm32/src/rtc/mod.rs +++ b/embassy-stm32/src/rtc/mod.rs @@ -11,6 +11,7 @@ use embassy_sync::blocking_mutex::Mutex; pub use self::datetime::{DateTime, DayOfWeek, Error as DateTimeError}; use crate::rcc::bd::BackupDomain; +pub use crate::rcc::RtcClockSource; /// refer to AN4759 to compare features of RTC2 and RTC3 #[cfg_attr(any(rtc_v1), path = "v1.rs")] diff --git a/tests/stm32/src/bin/rtc.rs b/tests/stm32/src/bin/rtc.rs index 7df415b4..1a64dd38 100644 --- a/tests/stm32/src/bin/rtc.rs +++ b/tests/stm32/src/bin/rtc.rs @@ -10,7 +10,8 @@ use chrono::{NaiveDate, NaiveDateTime}; use common::*; use defmt::assert; use embassy_executor::Spawner; -use embassy_stm32::rtc::{Rtc, RtcClockSource, RtcConfig}; +use embassy_stm32::rcc::RtcClockSource; +use embassy_stm32::rtc::{Rtc, RtcConfig}; use embassy_time::{Duration, Timer}; #[embassy_executor::main] diff --git a/tests/stm32/src/bin/stop.rs b/tests/stm32/src/bin/stop.rs index 4a49bde9..0b3f4a30 100644 --- a/tests/stm32/src/bin/stop.rs +++ b/tests/stm32/src/bin/stop.rs @@ -11,7 +11,8 @@ use common::*; use cortex_m_rt::entry; use embassy_executor::Spawner; use embassy_stm32::low_power::{stop_with_rtc, Executor}; -use embassy_stm32::rtc::{Rtc, RtcClockSource, RtcConfig}; +use embassy_stm32::rcc::RtcClockSource; +use embassy_stm32::rtc::{Rtc, RtcConfig}; use embassy_time::{Duration, Timer}; use static_cell::make_static; From 3bf6081eb5985d853ffee1bf8064304daa1fdfd8 Mon Sep 17 00:00:00 2001 From: xoviat Date: Sun, 27 Aug 2023 09:41:31 -0500 Subject: [PATCH 071/106] stm32: fix wl re-export --- embassy-stm32/src/rcc/wl.rs | 20 ++++++++------------ examples/stm32wl/src/bin/rtc.rs | 6 +++--- 2 files changed, 11 insertions(+), 15 deletions(-) diff --git a/embassy-stm32/src/rcc/wl.rs b/embassy-stm32/src/rcc/wl.rs index 8a9b24c9..5b190965 100644 --- a/embassy-stm32/src/rcc/wl.rs +++ b/embassy-stm32/src/rcc/wl.rs @@ -1,7 +1,7 @@ pub use super::bus::{AHBPrescaler, APBPrescaler, VoltageScale}; use crate::pac::pwr::vals::Dbp; use crate::pac::{FLASH, PWR, RCC}; -use crate::rcc::bd::{BackupDomain, RtcClockSource as RCS}; +use crate::rcc::bd::{BackupDomain, RtcClockSource}; use crate::rcc::{set_freqs, Clocks}; use crate::time::Hertz; @@ -130,16 +130,11 @@ impl Default for Config { apb2_pre: APBPrescaler::NotDivided, enable_lsi: false, enable_rtc_apb: false, - rtc_mux: RtcClockSource::LSI32, + rtc_mux: RtcClockSource::LSI, } } } -pub enum RtcClockSource { - LSE32, - LSI32, -} - #[repr(u8)] pub enum Lsedrv { Low = 0, @@ -215,7 +210,7 @@ pub(crate) unsafe fn init(config: Config) { while FLASH.acr().read().latency() != ws {} match config.rtc_mux { - RtcClockSource::LSE32 => { + RtcClockSource::LSE => { // 1. Unlock the backup domain PWR.cr1().modify(|w| w.set_dbp(Dbp::ENABLED)); @@ -231,17 +226,18 @@ pub(crate) unsafe fn init(config: Config) { // Wait until LSE is running while !RCC.bdcr().read().lserdy() {} - BackupDomain::set_rtc_clock_source(RCS::LSE); + BackupDomain::set_rtc_clock_source(RtcClockSource::LSE); } - RtcClockSource::LSI32 => { + RtcClockSource::LSI => { // Turn on the internal 32 kHz LSI oscillator RCC.csr().modify(|w| w.set_lsion(true)); // Wait until LSI is running while !RCC.csr().read().lsirdy() {} - BackupDomain::set_rtc_clock_source(RCS::LSI); + BackupDomain::set_rtc_clock_source(RtcClockSource::LSI); } + _ => unreachable!(), } match config.mux { @@ -266,7 +262,7 @@ pub(crate) unsafe fn init(config: Config) { w.set_msirange(range.into()); w.set_msion(true); - if let RtcClockSource::LSE32 = config.rtc_mux { + if let RtcClockSource::LSE = config.rtc_mux { // If LSE is enabled, enable calibration of MSI w.set_msipllen(true); } else { diff --git a/examples/stm32wl/src/bin/rtc.rs b/examples/stm32wl/src/bin/rtc.rs index fb1bc6e3..2be6c7b9 100644 --- a/examples/stm32wl/src/bin/rtc.rs +++ b/examples/stm32wl/src/bin/rtc.rs @@ -5,8 +5,8 @@ use chrono::{NaiveDate, NaiveDateTime}; use defmt::*; use embassy_executor::Spawner; -use embassy_stm32::rcc::{self, ClockSrc}; -use embassy_stm32::rtc::{Rtc, RtcConfig}; +use embassy_stm32::rcc::ClockSrc; +use embassy_stm32::rtc::{Rtc, RtcClockSource, RtcConfig}; use embassy_stm32::Config; use embassy_time::{Duration, Timer}; use {defmt_rtt as _, panic_probe as _}; @@ -16,7 +16,7 @@ async fn main(_spawner: Spawner) { let p = { let mut config = Config::default(); config.rcc.mux = ClockSrc::HSE32; - config.rcc.rtc_mux = rcc::RtcClockSource::LSE32; + config.rcc.rtc_mux = RtcClockSource::LSE; config.rcc.enable_rtc_apb = true; embassy_stm32::init(config) }; From f28ab18d7bc05ade2130979d67b0af6ad4085d76 Mon Sep 17 00:00:00 2001 From: xoviat Date: Sun, 27 Aug 2023 09:50:02 -0500 Subject: [PATCH 072/106] stm32: fix l4 re-export --- embassy-stm32/src/rcc/l4.rs | 20 ++++++++----------- examples/stm32l4/src/bin/rtc.rs | 2 +- .../src/bin/spe_adin1110_http_server.rs | 2 +- 3 files changed, 10 insertions(+), 14 deletions(-) diff --git a/embassy-stm32/src/rcc/l4.rs b/embassy-stm32/src/rcc/l4.rs index 1f02254b..c6bccfd2 100644 --- a/embassy-stm32/src/rcc/l4.rs +++ b/embassy-stm32/src/rcc/l4.rs @@ -9,7 +9,7 @@ use crate::gpio::sealed::AFType; use crate::gpio::Speed; use crate::pac::rcc::vals::{Hpre, Msirange, Pllsrc, Ppre, Sw}; use crate::pac::{FLASH, PWR, RCC}; -use crate::rcc::bd::{BackupDomain, RtcClockSource as RCS}; +use crate::rcc::bd::{BackupDomain, RtcClockSource}; use crate::rcc::{set_freqs, Clocks}; use crate::time::Hertz; use crate::{peripherals, Peripheral}; @@ -254,16 +254,11 @@ impl Default for Config { pllsai1: None, #[cfg(not(any(stm32l471, stm32l475, stm32l476, stm32l486)))] hsi48: false, - rtc_mux: RtcClockSource::LSI32, + rtc_mux: RtcClockSource::LSI, } } } -pub enum RtcClockSource { - LSE32, - LSI32, -} - pub enum McoClock { DIV1, DIV2, @@ -413,7 +408,7 @@ pub(crate) unsafe fn init(config: Config) { RCC.apb1enr1().modify(|w| w.set_pwren(true)); match config.rtc_mux { - RtcClockSource::LSE32 => { + RtcClockSource::LSE => { // 1. Unlock the backup domain PWR.cr1().modify(|w| w.set_dbp(true)); @@ -429,17 +424,18 @@ pub(crate) unsafe fn init(config: Config) { // Wait until LSE is running while !RCC.bdcr().read().lserdy() {} - BackupDomain::set_rtc_clock_source(RCS::LSE); + BackupDomain::set_rtc_clock_source(RtcClockSource::LSE); } - RtcClockSource::LSI32 => { + RtcClockSource::LSI => { // Turn on the internal 32 kHz LSI oscillator RCC.csr().modify(|w| w.set_lsion(true)); // Wait until LSI is running while !RCC.csr().read().lsirdy() {} - BackupDomain::set_rtc_clock_source(RCS::LSI); + BackupDomain::set_rtc_clock_source(RtcClockSource::LSI); } + _ => unreachable!(), } let (sys_clk, sw) = match config.mux { @@ -451,7 +447,7 @@ pub(crate) unsafe fn init(config: Config) { w.set_msirgsel(true); w.set_msion(true); - if let RtcClockSource::LSE32 = config.rtc_mux { + if let RtcClockSource::LSE = config.rtc_mux { // If LSE is enabled, enable calibration of MSI w.set_msipllen(true); } else { diff --git a/examples/stm32l4/src/bin/rtc.rs b/examples/stm32l4/src/bin/rtc.rs index 294ea456..f3f8aa46 100644 --- a/examples/stm32l4/src/bin/rtc.rs +++ b/examples/stm32l4/src/bin/rtc.rs @@ -23,7 +23,7 @@ async fn main(_spawner: Spawner) { PLLMul::Mul20, None, ); - config.rcc.rtc_mux = rcc::RtcClockSource::LSE32; + config.rcc.rtc_mux = rcc::RtcClockSource::LSE; embassy_stm32::init(config) }; info!("Hello World!"); diff --git a/examples/stm32l4/src/bin/spe_adin1110_http_server.rs b/examples/stm32l4/src/bin/spe_adin1110_http_server.rs index 148c5877..0a677be7 100644 --- a/examples/stm32l4/src/bin/spe_adin1110_http_server.rs +++ b/examples/stm32l4/src/bin/spe_adin1110_http_server.rs @@ -84,7 +84,7 @@ async fn main(spawner: Spawner) { None, ); config.rcc.hsi48 = true; // needed for rng - config.rcc.rtc_mux = rcc::RtcClockSource::LSI32; + config.rcc.rtc_mux = rcc::RtcClockSource::LSI; let dp = embassy_stm32::init(config); From 531f51d0eb66af9b681b49c10e28ef25e88bbcc2 Mon Sep 17 00:00:00 2001 From: xoviat Date: Sun, 27 Aug 2023 15:01:09 -0500 Subject: [PATCH 073/106] rcc/bd: consolidate mod --- embassy-stm32/Cargo.toml | 4 +- embassy-stm32/src/rcc/bd.rs | 119 +++++++++++++----------------------- embassy-stm32/src/rcc/wl.rs | 3 +- 3 files changed, 46 insertions(+), 80 deletions(-) diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index 150014af..d0ada97a 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml @@ -58,7 +58,7 @@ sdio-host = "0.5.0" embedded-sdmmc = { git = "https://github.com/embassy-rs/embedded-sdmmc-rs", rev = "a4f293d3a6f72158385f79c98634cb8a14d0d2fc", optional = true } critical-section = "1.1" atomic-polyfill = "1.0.1" -stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-2b87e34c661e19ff6dc603fabfe7fe99ab7261f7" } +stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-9a61a1f090462df8bd1751f89951f04934fdceb3" } vcell = "0.1.3" bxcan = "0.7.0" nb = "1.0.0" @@ -77,7 +77,7 @@ critical-section = { version = "1.1", features = ["std"] } [build-dependencies] proc-macro2 = "1.0.36" quote = "1.0.15" -stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-2b87e34c661e19ff6dc603fabfe7fe99ab7261f7", default-features = false, features = ["metadata"]} +stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-9a61a1f090462df8bd1751f89951f04934fdceb3", default-features = false, features = ["metadata"]} [features] default = ["rt"] diff --git a/embassy-stm32/src/rcc/bd.rs b/embassy-stm32/src/rcc/bd.rs index fd1b8d45..d56bc033 100644 --- a/embassy-stm32/src/rcc/bd.rs +++ b/embassy-stm32/src/rcc/bd.rs @@ -12,86 +12,67 @@ pub enum RtcClockSource { HSE = 0b11, } +#[cfg(not(any(rtc_v2l0, rtc_v2l1)))] +type Bdcr = crate::pac::rcc::regs::Bdcr; + +#[cfg(any(rtc_v2l0, rtc_v2l1))] +type Bdcr = crate::pac::rcc::regs::Csr; + #[allow(dead_code)] pub struct BackupDomain {} impl BackupDomain { #[cfg(any( - rtc_v2f0, rtc_v2f2, rtc_v2f3, rtc_v2f4, rtc_v2f7, rtc_v2h7, rtc_v2l0, rtc_v2l1, rtc_v2l4, rtc_v2wb + rtc_v2f0, rtc_v2f2, rtc_v2f3, rtc_v2f4, rtc_v2f7, rtc_v2h7, rtc_v2l0, rtc_v2l1, rtc_v2l4, rtc_v2wb, rtc_v3, + rtc_v3u5 ))] #[allow(dead_code)] - fn unlock_registers() { + fn modify(f: impl FnOnce(&mut Bdcr) -> R) -> R { #[cfg(any(rtc_v2f2, rtc_v2f3, rtc_v2l1))] let cr = crate::pac::PWR.cr(); - #[cfg(any(rtc_v2f4, rtc_v2f7, rtc_v2h7, rtc_v2l4, rtc_v2wb))] + #[cfg(any(rtc_v2f4, rtc_v2f7, rtc_v2h7, rtc_v2l4, rtc_v2wb, rtc_v3, rtc_v3u5))] let cr = crate::pac::PWR.cr1(); // TODO: Missing from PAC for l0 and f0? - #[cfg(not(any(rtc_v2f0, rtc_v2l0)))] + #[cfg(not(any(rtc_v2f0, rtc_v2l0, rtc_v3u5)))] { - if !cr.read().dbp() { - cr.modify(|w| w.set_dbp(true)); - while !cr.read().dbp() {} - } + cr.modify(|w| w.set_dbp(true)); + while !cr.read().dbp() {} } - } - #[cfg(any(rtc_v3, rtc_v3u5))] - #[allow(dead_code)] - fn unlock_registers() { - // Unlock the backup domain - #[cfg(not(any(rtc_v3u5, rcc_wl5, rcc_wle)))] - { - if !crate::pac::PWR.cr1().read().dbp() { - crate::pac::PWR.cr1().modify(|w| w.set_dbp(true)); - while !crate::pac::PWR.cr1().read().dbp() {} - } - } - #[cfg(any(rcc_wl5, rcc_wle))] - { - use crate::pac::pwr::vals::Dbp; - - if crate::pac::PWR.cr1().read().dbp() != Dbp::ENABLED { - crate::pac::PWR.cr1().modify(|w| w.set_dbp(Dbp::ENABLED)); - while crate::pac::PWR.cr1().read().dbp() != Dbp::ENABLED {} - } - } + crate::pac::RCC.bdcr().modify(|w| f(w)) } #[cfg(any( - rtc_v2f0, rtc_v2f2, rtc_v2f3, rtc_v2f4, rtc_v2f7, rtc_v2h7, rtc_v2l0, rtc_v2l1, rtc_v2l4, rtc_v2wb + rtc_v2f0, rtc_v2f2, rtc_v2f3, rtc_v2f4, rtc_v2f7, rtc_v2h7, rtc_v2l0, rtc_v2l1, rtc_v2l4, rtc_v2wb, rtc_v3, + rtc_v3u5 + ))] + #[allow(dead_code)] + fn read() -> Bdcr { + #[cfg(any(rtc_v2l0, rtc_v2l1))] + let r = crate::pac::RCC.csr().read(); + + #[cfg(not(any(rtc_v2l0, rtc_v2l1)))] + let r = crate::pac::RCC.bdcr().read(); + + r + } + + #[cfg(any( + rtc_v2f0, rtc_v2f2, rtc_v2f3, rtc_v2f4, rtc_v2f7, rtc_v2h7, rtc_v2l0, rtc_v2l1, rtc_v2l4, rtc_v2wb, rtc_v3, + rtc_v3u5 ))] #[allow(dead_code)] - pub fn set_rtc_clock_source(clock_source: RtcClockSource) { - #[cfg(not(rtc_v2wb))] - use stm32_metapac::rcc::vals::Rtcsel; - - #[cfg(not(any(rtc_v2l0, rtc_v2l1)))] - let cr = crate::pac::RCC.bdcr(); - #[cfg(any(rtc_v2l0, rtc_v2l1))] - let cr = crate::pac::RCC.csr(); - - Self::unlock_registers(); - - cr.modify(|w| { - // Select RTC source - #[cfg(not(rtc_v2wb))] - w.set_rtcsel(Rtcsel::from_bits(clock_source as u8)); - #[cfg(rtc_v2wb)] - w.set_rtcsel(clock_source as u8); - }); - } - - #[cfg(any(rtc_v3, rtc_v3u5))] - #[allow(dead_code)] pub fn set_rtc_clock_source(clock_source: RtcClockSource) { let clock_source = clock_source as u8; - #[cfg(not(any(rcc_wl5, rcc_wle)))] + #[cfg(any( + all(not(any(rtc_v3, rtc_v3u5)), not(rtc_v2wb)), + all(any(rtc_v3, rtc_v3u5), not(any(rcc_wl5, rcc_wle))) + ))] let clock_source = crate::pac::rcc::vals::Rtcsel::from_bits(clock_source); - Self::unlock_registers(); - - crate::pac::RCC.bdcr().modify(|w| { + #[cfg(not(rtc_v2wb))] + Self::modify(|w| { // Select RTC source w.set_rtcsel(clock_source); }); @@ -102,25 +83,16 @@ impl BackupDomain { ))] #[allow(dead_code)] pub fn enable_rtc() { - #[cfg(not(any(rtc_v2l0, rtc_v2l1)))] - let reg = crate::pac::RCC.bdcr().read(); - #[cfg(any(rtc_v2l0, rtc_v2l1))] - let reg = crate::pac::RCC.csr().read(); + let reg = Self::read(); #[cfg(any(rtc_v2h7, rtc_v2l4, rtc_v2wb))] assert!(!reg.lsecsson(), "RTC is not compatible with LSE CSS, yet."); if !reg.rtcen() { - Self::unlock_registers(); - #[cfg(not(any(rtc_v2l0, rtc_v2l1, rtc_v2f2)))] - crate::pac::RCC.bdcr().modify(|w| w.set_bdrst(true)); - #[cfg(not(any(rtc_v2l0, rtc_v2l1)))] - let cr = crate::pac::RCC.bdcr(); - #[cfg(any(rtc_v2l0, rtc_v2l1))] - let cr = crate::pac::RCC.csr(); + Self::modify(|w| w.set_bdrst(true)); - cr.modify(|w| { + Self::modify(|w| { // Reset #[cfg(not(any(rtc_v2l0, rtc_v2l1)))] w.set_bdrst(false); @@ -146,18 +118,13 @@ impl BackupDomain { #[cfg(any(rtc_v3, rtc_v3u5))] #[allow(dead_code)] pub fn enable_rtc() { - let bdcr = crate::pac::RCC.bdcr(); - - let reg = bdcr.read(); + let reg = Self::read(); assert!(!reg.lsecsson(), "RTC is not compatible with LSE CSS, yet."); if !reg.rtcen() { - Self::unlock_registers(); + Self::modify(|w| w.set_bdrst(true)); - bdcr.modify(|w| w.set_bdrst(true)); - - bdcr.modify(|w| { - // Reset + Self::modify(|w| { w.set_bdrst(false); w.set_rtcen(true); diff --git a/embassy-stm32/src/rcc/wl.rs b/embassy-stm32/src/rcc/wl.rs index 5b190965..e33690d1 100644 --- a/embassy-stm32/src/rcc/wl.rs +++ b/embassy-stm32/src/rcc/wl.rs @@ -1,5 +1,4 @@ pub use super::bus::{AHBPrescaler, APBPrescaler, VoltageScale}; -use crate::pac::pwr::vals::Dbp; use crate::pac::{FLASH, PWR, RCC}; use crate::rcc::bd::{BackupDomain, RtcClockSource}; use crate::rcc::{set_freqs, Clocks}; @@ -212,7 +211,7 @@ pub(crate) unsafe fn init(config: Config) { match config.rtc_mux { RtcClockSource::LSE => { // 1. Unlock the backup domain - PWR.cr1().modify(|w| w.set_dbp(Dbp::ENABLED)); + PWR.cr1().modify(|w| w.set_dbp(true)); // 2. Setup the LSE RCC.bdcr().modify(|w| { From cbc92dce052060bb15b82921c0a05c3a81d6dcc9 Mon Sep 17 00:00:00 2001 From: xoviat Date: Sun, 27 Aug 2023 15:18:34 -0500 Subject: [PATCH 074/106] stm32/bd: fix errors --- embassy-stm32/src/rcc/bd.rs | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/embassy-stm32/src/rcc/bd.rs b/embassy-stm32/src/rcc/bd.rs index d56bc033..0fc116ed 100644 --- a/embassy-stm32/src/rcc/bd.rs +++ b/embassy-stm32/src/rcc/bd.rs @@ -12,10 +12,12 @@ pub enum RtcClockSource { HSE = 0b11, } -#[cfg(not(any(rtc_v2l0, rtc_v2l1)))] +#[cfg(not(any(rtc_v2l0, rtc_v2l1, stm32c0)))] +#[allow(dead_code)] type Bdcr = crate::pac::rcc::regs::Bdcr; #[cfg(any(rtc_v2l0, rtc_v2l1))] +#[allow(dead_code)] type Bdcr = crate::pac::rcc::regs::Csr; #[allow(dead_code)] @@ -26,7 +28,7 @@ impl BackupDomain { rtc_v2f0, rtc_v2f2, rtc_v2f3, rtc_v2f4, rtc_v2f7, rtc_v2h7, rtc_v2l0, rtc_v2l1, rtc_v2l4, rtc_v2wb, rtc_v3, rtc_v3u5 ))] - #[allow(dead_code)] + #[allow(dead_code, unused_variables)] fn modify(f: impl FnOnce(&mut Bdcr) -> R) -> R { #[cfg(any(rtc_v2f2, rtc_v2f3, rtc_v2l1))] let cr = crate::pac::PWR.cr(); @@ -40,7 +42,13 @@ impl BackupDomain { while !cr.read().dbp() {} } - crate::pac::RCC.bdcr().modify(|w| f(w)) + #[cfg(any(rtc_v2l0, rtc_v2l1))] + let cr = crate::pac::RCC.csr(); + + #[cfg(not(any(rtc_v2l0, rtc_v2l1)))] + let cr = crate::pac::RCC.bdcr(); + + cr.modify(|w| f(w)) } #[cfg(any( @@ -62,7 +70,7 @@ impl BackupDomain { rtc_v2f0, rtc_v2f2, rtc_v2f3, rtc_v2f4, rtc_v2f7, rtc_v2h7, rtc_v2l0, rtc_v2l1, rtc_v2l4, rtc_v2wb, rtc_v3, rtc_v3u5 ))] - #[allow(dead_code)] + #[allow(dead_code, unused_variables)] pub fn set_rtc_clock_source(clock_source: RtcClockSource) { let clock_source = clock_source as u8; #[cfg(any( From 326e78757b6b69ba598fb89030defd62e081af64 Mon Sep 17 00:00:00 2001 From: xoviat Date: Sun, 27 Aug 2023 15:25:12 -0500 Subject: [PATCH 075/106] rustfmt --- examples/stm32f4/src/bin/rtc.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/examples/stm32f4/src/bin/rtc.rs b/examples/stm32f4/src/bin/rtc.rs index 33c4ebfd..23ff8ac4 100644 --- a/examples/stm32f4/src/bin/rtc.rs +++ b/examples/stm32f4/src/bin/rtc.rs @@ -5,10 +5,8 @@ use chrono::{NaiveDate, NaiveDateTime}; use defmt::*; use embassy_executor::Spawner; -use embassy_stm32::{ - rtc::{Rtc, RtcClockSource, RtcConfig}, - Config, -}; +use embassy_stm32::rtc::{Rtc, RtcClockSource, RtcConfig}; +use embassy_stm32::Config; use embassy_time::{Duration, Timer}; use {defmt_rtt as _, panic_probe as _}; From 9f928010a86be9e0f8b5fa4257c3edd70261c0dc Mon Sep 17 00:00:00 2001 From: xoviat Date: Sun, 27 Aug 2023 16:06:33 -0500 Subject: [PATCH 076/106] stm32/rtc: use psc to compute instants --- embassy-stm32/src/rtc/mod.rs | 53 ++++++++++++------------------------ embassy-stm32/src/rtc/v2.rs | 4 +-- 2 files changed, 19 insertions(+), 38 deletions(-) diff --git a/embassy-stm32/src/rtc/mod.rs b/embassy-stm32/src/rtc/mod.rs index c408b2d6..8bda0926 100644 --- a/embassy-stm32/src/rtc/mod.rs +++ b/embassy-stm32/src/rtc/mod.rs @@ -47,31 +47,6 @@ struct RtcInstant { subsecond: u16, } -#[cfg(feature = "low-power")] -impl RtcInstant { - pub fn now() -> Self { - let tr = RTC::regs().tr().read(); - let tr2 = RTC::regs().tr().read(); - let ssr = RTC::regs().ssr().read().ss(); - let ssr2 = RTC::regs().ssr().read().ss(); - - let st = bcd2_to_byte((tr.st(), tr.su())); - let st2 = bcd2_to_byte((tr2.st(), tr2.su())); - - assert!(st == st2); - assert!(ssr == ssr2); - - let _ = RTC::regs().dr().read(); - - let subsecond = ssr; - let second = st; - - // trace!("rtc: instant now: st, ssr: {}, {}", st, ssr); - - Self { second, subsecond } - } -} - #[cfg(feature = "low-power")] impl core::ops::Sub for RtcInstant { type Output = embassy_time::Duration; @@ -85,20 +60,13 @@ impl core::ops::Sub for RtcInstant { self.second }; - // TODO: read prescaler + let psc = RTC::regs().prer().read().prediv_s() as u32; - let self_ticks = second as u32 * 256 + (255 - self.subsecond as u32); - let other_ticks = rhs.second as u32 * 256 + (255 - rhs.subsecond as u32); + let self_ticks = second as u32 * (psc + 1) + (psc - self.subsecond as u32); + let other_ticks = rhs.second as u32 * (psc + 1) + (psc - rhs.subsecond as u32); let rtc_ticks = self_ticks - other_ticks; - // trace!( - // "rtc: instant sub: self, other, rtc ticks: {}, {}, {}", - // self_ticks, - // other_ticks, - // rtc_ticks - // ); - - Duration::from_ticks(((rtc_ticks * TICK_HZ as u32) / 256u32) as u64) + Duration::from_ticks(((rtc_ticks * TICK_HZ as u32) / psc) as u64) } } @@ -198,6 +166,19 @@ impl Rtc { Ok(()) } + /// Return the current instant. + fn instant(&self) -> RtcInstant { + let r = RTC::regs(); + let tr = r.tr().read(); + let subsecond = r.ssr().read().ss(); + let second = bcd2_to_byte((tr.st(), tr.su())); + + // Unlock the registers + r.dr(); + + RtcInstant { second, subsecond } + } + /// Return the current datetime. /// /// # Errors diff --git a/embassy-stm32/src/rtc/v2.rs b/embassy-stm32/src/rtc/v2.rs index 1e0ca9b4..62b39868 100644 --- a/embassy-stm32/src/rtc/v2.rs +++ b/embassy-stm32/src/rtc/v2.rs @@ -110,7 +110,7 @@ impl super::Rtc { trace!("rtc: start wakeup alarm for {} ms", duration.as_millis()); - critical_section::with(|cs| assert!(self.stop_time.borrow(cs).replace(Some(RtcInstant::now())).is_none())) + critical_section::with(|cs| assert!(self.stop_time.borrow(cs).replace(Some(self.instant())).is_none())) } #[cfg(feature = "low-power")] @@ -132,7 +132,7 @@ impl super::Rtc { critical_section::with(|cs| { if let Some(stop_time) = self.stop_time.borrow(cs).take() { - Some(RtcInstant::now() - stop_time) + Some(self.instant() - stop_time) } else { None } From e981cd496827c01cba11fd6ba40b2b7ed482e49b Mon Sep 17 00:00:00 2001 From: xoviat Date: Sun, 27 Aug 2023 21:15:57 -0500 Subject: [PATCH 077/106] stm32: fix rtc wakeup timing and add dbg --- embassy-stm32/Cargo.toml | 3 ++- embassy-stm32/src/low_power.rs | 7 ++++++ embassy-stm32/src/rcc/f4.rs | 2 +- embassy-stm32/src/rtc/mod.rs | 14 ++++++++++- embassy-stm32/src/rtc/v2.rs | 43 ++++++++++++++++++++++++-------- embassy-stm32/src/time_driver.rs | 2 ++ tests/stm32/src/bin/stop.rs | 6 +++-- 7 files changed, 62 insertions(+), 15 deletions(-) diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index d0ada97a..ca421910 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml @@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0" src_base = "https://github.com/embassy-rs/embassy/blob/embassy-stm32-v$VERSION/embassy-stm32/src/" src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-stm32/src/" -features = ["nightly", "defmt", "unstable-pac", "unstable-traits", "exti", "time-driver-any", "time", "low-power"] +features = ["nightly", "defmt", "unstable-pac", "unstable-traits", "exti", "time-driver-any", "time", "low-power", "rtc-debug"] flavors = [ { regex_feature = "stm32f0.*", target = "thumbv6m-none-eabi" }, { regex_feature = "stm32f1.*", target = "thumbv7m-none-eabi" }, @@ -90,6 +90,7 @@ defmt = ["dep:defmt", "bxcan/unstable-defmt", "embassy-sync/defmt", "embassy-emb exti = [] low-power = [ "dep:embassy-executor", "embassy-executor/arch-cortex-m" ] +rtc-debug = [] embassy-executor = [] ## Automatically generate `memory.x` file using [`stm32-metapac`](https://docs.rs/stm32-metapac/) diff --git a/embassy-stm32/src/low_power.rs b/embassy-stm32/src/low_power.rs index 65b93f8a..f9b5fde9 100644 --- a/embassy-stm32/src/low_power.rs +++ b/embassy-stm32/src/low_power.rs @@ -89,6 +89,9 @@ impl Executor { self.time_driver.resume_time(); trace!("low power: resume time"); + + #[cfg(feature = "rtc-debug")] + cortex_m::asm::bkpt(); } pub(self) fn stop_with_rtc(&mut self, rtc: &'static Rtc) { @@ -118,6 +121,7 @@ impl Executor { } trace!("low power: enter stop..."); + #[cfg(not(feature = "rtc-debug"))] self.scb.set_sleepdeep(); } @@ -140,6 +144,9 @@ impl Executor { /// /// This function never returns. pub fn run(&'static mut self, init: impl FnOnce(Spawner)) -> ! { + #[cfg(feature = "rtc-debug")] + trace!("low power: rtc debug enabled"); + init(unsafe { EXECUTOR.as_mut().unwrap() }.inner.spawner()); loop { diff --git a/embassy-stm32/src/rcc/f4.rs b/embassy-stm32/src/rcc/f4.rs index 10d3322a..d8b689e4 100644 --- a/embassy-stm32/src/rcc/f4.rs +++ b/embassy-stm32/src/rcc/f4.rs @@ -17,7 +17,7 @@ use crate::{peripherals, Peripheral}; pub const HSI_FREQ: Hertz = Hertz(16_000_000); /// LSI speed -pub const LSI_FREQ: Hertz = Hertz(32_000); +pub const LSI_FREQ: Hertz = Hertz(32_768); /// Clocks configuration #[non_exhaustive] diff --git a/embassy-stm32/src/rtc/mod.rs b/embassy-stm32/src/rtc/mod.rs index 8bda0926..496ad5c1 100644 --- a/embassy-stm32/src/rtc/mod.rs +++ b/embassy-stm32/src/rtc/mod.rs @@ -47,6 +47,18 @@ struct RtcInstant { subsecond: u16, } +#[cfg(all(feature = "low-power", feature = "defmt"))] +impl defmt::Format for RtcInstant { + fn format(&self, fmt: defmt::Formatter) { + defmt::write!( + fmt, + "{}:{}", + self.second, + RTC::regs().prer().read().prediv_s() - self.subsecond, + ) + } +} + #[cfg(feature = "low-power")] impl core::ops::Sub for RtcInstant { type Output = embassy_time::Duration; @@ -174,7 +186,7 @@ impl Rtc { let second = bcd2_to_byte((tr.st(), tr.su())); // Unlock the registers - r.dr(); + r.dr().read(); RtcInstant { second, subsecond } } diff --git a/embassy-stm32/src/rtc/v2.rs b/embassy-stm32/src/rtc/v2.rs index 62b39868..7eb8a96c 100644 --- a/embassy-stm32/src/rtc/v2.rs +++ b/embassy-stm32/src/rtc/v2.rs @@ -1,7 +1,5 @@ use stm32_metapac::rtc::vals::{Init, Osel, Pol}; -#[cfg(feature = "low-power")] -use super::RtcInstant; use super::{sealed, RtcConfig}; use crate::pac::rtc::Rtc; use crate::peripherals::RTC; @@ -77,6 +75,21 @@ impl super::Rtc { /// start the wakeup alarm and wtih a duration that is as close to but less than /// the requested duration, and record the instant the wakeup alarm was started pub(crate) fn start_wakeup_alarm(&self, requested_duration: embassy_time::Duration) { + #[cfg(feature = "rtc-debug")] + if critical_section::with(|cs| { + if let Some(instant) = self.stop_time.borrow(cs).take() { + self.stop_time.borrow(cs).replace(Some(instant)); + + Some(()) + } else { + None + } + }) + .is_some() + { + return; + } + use embassy_time::{Duration, TICK_HZ}; use crate::rcc::get_freqs; @@ -86,17 +99,14 @@ impl super::Rtc { let rtc_ticks = requested_duration.as_ticks() * rtc_hz / TICK_HZ; let prescaler = WakeupPrescaler::compute_min((rtc_ticks / u16::MAX as u64) as u32); - // adjust the rtc ticks to the prescaler + // adjust the rtc ticks to the prescaler and subtract one rtc tick let rtc_ticks = rtc_ticks / (>::into(prescaler) as u64); let rtc_ticks = if rtc_ticks >= u16::MAX as u64 { u16::MAX - 1 } else { rtc_ticks as u16 - }; - - let duration = Duration::from_ticks( - rtc_ticks as u64 * TICK_HZ * (>::into(prescaler) as u64) / rtc_hz, - ); + } + .saturating_sub(1); self.write(false, |regs| { regs.cr().modify(|w| w.set_wute(false)); @@ -104,11 +114,21 @@ impl super::Rtc { while !regs.isr().read().wutwf() {} regs.cr().modify(|w| w.set_wucksel(prescaler.into())); + regs.wutr().write(|w| w.set_wut(rtc_ticks)); regs.cr().modify(|w| w.set_wute(true)); regs.cr().modify(|w| w.set_wutie(true)); }); - trace!("rtc: start wakeup alarm for {} ms", duration.as_millis()); + trace!( + "rtc: start wakeup alarm for {} ms (psc: {}, ticks: {}) at {}", + Duration::from_ticks( + rtc_ticks as u64 * TICK_HZ * (>::into(prescaler) as u64) / rtc_hz, + ) + .as_millis(), + >::into(prescaler), + rtc_ticks, + self.instant(), + ); critical_section::with(|cs| assert!(self.stop_time.borrow(cs).replace(Some(self.instant())).is_none())) } @@ -119,7 +139,10 @@ impl super::Rtc { pub(crate) fn stop_wakeup_alarm(&self) -> Option { use crate::interrupt::typelevel::Interrupt; - trace!("rtc: stop wakeup alarm..."); + trace!("rtc: stop wakeup alarm at {}", self.instant()); + + #[cfg(feature = "rtc-debug")] + return None; self.write(false, |regs| { regs.cr().modify(|w| w.set_wutie(false)); diff --git a/embassy-stm32/src/time_driver.rs b/embassy-stm32/src/time_driver.rs index 99d423d0..d4442c23 100644 --- a/embassy-stm32/src/time_driver.rs +++ b/embassy-stm32/src/time_driver.rs @@ -363,6 +363,7 @@ impl RtcDriver { .start_wakeup_alarm(time_until_next_alarm); }); + #[cfg(not(feature = "rtc-debug"))] T::regs_gp16().cr1().modify(|w| w.set_cen(false)); Ok(()) @@ -374,6 +375,7 @@ impl RtcDriver { pub(crate) fn resume_time(&self) { self.stop_wakeup_alarm(); + #[cfg(not(feature = "rtc-debug"))] T::regs_gp16().cr1().modify(|w| w.set_cen(true)); } } diff --git a/tests/stm32/src/bin/stop.rs b/tests/stm32/src/bin/stop.rs index 0b3f4a30..a490d7b8 100644 --- a/tests/stm32/src/bin/stop.rs +++ b/tests/stm32/src/bin/stop.rs @@ -46,8 +46,10 @@ async fn async_main(_spawner: Spawner) { stop_with_rtc(rtc); - info!("Waiting 5 seconds"); - Timer::after(Duration::from_secs(5)).await; + info!("Waiting..."); + Timer::after(Duration::from_secs(2)).await; + info!("Waiting..."); + Timer::after(Duration::from_secs(3)).await; info!("Test OK"); cortex_m::asm::bkpt(); From 538001a4bc4cdf647924d621347c851f13b6a95d Mon Sep 17 00:00:00 2001 From: xoviat Date: Sun, 27 Aug 2023 21:24:16 -0500 Subject: [PATCH 078/106] stm32/rtc: fix psc div --- embassy-stm32/src/rtc/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/embassy-stm32/src/rtc/mod.rs b/embassy-stm32/src/rtc/mod.rs index 496ad5c1..ca375855 100644 --- a/embassy-stm32/src/rtc/mod.rs +++ b/embassy-stm32/src/rtc/mod.rs @@ -78,7 +78,7 @@ impl core::ops::Sub for RtcInstant { let other_ticks = rhs.second as u32 * (psc + 1) + (psc - rhs.subsecond as u32); let rtc_ticks = self_ticks - other_ticks; - Duration::from_ticks(((rtc_ticks * TICK_HZ as u32) / psc) as u64) + Duration::from_ticks(((rtc_ticks * TICK_HZ as u32) / (psc + 1)) as u64) } } From 2c80784fe6e1a165cabae83baf7c842218a35046 Mon Sep 17 00:00:00 2001 From: xoviat Date: Sun, 27 Aug 2023 21:26:29 -0500 Subject: [PATCH 079/106] stm32/rtc: feature-gate instant --- embassy-stm32/src/rtc/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/embassy-stm32/src/rtc/mod.rs b/embassy-stm32/src/rtc/mod.rs index ca375855..796fd7d9 100644 --- a/embassy-stm32/src/rtc/mod.rs +++ b/embassy-stm32/src/rtc/mod.rs @@ -178,6 +178,7 @@ impl Rtc { Ok(()) } + #[cfg(feature = "low-power")] /// Return the current instant. fn instant(&self) -> RtcInstant { let r = RTC::regs(); From fd739250ea8b830f06f8a78a272874faa888d42c Mon Sep 17 00:00:00 2001 From: Olle Sandberg Date: Mon, 28 Aug 2023 11:27:56 +0200 Subject: [PATCH 080/106] stm32: fix wait for RNG data If no data was available to read then the loop would wait for an interrupt and skip to the next chunk without writing the current one. This could cause the given slice to only be partially filled with random data. Fixed by moving the wait to before actually writing data to the chunk. --- embassy-stm32/src/rng.rs | 46 ++++++++++++++++++++++------------------ 1 file changed, 25 insertions(+), 21 deletions(-) diff --git a/embassy-stm32/src/rng.rs b/embassy-stm32/src/rng.rs index 30816e43..0979dce8 100644 --- a/embassy-stm32/src/rng.rs +++ b/embassy-stm32/src/rng.rs @@ -119,7 +119,31 @@ impl<'d, T: Instance> Rng<'d, T> { pub async fn async_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> { for chunk in dest.chunks_mut(4) { - let bits = T::regs().sr().read(); + let mut bits = T::regs().sr().read(); + if !bits.seis() && !bits.ceis() && !bits.drdy() { + // wait for interrupt + poll_fn(|cx| { + // quick check to avoid registration if already done. + let bits = T::regs().sr().read(); + if bits.drdy() || bits.seis() || bits.ceis() { + return Poll::Ready(()); + } + RNG_WAKER.register(cx.waker()); + T::regs().cr().modify(|reg| reg.set_ie(true)); + // Need to check condition **after** `register` to avoid a race + // condition that would result in lost notifications. + let bits = T::regs().sr().read(); + if bits.drdy() || bits.seis() || bits.ceis() { + Poll::Ready(()) + } else { + Poll::Pending + } + }) + .await; + + // Re-read the status register after wait. + bits = T::regs().sr().read() + } if bits.seis() { // in case of noise-source or seed error we try to recover here // but we must not use the data in DR and we return an error @@ -143,26 +167,6 @@ impl<'d, T: Instance> Rng<'d, T> { for (dest, src) in chunk.iter_mut().zip(random_word.to_be_bytes().iter()) { *dest = *src } - } else { - // wait for interrupt - poll_fn(|cx| { - // quick check to avoid registration if already done. - let bits = T::regs().sr().read(); - if bits.drdy() || bits.seis() || bits.ceis() { - return Poll::Ready(()); - } - RNG_WAKER.register(cx.waker()); - T::regs().cr().modify(|reg| reg.set_ie(true)); - // Need to check condition **after** `register` to avoid a race - // condition that would result in lost notifications. - let bits = T::regs().sr().read(); - if bits.drdy() || bits.seis() || bits.ceis() { - Poll::Ready(()) - } else { - Poll::Pending - } - }) - .await; } } From 1f63bf4153b6ba4a915c0df22041f09adaaca400 Mon Sep 17 00:00:00 2001 From: Jesse Braham Date: Mon, 28 Aug 2023 08:00:18 -0700 Subject: [PATCH 081/106] Release embassy-time v0.1.3 --- cyw43/Cargo.toml | 4 ++-- embassy-embedded-hal/Cargo.toml | 2 +- embassy-executor/Cargo.toml | 2 +- embassy-lora/Cargo.toml | 4 ++-- embassy-net-enc28j60/Cargo.toml | 4 ++-- embassy-net-esp-hosted/Cargo.toml | 4 ++-- embassy-net-wiznet/Cargo.toml | 4 ++-- embassy-net/Cargo.toml | 2 +- embassy-nrf/Cargo.toml | 2 +- embassy-rp/Cargo.toml | 2 +- embassy-stm32-wpan/Cargo.toml | 2 +- embassy-stm32/Cargo.toml | 2 +- embassy-time/CHANGELOG.md | 7 ++++++- embassy-time/Cargo.toml | 2 +- examples/boot/application/nrf/Cargo.toml | 2 +- examples/boot/application/rp/Cargo.toml | 2 +- examples/boot/application/stm32f3/Cargo.toml | 2 +- examples/boot/application/stm32f7/Cargo.toml | 2 +- examples/boot/application/stm32h7/Cargo.toml | 2 +- examples/boot/application/stm32l0/Cargo.toml | 2 +- examples/boot/application/stm32l1/Cargo.toml | 2 +- examples/boot/application/stm32l4/Cargo.toml | 2 +- examples/boot/application/stm32wl/Cargo.toml | 2 +- examples/nrf-rtos-trace/Cargo.toml | 2 +- examples/nrf52840-rtic/Cargo.toml | 2 +- examples/nrf52840/Cargo.toml | 4 ++-- examples/nrf5340/Cargo.toml | 2 +- examples/rp/Cargo.toml | 4 ++-- examples/std/Cargo.toml | 2 +- examples/stm32c0/Cargo.toml | 2 +- examples/stm32f0/Cargo.toml | 2 +- examples/stm32f1/Cargo.toml | 2 +- examples/stm32f2/Cargo.toml | 2 +- examples/stm32f3/Cargo.toml | 2 +- examples/stm32f4/Cargo.toml | 2 +- examples/stm32f7/Cargo.toml | 2 +- examples/stm32g0/Cargo.toml | 2 +- examples/stm32g4/Cargo.toml | 2 +- examples/stm32h5/Cargo.toml | 2 +- examples/stm32h7/Cargo.toml | 2 +- examples/stm32l0/Cargo.toml | 4 ++-- examples/stm32l1/Cargo.toml | 2 +- examples/stm32l4/Cargo.toml | 2 +- examples/stm32l5/Cargo.toml | 2 +- examples/stm32u5/Cargo.toml | 2 +- examples/stm32wb/Cargo.toml | 2 +- examples/stm32wl/Cargo.toml | 4 ++-- examples/wasm/Cargo.toml | 2 +- tests/nrf/Cargo.toml | 4 ++-- tests/riscv32/Cargo.toml | 2 +- tests/rp/Cargo.toml | 2 +- tests/stm32/Cargo.toml | 2 +- 52 files changed, 67 insertions(+), 62 deletions(-) diff --git a/cyw43/Cargo.toml b/cyw43/Cargo.toml index 855d54b1..59b297e0 100644 --- a/cyw43/Cargo.toml +++ b/cyw43/Cargo.toml @@ -11,7 +11,7 @@ log = ["dep:log"] firmware-logs = [] [dependencies] -embassy-time = { version = "0.1.2", path = "../embassy-time"} +embassy-time = { version = "0.1.3", path = "../embassy-time"} embassy-sync = { version = "0.2.0", path = "../embassy-sync"} embassy-futures = { version = "0.1.0", path = "../embassy-futures"} embassy-net-driver-channel = { version = "0.1.0", path = "../embassy-net-driver-channel"} @@ -31,4 +31,4 @@ num_enum = { version = "0.5.7", default-features = false } src_base = "https://github.com/embassy-rs/embassy/blob/cyw43-v$VERSION/cyw43/src/" src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/cyw43/src/" target = "thumbv6m-none-eabi" -features = ["defmt", "firmware-logs"] \ No newline at end of file +features = ["defmt", "firmware-logs"] diff --git a/embassy-embedded-hal/Cargo.toml b/embassy-embedded-hal/Cargo.toml index fd921d27..b311b591 100644 --- a/embassy-embedded-hal/Cargo.toml +++ b/embassy-embedded-hal/Cargo.toml @@ -21,7 +21,7 @@ default = ["time"] [dependencies] embassy-futures = { version = "0.1.0", path = "../embassy-futures", optional = true } embassy-sync = { version = "0.2.0", path = "../embassy-sync" } -embassy-time = { version = "0.1.2", path = "../embassy-time", optional = true } +embassy-time = { version = "0.1.3", path = "../embassy-time", optional = true } embedded-hal-02 = { package = "embedded-hal", version = "0.2.6", features = [ "unproven", ] } diff --git a/embassy-executor/Cargo.toml b/embassy-executor/Cargo.toml index 5bf68fc6..35944625 100644 --- a/embassy-executor/Cargo.toml +++ b/embassy-executor/Cargo.toml @@ -59,7 +59,7 @@ rtos-trace = { version = "0.1.2", optional = true } futures-util = { version = "0.3.17", default-features = false } embassy-macros = { version = "0.2.1", path = "../embassy-macros" } -embassy-time = { version = "0.1.2", path = "../embassy-time", optional = true} +embassy-time = { version = "0.1.3", path = "../embassy-time", optional = true} atomic-polyfill = "1.0.1" critical-section = "1.1" static_cell = "1.1" diff --git a/embassy-lora/Cargo.toml b/embassy-lora/Cargo.toml index feea0658..fa445a39 100644 --- a/embassy-lora/Cargo.toml +++ b/embassy-lora/Cargo.toml @@ -20,7 +20,7 @@ defmt = ["dep:defmt", "lorawan-device/defmt"] defmt = { version = "0.3", optional = true } log = { version = "0.4.14", optional = true } -embassy-time = { version = "0.1.2", path = "../embassy-time", optional = true } +embassy-time = { version = "0.1.3", path = "../embassy-time", optional = true } embassy-sync = { version = "0.2.0", path = "../embassy-sync" } embassy-stm32 = { version = "0.1.0", path = "../embassy-stm32", default-features = false, optional = true } embedded-hal-async = { version = "=1.0.0-rc.1" } @@ -31,4 +31,4 @@ lora-phy = { version = "1" } lorawan-device = { version = "0.10.0", default-features = false, features = ["async"], optional = true } [patch.crates-io] -lora-phy = { git = "https://github.com/embassy-rs/lora-phy", rev = "1323eccc1c470d4259f95f4f315d1be830d572a3"} \ No newline at end of file +lora-phy = { git = "https://github.com/embassy-rs/lora-phy", rev = "1323eccc1c470d4259f95f4f315d1be830d572a3"} diff --git a/embassy-net-enc28j60/Cargo.toml b/embassy-net-enc28j60/Cargo.toml index e02c984e..161d055c 100644 --- a/embassy-net-enc28j60/Cargo.toml +++ b/embassy-net-enc28j60/Cargo.toml @@ -11,7 +11,7 @@ edition = "2021" embedded-hal = { version = "1.0.0-rc.1" } embedded-hal-async = { version = "=1.0.0-rc.1" } embassy-net-driver = { version = "0.1.0", path = "../embassy-net-driver" } -embassy-time = { version = "0.1.2", path = "../embassy-time" } +embassy-time = { version = "0.1.3", path = "../embassy-time" } embassy-futures = { version = "0.1.0", path = "../embassy-futures" } defmt = { version = "0.3", optional = true } @@ -20,4 +20,4 @@ log = { version = "0.4.14", optional = true } [package.metadata.embassy_docs] src_base = "https://github.com/embassy-rs/embassy/blob/embassy-net-enc28j60-v$VERSION/embassy-net-enc28j60/src/" src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-net-enc28j60/src/" -target = "thumbv7em-none-eabi" \ No newline at end of file +target = "thumbv7em-none-eabi" diff --git a/embassy-net-esp-hosted/Cargo.toml b/embassy-net-esp-hosted/Cargo.toml index d334cf3f..67c86936 100644 --- a/embassy-net-esp-hosted/Cargo.toml +++ b/embassy-net-esp-hosted/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" defmt = { version = "0.3", optional = true } log = { version = "0.4.14", optional = true } -embassy-time = { version = "0.1.2", path = "../embassy-time" } +embassy-time = { version = "0.1.3", path = "../embassy-time" } embassy-sync = { version = "0.2.0", path = "../embassy-sync"} embassy-futures = { version = "0.1.0", path = "../embassy-futures"} embassy-net-driver-channel = { version = "0.1.0", path = "../embassy-net-driver-channel"} @@ -23,4 +23,4 @@ heapless = "0.7.16" src_base = "https://github.com/embassy-rs/embassy/blob/embassy-net-esp-hosted-v$VERSION/embassy-net-esp-hosted/src/" src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-net-esp-hosted/src/" target = "thumbv7em-none-eabi" -features = ["defmt"] \ No newline at end of file +features = ["defmt"] diff --git a/embassy-net-wiznet/Cargo.toml b/embassy-net-wiznet/Cargo.toml index adf0b45f..afa0d5cd 100644 --- a/embassy-net-wiznet/Cargo.toml +++ b/embassy-net-wiznet/Cargo.toml @@ -11,7 +11,7 @@ edition = "2021" embedded-hal = { version = "1.0.0-rc.1" } embedded-hal-async = { version = "=1.0.0-rc.1" } embassy-net-driver-channel = { version = "0.1.0", path = "../embassy-net-driver-channel" } -embassy-time = { version = "0.1.2", path = "../embassy-time" } +embassy-time = { version = "0.1.3", path = "../embassy-time" } embassy-futures = { version = "0.1.0", path = "../embassy-futures" } defmt = { version = "0.3", optional = true } @@ -19,4 +19,4 @@ defmt = { version = "0.3", optional = true } src_base = "https://github.com/embassy-rs/embassy/blob/embassy-net-wiznet-v$VERSION/embassy-net-wiznet/src/" src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-net-wiznet/src/" target = "thumbv7em-none-eabi" -features = ["defmt"] \ No newline at end of file +features = ["defmt"] diff --git a/embassy-net/Cargo.toml b/embassy-net/Cargo.toml index 0361f1db..c763d41c 100644 --- a/embassy-net/Cargo.toml +++ b/embassy-net/Cargo.toml @@ -51,7 +51,7 @@ smoltcp = { version = "0.10.0", default-features = false, features = [ ] } embassy-net-driver = { version = "0.1.0", path = "../embassy-net-driver" } -embassy-time = { version = "0.1.2", path = "../embassy-time" } +embassy-time = { version = "0.1.3", path = "../embassy-time" } embassy-sync = { version = "0.2.0", path = "../embassy-sync" } embedded-io-async = { version = "0.5.0", optional = true } diff --git a/embassy-nrf/Cargo.toml b/embassy-nrf/Cargo.toml index 67ec4eb9..e7afef26 100644 --- a/embassy-nrf/Cargo.toml +++ b/embassy-nrf/Cargo.toml @@ -91,7 +91,7 @@ _dppi = [] _gpio-p1 = [] [dependencies] -embassy-time = { version = "0.1.2", path = "../embassy-time", optional = true } +embassy-time = { version = "0.1.3", path = "../embassy-time", optional = true } embassy-sync = { version = "0.2.0", path = "../embassy-sync" } embassy-hal-internal = {version = "0.1.0", path = "../embassy-hal-internal", features = ["cortex-m", "prio-bits-3"] } embassy-embedded-hal = {version = "0.1.0", path = "../embassy-embedded-hal" } diff --git a/embassy-rp/Cargo.toml b/embassy-rp/Cargo.toml index 60143c2b..eebb6e3b 100644 --- a/embassy-rp/Cargo.toml +++ b/embassy-rp/Cargo.toml @@ -60,7 +60,7 @@ unstable-traits = ["embedded-hal-1", "embedded-hal-nb"] [dependencies] embassy-sync = { version = "0.2.0", path = "../embassy-sync" } -embassy-time = { version = "0.1.2", path = "../embassy-time", features = [ "tick-hz-1_000_000" ] } +embassy-time = { version = "0.1.3", path = "../embassy-time", features = [ "tick-hz-1_000_000" ] } embassy-futures = { version = "0.1.0", path = "../embassy-futures" } embassy-hal-internal = {version = "0.1.0", path = "../embassy-hal-internal", features = ["cortex-m", "prio-bits-2"] } embassy-embedded-hal = {version = "0.1.0", path = "../embassy-embedded-hal" } diff --git a/embassy-stm32-wpan/Cargo.toml b/embassy-stm32-wpan/Cargo.toml index 96c47484..7a4d3ec6 100644 --- a/embassy-stm32-wpan/Cargo.toml +++ b/embassy-stm32-wpan/Cargo.toml @@ -13,7 +13,7 @@ features = ["stm32wb55rg"] [dependencies] embassy-stm32 = { version = "0.1.0", path = "../embassy-stm32" } embassy-sync = { version = "0.2.0", path = "../embassy-sync" } -embassy-time = { version = "0.1.2", path = "../embassy-time", optional = true } +embassy-time = { version = "0.1.3", path = "../embassy-time", optional = true } embassy-futures = { version = "0.1.0", path = "../embassy-futures" } embassy-hal-internal = { version = "0.1.0", path = "../embassy-hal-internal" } embassy-embedded-hal = { version = "0.1.0", path = "../embassy-embedded-hal" } diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index d0ada97a..d169107d 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml @@ -32,7 +32,7 @@ flavors = [ [dependencies] embassy-sync = { version = "0.2.0", path = "../embassy-sync" } -embassy-time = { version = "0.1.2", path = "../embassy-time", optional = true } +embassy-time = { version = "0.1.3", path = "../embassy-time", optional = true } embassy-futures = { version = "0.1.0", path = "../embassy-futures" } embassy-hal-internal = {version = "0.1.0", path = "../embassy-hal-internal", features = ["cortex-m", "prio-bits-4"] } embassy-embedded-hal = {version = "0.1.0", path = "../embassy-embedded-hal" } diff --git a/embassy-time/CHANGELOG.md b/embassy-time/CHANGELOG.md index 26640d93..8bf02dbc 100644 --- a/embassy-time/CHANGELOG.md +++ b/embassy-time/CHANGELOG.md @@ -5,6 +5,11 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## 0.1.3 - 2023-08-28 + +- Update `embedded-hal-async` to `1.0.0-rc.1` +- Update `embedded-hal v1` to `1.0.0-rc.1` + ## 0.1.2 - 2023-07-05 - Update `embedded-hal-async` to `0.2.0-alpha.2`. @@ -26,4 +31,4 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## 0.1.0 - 2022-08-26 -- First release \ No newline at end of file +- First release diff --git a/embassy-time/Cargo.toml b/embassy-time/Cargo.toml index 00d31d30..03aa6ca2 100644 --- a/embassy-time/Cargo.toml +++ b/embassy-time/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "embassy-time" -version = "0.1.2" +version = "0.1.3" edition = "2021" description = "Instant and Duration for embedded no-std systems, with async timer support" repository = "https://github.com/embassy-rs/embassy" diff --git a/examples/boot/application/nrf/Cargo.toml b/examples/boot/application/nrf/Cargo.toml index 46ce7ba9..49f6eb13 100644 --- a/examples/boot/application/nrf/Cargo.toml +++ b/examples/boot/application/nrf/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-sync = { version = "0.2.0", path = "../../../../embassy-sync" } embassy-executor = { version = "0.3.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "nightly", "integrated-timers", "arch-cortex-m", "executor-thread"] } -embassy-time = { version = "0.1.2", path = "../../../../embassy-time", features = ["nightly"] } +embassy-time = { version = "0.1.3", path = "../../../../embassy-time", features = ["nightly"] } embassy-nrf = { version = "0.1.0", path = "../../../../embassy-nrf", features = ["time-driver-rtc1", "gpiote", "nightly"] } embassy-boot = { version = "0.1.0", path = "../../../../embassy-boot/boot", features = ["nightly"] } embassy-boot-nrf = { version = "0.1.0", path = "../../../../embassy-boot/nrf", features = ["nightly"] } diff --git a/examples/boot/application/rp/Cargo.toml b/examples/boot/application/rp/Cargo.toml index be85f443..e9d4fb32 100644 --- a/examples/boot/application/rp/Cargo.toml +++ b/examples/boot/application/rp/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-sync = { version = "0.2.0", path = "../../../../embassy-sync" } embassy-executor = { version = "0.3.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "nightly", "integrated-timers", "arch-cortex-m", "executor-thread"] } -embassy-time = { version = "0.1.2", path = "../../../../embassy-time", features = ["nightly"] } +embassy-time = { version = "0.1.3", path = "../../../../embassy-time", features = ["nightly"] } embassy-rp = { version = "0.1.0", path = "../../../../embassy-rp", features = ["time-driver", "unstable-traits", "nightly"] } embassy-boot-rp = { version = "0.1.0", path = "../../../../embassy-boot/rp", features = ["nightly"] } embassy-embedded-hal = { version = "0.1.0", path = "../../../../embassy-embedded-hal" } diff --git a/examples/boot/application/stm32f3/Cargo.toml b/examples/boot/application/stm32f3/Cargo.toml index ea878933..6a6f967b 100644 --- a/examples/boot/application/stm32f3/Cargo.toml +++ b/examples/boot/application/stm32f3/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-sync = { version = "0.2.0", path = "../../../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.3.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "nightly", "integrated-timers"] } -embassy-time = { version = "0.1.2", path = "../../../../embassy-time", features = ["nightly", "tick-hz-32_768"] } +embassy-time = { version = "0.1.3", path = "../../../../embassy-time", features = ["nightly", "tick-hz-32_768"] } embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["unstable-traits", "nightly", "stm32f303re", "time-driver-any", "exti"] } embassy-boot-stm32 = { version = "0.1.0", path = "../../../../embassy-boot/stm32", features = ["nightly"] } embassy-embedded-hal = { version = "0.1.0", path = "../../../../embassy-embedded-hal" } diff --git a/examples/boot/application/stm32f7/Cargo.toml b/examples/boot/application/stm32f7/Cargo.toml index b39bc292..55a631e9 100644 --- a/examples/boot/application/stm32f7/Cargo.toml +++ b/examples/boot/application/stm32f7/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-sync = { version = "0.2.0", path = "../../../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.3.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "nightly", "integrated-timers"] } -embassy-time = { version = "0.1.2", path = "../../../../embassy-time", features = ["nightly", "tick-hz-32_768"] } +embassy-time = { version = "0.1.3", path = "../../../../embassy-time", features = ["nightly", "tick-hz-32_768"] } embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["unstable-traits", "nightly", "stm32f767zi", "time-driver-any", "exti"] } embassy-boot-stm32 = { version = "0.1.0", path = "../../../../embassy-boot/stm32", features = ["nightly"] } embassy-embedded-hal = { version = "0.1.0", path = "../../../../embassy-embedded-hal" } diff --git a/examples/boot/application/stm32h7/Cargo.toml b/examples/boot/application/stm32h7/Cargo.toml index f015b2ca..ff960f22 100644 --- a/examples/boot/application/stm32h7/Cargo.toml +++ b/examples/boot/application/stm32h7/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-sync = { version = "0.2.0", path = "../../../../embassy-sync" } embassy-executor = { version = "0.3.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "nightly", "integrated-timers"] } -embassy-time = { version = "0.1.2", path = "../../../../embassy-time", features = ["nightly", "tick-hz-32_768"] } +embassy-time = { version = "0.1.3", path = "../../../../embassy-time", features = ["nightly", "tick-hz-32_768"] } embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["unstable-traits", "nightly", "stm32h743zi", "time-driver-any", "exti"] } embassy-boot-stm32 = { version = "0.1.0", path = "../../../../embassy-boot/stm32", features = ["nightly"] } embassy-embedded-hal = { version = "0.1.0", path = "../../../../embassy-embedded-hal" } diff --git a/examples/boot/application/stm32l0/Cargo.toml b/examples/boot/application/stm32l0/Cargo.toml index f221e1de..a0f88585 100644 --- a/examples/boot/application/stm32l0/Cargo.toml +++ b/examples/boot/application/stm32l0/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-sync = { version = "0.2.0", path = "../../../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.3.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "nightly", "integrated-timers"] } -embassy-time = { version = "0.1.2", path = "../../../../embassy-time", features = ["nightly", "tick-hz-32_768"] } +embassy-time = { version = "0.1.3", path = "../../../../embassy-time", features = ["nightly", "tick-hz-32_768"] } embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["unstable-traits", "nightly", "stm32l072cz", "time-driver-any", "exti", "memory-x"] } embassy-boot-stm32 = { version = "0.1.0", path = "../../../../embassy-boot/stm32", features = ["nightly"] } embassy-embedded-hal = { version = "0.1.0", path = "../../../../embassy-embedded-hal" } diff --git a/examples/boot/application/stm32l1/Cargo.toml b/examples/boot/application/stm32l1/Cargo.toml index 2896afa3..1a251df3 100644 --- a/examples/boot/application/stm32l1/Cargo.toml +++ b/examples/boot/application/stm32l1/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-sync = { version = "0.2.0", path = "../../../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.3.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "nightly", "integrated-timers"] } -embassy-time = { version = "0.1.2", path = "../../../../embassy-time", features = ["nightly", "tick-hz-32_768"] } +embassy-time = { version = "0.1.3", path = "../../../../embassy-time", features = ["nightly", "tick-hz-32_768"] } embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["unstable-traits", "nightly", "stm32l151cb-a", "time-driver-any", "exti"] } embassy-boot-stm32 = { version = "0.1.0", path = "../../../../embassy-boot/stm32", features = ["nightly"] } embassy-embedded-hal = { version = "0.1.0", path = "../../../../embassy-embedded-hal" } diff --git a/examples/boot/application/stm32l4/Cargo.toml b/examples/boot/application/stm32l4/Cargo.toml index 50d8967a..8d1c8af1 100644 --- a/examples/boot/application/stm32l4/Cargo.toml +++ b/examples/boot/application/stm32l4/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-sync = { version = "0.2.0", path = "../../../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.3.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "nightly", "integrated-timers"] } -embassy-time = { version = "0.1.2", path = "../../../../embassy-time", features = ["nightly", "tick-hz-32_768"] } +embassy-time = { version = "0.1.3", path = "../../../../embassy-time", features = ["nightly", "tick-hz-32_768"] } embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["unstable-traits", "nightly", "stm32l475vg", "time-driver-any", "exti"] } embassy-boot-stm32 = { version = "0.1.0", path = "../../../../embassy-boot/stm32", features = ["nightly"] } embassy-embedded-hal = { version = "0.1.0", path = "../../../../embassy-embedded-hal" } diff --git a/examples/boot/application/stm32wl/Cargo.toml b/examples/boot/application/stm32wl/Cargo.toml index 27541439..441b355a 100644 --- a/examples/boot/application/stm32wl/Cargo.toml +++ b/examples/boot/application/stm32wl/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-sync = { version = "0.2.0", path = "../../../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.3.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "nightly", "integrated-timers"] } -embassy-time = { version = "0.1.2", path = "../../../../embassy-time", features = ["nightly", "tick-hz-32_768"] } +embassy-time = { version = "0.1.3", path = "../../../../embassy-time", features = ["nightly", "tick-hz-32_768"] } embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["unstable-traits", "nightly", "stm32wl55jc-cm4", "time-driver-any", "exti"] } embassy-boot-stm32 = { version = "0.1.0", path = "../../../../embassy-boot/stm32", features = ["nightly"] } embassy-embedded-hal = { version = "0.1.0", path = "../../../../embassy-embedded-hal" } diff --git a/examples/nrf-rtos-trace/Cargo.toml b/examples/nrf-rtos-trace/Cargo.toml index b06722f5..ed6aca81 100644 --- a/examples/nrf-rtos-trace/Cargo.toml +++ b/examples/nrf-rtos-trace/Cargo.toml @@ -18,7 +18,7 @@ log = [ [dependencies] embassy-sync = { version = "0.2.0", path = "../../embassy-sync" } embassy-executor = { version = "0.3.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "rtos-trace", "rtos-trace-interrupt", "integrated-timers"] } -embassy-time = { version = "0.1.2", path = "../../embassy-time" } +embassy-time = { version = "0.1.3", path = "../../embassy-time" } embassy-nrf = { version = "0.1.0", path = "../../embassy-nrf", features = ["nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac"] } cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } diff --git a/examples/nrf52840-rtic/Cargo.toml b/examples/nrf52840-rtic/Cargo.toml index 715f1ecf..02a7f98b 100644 --- a/examples/nrf52840-rtic/Cargo.toml +++ b/examples/nrf52840-rtic/Cargo.toml @@ -9,7 +9,7 @@ rtic = { version = "2", features = ["thumbv7-backend"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] } -embassy-time = { version = "0.1.2", path = "../../embassy-time", features = ["nightly", "unstable-traits", "defmt", "defmt-timestamp-uptime", "generic-queue"] } +embassy-time = { version = "0.1.3", path = "../../embassy-time", features = ["nightly", "unstable-traits", "defmt", "defmt-timestamp-uptime", "generic-queue"] } embassy-nrf = { version = "0.1.0", path = "../../embassy-nrf", features = ["nightly", "unstable-traits", "defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } defmt = "0.3" diff --git a/examples/nrf52840/Cargo.toml b/examples/nrf52840/Cargo.toml index 1b2f1eb1..8b7121ab 100644 --- a/examples/nrf52840/Cargo.toml +++ b/examples/nrf52840/Cargo.toml @@ -31,7 +31,7 @@ nightly = [ embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.3.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] } -embassy-time = { version = "0.1.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } +embassy-time = { version = "0.1.3", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } embassy-nrf = { version = "0.1.0", path = "../../embassy-nrf", features = ["defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } embassy-net = { version = "0.1.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet"], optional = true } embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt", "msos-descriptor",], optional = true } @@ -67,4 +67,4 @@ microfft = "0.5.0" debug = 2 [patch.crates-io] -lora-phy = { git = "https://github.com/embassy-rs/lora-phy", rev = "1323eccc1c470d4259f95f4f315d1be830d572a3"} \ No newline at end of file +lora-phy = { git = "https://github.com/embassy-rs/lora-phy", rev = "1323eccc1c470d4259f95f4f315d1be830d572a3"} diff --git a/examples/nrf5340/Cargo.toml b/examples/nrf5340/Cargo.toml index 4968a79a..e423ad95 100644 --- a/examples/nrf5340/Cargo.toml +++ b/examples/nrf5340/Cargo.toml @@ -14,7 +14,7 @@ embassy-executor = { version = "0.3.0", path = "../../embassy-executor", feature "defmt", "integrated-timers", ] } -embassy-time = { version = "0.1.2", path = "../../embassy-time", features = [ +embassy-time = { version = "0.1.3", path = "../../embassy-time", features = [ "defmt", "defmt-timestamp-uptime", ] } diff --git a/examples/rp/Cargo.toml b/examples/rp/Cargo.toml index 3efc804a..3b086133 100644 --- a/examples/rp/Cargo.toml +++ b/examples/rp/Cargo.toml @@ -9,7 +9,7 @@ license = "MIT OR Apache-2.0" embassy-embedded-hal = { version = "0.1.0", path = "../../embassy-embedded-hal", features = ["defmt"] } embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.3.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 = ["nightly", "unstable-traits", "defmt", "defmt-timestamp-uptime"] } +embassy-time = { version = "0.1.3", path = "../../embassy-time", features = ["nightly", "unstable-traits", "defmt", "defmt-timestamp-uptime"] } embassy-rp = { version = "0.1.0", path = "../../embassy-rp", features = ["defmt", "unstable-traits", "nightly", "unstable-pac", "time-driver", "critical-section-impl"] } embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] } embassy-net = { version = "0.1.0", path = "../../embassy-net", features = ["defmt", "nightly", "tcp", "udp", "dhcpv4", "medium-ethernet"] } @@ -57,4 +57,4 @@ rand = { version = "0.8.5", default-features = false } debug = 2 [patch.crates-io] -lora-phy = { git = "https://github.com/embassy-rs/lora-phy", rev = "1323eccc1c470d4259f95f4f315d1be830d572a3"} \ No newline at end of file +lora-phy = { git = "https://github.com/embassy-rs/lora-phy", rev = "1323eccc1c470d4259f95f4f315d1be830d572a3"} diff --git a/examples/std/Cargo.toml b/examples/std/Cargo.toml index 7b0d0bda..ca061d68 100644 --- a/examples/std/Cargo.toml +++ b/examples/std/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["log"] } embassy-executor = { version = "0.3.0", path = "../../embassy-executor", features = ["arch-std", "executor-thread", "log", "nightly", "integrated-timers"] } -embassy-time = { version = "0.1.2", path = "../../embassy-time", features = ["log", "std", "nightly"] } +embassy-time = { version = "0.1.3", path = "../../embassy-time", features = ["log", "std", "nightly"] } embassy-net = { version = "0.1.0", path = "../../embassy-net", features=[ "std", "nightly", "log", "medium-ethernet", "medium-ip", "tcp", "udp", "dns", "dhcpv4", "proto-ipv6"] } embassy-net-tuntap = { version = "0.1.0", path = "../../embassy-net-tuntap" } embassy-net-ppp = { version = "0.1.0", path = "../../embassy-net-ppp", features = ["log"]} diff --git a/examples/stm32c0/Cargo.toml b/examples/stm32c0/Cargo.toml index 9d188513..a691be42 100644 --- a/examples/stm32c0/Cargo.toml +++ b/examples/stm32c0/Cargo.toml @@ -9,7 +9,7 @@ license = "MIT OR Apache-2.0" 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.3.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-time = { version = "0.1.3", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } defmt = "0.3" defmt-rtt = "0.4" diff --git a/examples/stm32f0/Cargo.toml b/examples/stm32f0/Cargo.toml index ca9ab1cf..894681d0 100644 --- a/examples/stm32f0/Cargo.toml +++ b/examples/stm32f0/Cargo.toml @@ -16,7 +16,7 @@ defmt-rtt = "0.4" panic-probe = "0.3" embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.3.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-time = { version = "0.1.3", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } static_cell = { version = "1.1", features = ["nightly"]} [profile.release] diff --git a/examples/stm32f1/Cargo.toml b/examples/stm32f1/Cargo.toml index 16796841..bec7bf65 100644 --- a/examples/stm32f1/Cargo.toml +++ b/examples/stm32f1/Cargo.toml @@ -9,7 +9,7 @@ license = "MIT OR Apache-2.0" 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.3.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-time = { version = "0.1.3", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } diff --git a/examples/stm32f2/Cargo.toml b/examples/stm32f2/Cargo.toml index 54eadd1a..7cc5747d 100644 --- a/examples/stm32f2/Cargo.toml +++ b/examples/stm32f2/Cargo.toml @@ -9,7 +9,7 @@ license = "MIT OR Apache-2.0" 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.3.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-time = { version = "0.1.3", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } defmt = "0.3" defmt-rtt = "0.4" diff --git a/examples/stm32f3/Cargo.toml b/examples/stm32f3/Cargo.toml index 5d8f5f74..ffacece5 100644 --- a/examples/stm32f3/Cargo.toml +++ b/examples/stm32f3/Cargo.toml @@ -9,7 +9,7 @@ license = "MIT OR Apache-2.0" 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.3.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-time = { version = "0.1.3", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } diff --git a/examples/stm32f4/Cargo.toml b/examples/stm32f4/Cargo.toml index ed456c5c..ca517df7 100644 --- a/examples/stm32f4/Cargo.toml +++ b/examples/stm32f4/Cargo.toml @@ -9,7 +9,7 @@ license = "MIT OR Apache-2.0" 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.3.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-time = { version = "0.1.3", 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/stm32f7/Cargo.toml b/examples/stm32f7/Cargo.toml index b658a964..f7a7fb8c 100644 --- a/examples/stm32f7/Cargo.toml +++ b/examples/stm32f7/Cargo.toml @@ -9,7 +9,7 @@ license = "MIT OR Apache-2.0" 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.3.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-time = { version = "0.1.3", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-net = { path = "../../embassy-net", features = ["defmt", "nightly", "tcp", "dhcpv4", "medium-ethernet"] } embedded-io-async = { version = "0.5.0" } embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] } diff --git a/examples/stm32g0/Cargo.toml b/examples/stm32g0/Cargo.toml index 4e88151a..474c2af8 100644 --- a/examples/stm32g0/Cargo.toml +++ b/examples/stm32g0/Cargo.toml @@ -9,7 +9,7 @@ license = "MIT OR Apache-2.0" 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.3.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-time = { version = "0.1.3", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } defmt = "0.3" defmt-rtt = "0.4" diff --git a/examples/stm32g4/Cargo.toml b/examples/stm32g4/Cargo.toml index 7bb05dbc..0c1cdd67 100644 --- a/examples/stm32g4/Cargo.toml +++ b/examples/stm32g4/Cargo.toml @@ -9,7 +9,7 @@ license = "MIT OR Apache-2.0" 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.3.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-time = { version = "0.1.3", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] } defmt = "0.3" diff --git a/examples/stm32h5/Cargo.toml b/examples/stm32h5/Cargo.toml index f7a1de63..d4b7d18c 100644 --- a/examples/stm32h5/Cargo.toml +++ b/examples/stm32h5/Cargo.toml @@ -9,7 +9,7 @@ license = "MIT OR Apache-2.0" 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.3.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-time = { version = "0.1.3", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "unstable-traits", "tick-hz-32_768"] } embassy-net = { path = "../../embassy-net", features = ["defmt", "nightly", "tcp", "dhcpv4", "medium-ethernet", "proto-ipv6"] } embedded-io-async = { version = "0.5.0" } embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] } diff --git a/examples/stm32h7/Cargo.toml b/examples/stm32h7/Cargo.toml index 1ee11b07..eda04e44 100644 --- a/examples/stm32h7/Cargo.toml +++ b/examples/stm32h7/Cargo.toml @@ -9,7 +9,7 @@ license = "MIT OR Apache-2.0" 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.3.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-time = { version = "0.1.3", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "unstable-traits", "tick-hz-32_768"] } embassy-net = { path = "../../embassy-net", features = ["defmt", "nightly", "tcp", "dhcpv4", "medium-ethernet", "proto-ipv6"] } embedded-io-async = { version = "0.5.0" } embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] } diff --git a/examples/stm32l0/Cargo.toml b/examples/stm32l0/Cargo.toml index d4e0da0b..d33e0378 100644 --- a/examples/stm32l0/Cargo.toml +++ b/examples/stm32l0/Cargo.toml @@ -14,7 +14,7 @@ nightly = ["embassy-stm32/nightly", "embassy-time/nightly", "embassy-time/unstab 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.3.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-time = { version = "0.1.3", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } 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 } @@ -39,4 +39,4 @@ static_cell = "1.1" debug = 2 [patch.crates-io] -lora-phy = { git = "https://github.com/embassy-rs/lora-phy", rev = "1323eccc1c470d4259f95f4f315d1be830d572a3"} \ No newline at end of file +lora-phy = { git = "https://github.com/embassy-rs/lora-phy", rev = "1323eccc1c470d4259f95f4f315d1be830d572a3"} diff --git a/examples/stm32l1/Cargo.toml b/examples/stm32l1/Cargo.toml index 192fd3e3..9bf633ce 100644 --- a/examples/stm32l1/Cargo.toml +++ b/examples/stm32l1/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.3.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-time = { version = "0.1.3", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32l151cb-a", "time-driver-any", "memory-x"] } defmt = "0.3" diff --git a/examples/stm32l4/Cargo.toml b/examples/stm32l4/Cargo.toml index e5be94ed..5fe1499e 100644 --- a/examples/stm32l4/Cargo.toml +++ b/examples/stm32l4/Cargo.toml @@ -9,7 +9,7 @@ license = "MIT OR Apache-2.0" embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "unstable-pac", "stm32l4s5qi", "memory-x", "time-driver-any", "exti", "unstable-traits", "chrono"] } embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.3.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", "unstable-traits", "nightly"] } +embassy-time = { version = "0.1.3", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768", "unstable-traits", "nightly"] } embassy-embedded-hal = { version = "0.1.0", path = "../../embassy-embedded-hal" } embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] } embassy-net-adin1110 = { version = "0.1.0", path = "../../embassy-net-adin1110", default-features = false } diff --git a/examples/stm32l5/Cargo.toml b/examples/stm32l5/Cargo.toml index b46c2570..d387ee62 100644 --- a/examples/stm32l5/Cargo.toml +++ b/examples/stm32l5/Cargo.toml @@ -9,7 +9,7 @@ license = "MIT OR Apache-2.0" 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.3.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-time = { version = "0.1.3", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "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", "nightly", "tcp", "dhcpv4", "medium-ethernet"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } diff --git a/examples/stm32u5/Cargo.toml b/examples/stm32u5/Cargo.toml index f928e7a6..403e5714 100644 --- a/examples/stm32u5/Cargo.toml +++ b/examples/stm32u5/Cargo.toml @@ -9,7 +9,7 @@ license = "MIT OR Apache-2.0" 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.3.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-time = { version = "0.1.3", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] } defmt = "0.3" diff --git a/examples/stm32wb/Cargo.toml b/examples/stm32wb/Cargo.toml index 16db92c1..81d9ec69 100644 --- a/examples/stm32wb/Cargo.toml +++ b/examples/stm32wb/Cargo.toml @@ -10,7 +10,7 @@ embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = [" 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.3.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-time = { version = "0.1.3", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-net = { version = "0.1.0", path = "../../embassy-net", features = ["defmt", "udp", "proto-ipv6", "medium-ieee802154", "nightly"], optional=true } defmt = "0.3" diff --git a/examples/stm32wl/Cargo.toml b/examples/stm32wl/Cargo.toml index 1c771ddc..3ea76cbb 100644 --- a/examples/stm32wl/Cargo.toml +++ b/examples/stm32wl/Cargo.toml @@ -9,7 +9,7 @@ license = "MIT OR Apache-2.0" 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.3.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-time = { version = "0.1.3", path = "../../embassy-time", features = ["nightly", "unstable-traits", "defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } 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" } @@ -32,4 +32,4 @@ chrono = { version = "^0.4", default-features = false } debug = 2 [patch.crates-io] -lora-phy = { git = "https://github.com/embassy-rs/lora-phy", rev = "1323eccc1c470d4259f95f4f315d1be830d572a3"} \ No newline at end of file +lora-phy = { git = "https://github.com/embassy-rs/lora-phy", rev = "1323eccc1c470d4259f95f4f315d1be830d572a3"} diff --git a/examples/wasm/Cargo.toml b/examples/wasm/Cargo.toml index 5b206d71..2999dc52 100644 --- a/examples/wasm/Cargo.toml +++ b/examples/wasm/Cargo.toml @@ -10,7 +10,7 @@ crate-type = ["cdylib"] [dependencies] embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["log"] } embassy-executor = { version = "0.3.0", path = "../../embassy-executor", features = ["arch-wasm", "executor-thread", "log", "nightly", "integrated-timers"] } -embassy-time = { version = "0.1.2", path = "../../embassy-time", features = ["log", "wasm", "nightly"] } +embassy-time = { version = "0.1.3", path = "../../embassy-time", features = ["log", "wasm", "nightly"] } wasm-logger = "0.2.0" wasm-bindgen = "0.2" diff --git a/tests/nrf/Cargo.toml b/tests/nrf/Cargo.toml index 4e31bed5..867bf272 100644 --- a/tests/nrf/Cargo.toml +++ b/tests/nrf/Cargo.toml @@ -10,7 +10,7 @@ teleprobe-meta = "1" embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt", "nightly"] } embassy-executor = { version = "0.3.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "nightly", "integrated-timers"] } -embassy-time = { version = "0.1.2", path = "../../embassy-time", features = ["defmt", "nightly", "unstable-traits", "defmt-timestamp-uptime"] } +embassy-time = { version = "0.1.3", path = "../../embassy-time", features = ["defmt", "nightly", "unstable-traits", "defmt-timestamp-uptime"] } embassy-nrf = { version = "0.1.0", path = "../../embassy-nrf", features = ["defmt", "nightly", "unstable-traits", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac"] } embedded-io-async = { version = "0.5.0" } embassy-net = { version = "0.1.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "nightly"] } @@ -25,4 +25,4 @@ defmt-rtt = "0.4" cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] } cortex-m-rt = "0.7.0" -panic-probe = { version = "0.3", features = ["print-defmt"] } \ No newline at end of file +panic-probe = { version = "0.3", features = ["print-defmt"] } diff --git a/tests/riscv32/Cargo.toml b/tests/riscv32/Cargo.toml index be610b1c..66ab34ec 100644 --- a/tests/riscv32/Cargo.toml +++ b/tests/riscv32/Cargo.toml @@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0" critical-section = { version = "1.1.1", features = ["restore-state-bool"] } embassy-sync = { version = "0.2.0", path = "../../embassy-sync" } embassy-executor = { version = "0.3.0", path = "../../embassy-executor", features = ["arch-riscv32", "nightly", "executor-thread"] } -embassy-time = { version = "0.1.2", path = "../../embassy-time" } +embassy-time = { version = "0.1.3", path = "../../embassy-time" } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } riscv-rt = "0.11" diff --git a/tests/rp/Cargo.toml b/tests/rp/Cargo.toml index c494b66e..d71db8bb 100644 --- a/tests/rp/Cargo.toml +++ b/tests/rp/Cargo.toml @@ -9,7 +9,7 @@ teleprobe-meta = "1.1" embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.3.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", "nightly", "unstable-traits"] } +embassy-time = { version = "0.1.3", path = "../../embassy-time", features = ["defmt", "nightly", "unstable-traits"] } embassy-rp = { version = "0.1.0", path = "../../embassy-rp", features = ["nightly", "defmt", "unstable-pac", "unstable-traits", "time-driver", "critical-section-impl", "intrinsics", "rom-v2-intrinsics", "run-from-ram"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } embassy-net = { version = "0.1.0", path = "../../embassy-net", features = ["defmt", "nightly", "tcp", "udp", "dhcpv4", "medium-ethernet"] } diff --git a/tests/stm32/Cargo.toml b/tests/stm32/Cargo.toml index 1f8c7373..c96b5a5a 100644 --- a/tests/stm32/Cargo.toml +++ b/tests/stm32/Cargo.toml @@ -31,7 +31,7 @@ teleprobe-meta = "1" embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.3.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", "tick-hz-32_768", "defmt-timestamp-uptime"] } +embassy-time = { version = "0.1.3", path = "../../embassy-time", features = ["defmt", "tick-hz-32_768", "defmt-timestamp-uptime"] } embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "unstable-pac", "memory-x", "time-driver-any"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } embassy-stm32-wpan = { version = "0.1.0", path = "../../embassy-stm32-wpan", optional = true, features = ["defmt", "stm32wb55rg", "ble"] } From 4098a61ef04e42294b182f4b0bf44ced97c706a0 Mon Sep 17 00:00:00 2001 From: Frostie314159 Date: Mon, 28 Aug 2023 21:02:38 +0200 Subject: [PATCH 082/106] cyw43: Fix warning in event.rs. Allow non_upper_case_globals, to prevent the compiler from spitting out a warning about the Event enum. --- cyw43/src/events.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cyw43/src/events.rs b/cyw43/src/events.rs index a94c49a0..ce0e7e37 100644 --- a/cyw43/src/events.rs +++ b/cyw43/src/events.rs @@ -1,5 +1,5 @@ #![allow(dead_code)] -#![allow(non_camel_case_types)] +#![allow(non_camel_case_types, non_upper_case_globals)] use core::cell::RefCell; From 05ee02b5933dc8e87f3714294d272aa4cb23aefb Mon Sep 17 00:00:00 2001 From: Frostie314159 Date: Mon, 28 Aug 2023 21:32:31 +0200 Subject: [PATCH 083/106] cyw43: Introduce seperate up/down functions. Create two helper functions, for setting the interface up/down. --- cyw43/src/control.rs | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/cyw43/src/control.rs b/cyw43/src/control.rs index c67614dd..d2f6e4a0 100644 --- a/cyw43/src/control.rs +++ b/cyw43/src/control.rs @@ -124,7 +124,7 @@ impl<'a> Control<'a> { Timer::after(Duration::from_millis(100)).await; // set wifi up - self.ioctl(IoctlType::Set, IOCTL_CMD_UP, 0, &mut []).await; + self.up().await; Timer::after(Duration::from_millis(100)).await; @@ -138,6 +138,16 @@ impl<'a> Control<'a> { debug!("INIT DONE"); } + /// Set the WiFi interface up. + async fn up(&mut self) { + self.ioctl(IoctlType::Set, IOCTL_CMD_UP, 0, &mut []).await; + } + + /// Set the interface down. + async fn down(&mut self) { + self.ioctl(IoctlType::Set, IOCTL_CMD_DOWN, 0, &mut []).await; + } + pub async fn set_power_management(&mut self, mode: PowerManagementMode) { // power save mode let mode_num = mode.mode(); @@ -256,13 +266,13 @@ impl<'a> Control<'a> { } // Temporarily set wifi down - self.ioctl(IoctlType::Set, IOCTL_CMD_DOWN, 0, &mut []).await; + self.down().await; // Turn off APSTA mode self.set_iovar_u32("apsta", 0).await; // Set wifi up again - self.ioctl(IoctlType::Set, IOCTL_CMD_UP, 0, &mut []).await; + self.up().await; // Turn on AP mode self.ioctl_set_u32(IOCTL_CMD_SET_AP, 0, 1).await; From e0256939141ab8e4670f58e87886d0266c1d462c Mon Sep 17 00:00:00 2001 From: Frostie314159 Date: Mon, 28 Aug 2023 21:34:14 +0200 Subject: [PATCH 084/106] cyw43: Create leave function on Control struct. Create a function, which disassociates us, from the currently connected infra. --- cyw43/src/consts.rs | 1 + cyw43/src/control.rs | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/cyw43/src/consts.rs b/cyw43/src/consts.rs index 1f655158..4e2836f3 100644 --- a/cyw43/src/consts.rs +++ b/cyw43/src/consts.rs @@ -96,6 +96,7 @@ pub(crate) const IOCTL_CMD_UP: u32 = 2; pub(crate) const IOCTL_CMD_DOWN: u32 = 3; pub(crate) const IOCTL_CMD_SET_SSID: u32 = 26; pub(crate) const IOCTL_CMD_SET_CHANNEL: u32 = 30; +pub(crate) const IOCTL_CMD_DISASSOC: u32 = 52; pub(crate) const IOCTL_CMD_ANTDIV: u32 = 64; pub(crate) const IOCTL_CMD_SET_AP: u32 = 118; pub(crate) const IOCTL_CMD_SET_VAR: u32 = 263; diff --git a/cyw43/src/control.rs b/cyw43/src/control.rs index d2f6e4a0..a6d1f0bf 100644 --- a/cyw43/src/control.rs +++ b/cyw43/src/control.rs @@ -433,6 +433,11 @@ impl<'a> Control<'a> { events: &self.events, } } + /// Leave the wifi, with which we are currently associated. + pub async fn leave(&mut self) { + self.ioctl(IoctlType::Set, IOCTL_CMD_DISASSOC, 0, &mut []).await; + info!("Disassociated") + } } pub struct Scanner<'a> { From b315c28d4eda4fe62747d7f626226862cbc92629 Mon Sep 17 00:00:00 2001 From: xoviat Date: Mon, 28 Aug 2023 15:30:29 -0500 Subject: [PATCH 085/106] stm32/rtc: remove rtc-debug and asbtract exti wakeup --- embassy-stm32/Cargo.toml | 3 +-- embassy-stm32/src/low_power.rs | 10 +--------- embassy-stm32/src/rtc/v2.rs | 26 ++++++++------------------ embassy-stm32/src/time_driver.rs | 2 -- 4 files changed, 10 insertions(+), 31 deletions(-) diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index ca421910..d0ada97a 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml @@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0" src_base = "https://github.com/embassy-rs/embassy/blob/embassy-stm32-v$VERSION/embassy-stm32/src/" src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-stm32/src/" -features = ["nightly", "defmt", "unstable-pac", "unstable-traits", "exti", "time-driver-any", "time", "low-power", "rtc-debug"] +features = ["nightly", "defmt", "unstable-pac", "unstable-traits", "exti", "time-driver-any", "time", "low-power"] flavors = [ { regex_feature = "stm32f0.*", target = "thumbv6m-none-eabi" }, { regex_feature = "stm32f1.*", target = "thumbv7m-none-eabi" }, @@ -90,7 +90,6 @@ defmt = ["dep:defmt", "bxcan/unstable-defmt", "embassy-sync/defmt", "embassy-emb exti = [] low-power = [ "dep:embassy-executor", "embassy-executor/arch-cortex-m" ] -rtc-debug = [] embassy-executor = [] ## Automatically generate `memory.x` file using [`stm32-metapac`](https://docs.rs/stm32-metapac/) diff --git a/embassy-stm32/src/low_power.rs b/embassy-stm32/src/low_power.rs index f9b5fde9..d0230ed7 100644 --- a/embassy-stm32/src/low_power.rs +++ b/embassy-stm32/src/low_power.rs @@ -89,9 +89,6 @@ impl Executor { self.time_driver.resume_time(); trace!("low power: resume time"); - - #[cfg(feature = "rtc-debug")] - cortex_m::asm::bkpt(); } pub(self) fn stop_with_rtc(&mut self, rtc: &'static Rtc) { @@ -102,8 +99,7 @@ impl Executor { crate::interrupt::typelevel::RTC_WKUP::unpend(); unsafe { crate::interrupt::typelevel::RTC_WKUP::enable() }; - EXTI.rtsr(0).modify(|w| w.set_line(22, true)); - EXTI.imr(0).modify(|w| w.set_line(22, true)); + rtc.enable_wakeup_line(); } fn configure_pwr(&mut self) { @@ -121,7 +117,6 @@ impl Executor { } trace!("low power: enter stop..."); - #[cfg(not(feature = "rtc-debug"))] self.scb.set_sleepdeep(); } @@ -144,9 +139,6 @@ impl Executor { /// /// This function never returns. pub fn run(&'static mut self, init: impl FnOnce(Spawner)) -> ! { - #[cfg(feature = "rtc-debug")] - trace!("low power: rtc debug enabled"); - init(unsafe { EXECUTOR.as_mut().unwrap() }.inner.spawner()); loop { diff --git a/embassy-stm32/src/rtc/v2.rs b/embassy-stm32/src/rtc/v2.rs index 7eb8a96c..49f66e95 100644 --- a/embassy-stm32/src/rtc/v2.rs +++ b/embassy-stm32/src/rtc/v2.rs @@ -75,21 +75,6 @@ impl super::Rtc { /// start the wakeup alarm and wtih a duration that is as close to but less than /// the requested duration, and record the instant the wakeup alarm was started pub(crate) fn start_wakeup_alarm(&self, requested_duration: embassy_time::Duration) { - #[cfg(feature = "rtc-debug")] - if critical_section::with(|cs| { - if let Some(instant) = self.stop_time.borrow(cs).take() { - self.stop_time.borrow(cs).replace(Some(instant)); - - Some(()) - } else { - None - } - }) - .is_some() - { - return; - } - use embassy_time::{Duration, TICK_HZ}; use crate::rcc::get_freqs; @@ -133,6 +118,14 @@ impl super::Rtc { critical_section::with(|cs| assert!(self.stop_time.borrow(cs).replace(Some(self.instant())).is_none())) } + #[cfg(feature = "low-power")] + pub(crate) fn enable_wakeup_line(&self) { + use crate::pac::EXTI; + + EXTI.rtsr(0).modify(|w| w.set_line(22, true)); + EXTI.imr(0).modify(|w| w.set_line(22, true)); + } + #[cfg(feature = "low-power")] /// stop the wakeup alarm and return the time elapsed since `start_wakeup_alarm` /// was called, otherwise none @@ -141,9 +134,6 @@ impl super::Rtc { trace!("rtc: stop wakeup alarm at {}", self.instant()); - #[cfg(feature = "rtc-debug")] - return None; - self.write(false, |regs| { regs.cr().modify(|w| w.set_wutie(false)); regs.cr().modify(|w| w.set_wute(false)); diff --git a/embassy-stm32/src/time_driver.rs b/embassy-stm32/src/time_driver.rs index d4442c23..99d423d0 100644 --- a/embassy-stm32/src/time_driver.rs +++ b/embassy-stm32/src/time_driver.rs @@ -363,7 +363,6 @@ impl RtcDriver { .start_wakeup_alarm(time_until_next_alarm); }); - #[cfg(not(feature = "rtc-debug"))] T::regs_gp16().cr1().modify(|w| w.set_cen(false)); Ok(()) @@ -375,7 +374,6 @@ impl RtcDriver { pub(crate) fn resume_time(&self) { self.stop_wakeup_alarm(); - #[cfg(not(feature = "rtc-debug"))] T::regs_gp16().cr1().modify(|w| w.set_cen(true)); } } From 70a5221b2e0d40a43794bf65fc4d84e0af8ab079 Mon Sep 17 00:00:00 2001 From: xoviat Date: Mon, 28 Aug 2023 15:34:08 -0500 Subject: [PATCH 086/106] stm32/bd: consolidate enable_rtc --- embassy-stm32/src/rcc/bd.rs | 39 +++++++------------------------------ 1 file changed, 7 insertions(+), 32 deletions(-) diff --git a/embassy-stm32/src/rcc/bd.rs b/embassy-stm32/src/rcc/bd.rs index 0fc116ed..4d8ed82a 100644 --- a/embassy-stm32/src/rcc/bd.rs +++ b/embassy-stm32/src/rcc/bd.rs @@ -87,13 +87,14 @@ impl BackupDomain { } #[cfg(any( - rtc_v2f0, rtc_v2f2, rtc_v2f3, rtc_v2f4, rtc_v2f7, rtc_v2h7, rtc_v2l0, rtc_v2l1, rtc_v2l4, rtc_v2wb + rtc_v2f0, rtc_v2f2, rtc_v2f3, rtc_v2f4, rtc_v2f7, rtc_v2h7, rtc_v2l0, rtc_v2l1, rtc_v2l4, rtc_v2wb, rtc_v3, + rtc_v3u5 ))] #[allow(dead_code)] pub fn enable_rtc() { let reg = Self::read(); - #[cfg(any(rtc_v2h7, rtc_v2l4, rtc_v2wb))] + #[cfg(any(rtc_v2h7, rtc_v2l4, rtc_v2wb, rtc_v3, rtc_v3u5))] assert!(!reg.lsecsson(), "RTC is not compatible with LSE CSS, yet."); if !reg.rtcen() { @@ -102,47 +103,21 @@ impl BackupDomain { Self::modify(|w| { // Reset - #[cfg(not(any(rtc_v2l0, rtc_v2l1)))] + #[cfg(not(any(rtc_v2l0, rtc_v2l1, rtc_v2f2)))] w.set_bdrst(false); w.set_rtcen(true); w.set_rtcsel(reg.rtcsel()); // Restore bcdr - #[cfg(any(rtc_v2l4, rtc_v2wb))] + #[cfg(any(rtc_v2l4, rtc_v2wb, rtc_v3, rtc_v3u5))] w.set_lscosel(reg.lscosel()); - #[cfg(any(rtc_v2l4, rtc_v2wb))] + #[cfg(any(rtc_v2l4, rtc_v2wb, rtc_v3, rtc_v3u5))] w.set_lscoen(reg.lscoen()); w.set_lseon(reg.lseon()); - #[cfg(any(rtc_v2f0, rtc_v2f7, rtc_v2h7, rtc_v2l4, rtc_v2wb))] - w.set_lsedrv(reg.lsedrv()); - w.set_lsebyp(reg.lsebyp()); - }); - } - } - - #[cfg(any(rtc_v3, rtc_v3u5))] - #[allow(dead_code)] - pub fn enable_rtc() { - let reg = Self::read(); - assert!(!reg.lsecsson(), "RTC is not compatible with LSE CSS, yet."); - - if !reg.rtcen() { - Self::modify(|w| w.set_bdrst(true)); - - Self::modify(|w| { - w.set_bdrst(false); - - w.set_rtcen(true); - w.set_rtcsel(reg.rtcsel()); - - // Restore bcdr - w.set_lscosel(reg.lscosel()); - w.set_lscoen(reg.lscoen()); - - w.set_lseon(reg.lseon()); + #[cfg(any(rtc_v2f0, rtc_v2f7, rtc_v2h7, rtc_v2l4, rtc_v2wb, rtc_v3, rtc_v3u5))] w.set_lsedrv(reg.lsedrv()); w.set_lsebyp(reg.lsebyp()); }); From e07f9435624ea739282665d09fe0f996c71ef54c Mon Sep 17 00:00:00 2001 From: xoviat Date: Mon, 28 Aug 2023 15:52:13 -0500 Subject: [PATCH 087/106] rustfmt --- embassy-stm32/src/low_power.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/embassy-stm32/src/low_power.rs b/embassy-stm32/src/low_power.rs index d0230ed7..7e678d32 100644 --- a/embassy-stm32/src/low_power.rs +++ b/embassy-stm32/src/low_power.rs @@ -6,7 +6,6 @@ use embassy_executor::*; use crate::interrupt; use crate::interrupt::typelevel::Interrupt; -use crate::pac::EXTI; use crate::rcc::low_power_ready; use crate::time_driver::{get_driver, RtcDriver}; From 6b8b145266faaa06f6483ccb8d227c8060c9a46d Mon Sep 17 00:00:00 2001 From: xoviat Date: Mon, 28 Aug 2023 16:17:42 -0500 Subject: [PATCH 088/106] stm32: revert changes to rcc f4 --- embassy-stm32/src/rcc/f4.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/embassy-stm32/src/rcc/f4.rs b/embassy-stm32/src/rcc/f4.rs index d8b689e4..10d3322a 100644 --- a/embassy-stm32/src/rcc/f4.rs +++ b/embassy-stm32/src/rcc/f4.rs @@ -17,7 +17,7 @@ use crate::{peripherals, Peripheral}; pub const HSI_FREQ: Hertz = Hertz(16_000_000); /// LSI speed -pub const LSI_FREQ: Hertz = Hertz(32_768); +pub const LSI_FREQ: Hertz = Hertz(32_000); /// Clocks configuration #[non_exhaustive] From 0eeefd3dbf86cc2a590a34a2e1ac2dd80204faf2 Mon Sep 17 00:00:00 2001 From: Frostie314159 Date: Tue, 29 Aug 2023 23:05:05 +0200 Subject: [PATCH 089/106] cyw43: Make Scanner public. --- cyw43/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cyw43/src/lib.rs b/cyw43/src/lib.rs index 30a3d5f2..6b124cf7 100644 --- a/cyw43/src/lib.rs +++ b/cyw43/src/lib.rs @@ -27,7 +27,7 @@ use ioctl::IoctlState; use crate::bus::Bus; pub use crate::bus::SpiBusCyw43; -pub use crate::control::{Control, Error as ControlError}; +pub use crate::control::{Control, Error as ControlError, Scanner}; pub use crate::runner::Runner; pub use crate::structs::BssInfo; From 975f2f23c0256f192838a5a5cd995faa9ad88f34 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Wed, 30 Aug 2023 01:04:43 +0200 Subject: [PATCH 090/106] net-ppp: return error when PPP link gets terminated by the peer. --- embassy-net-ppp/Cargo.toml | 2 +- embassy-net-ppp/src/lib.rs | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/embassy-net-ppp/Cargo.toml b/embassy-net-ppp/Cargo.toml index b2874c68..191577b5 100644 --- a/embassy-net-ppp/Cargo.toml +++ b/embassy-net-ppp/Cargo.toml @@ -18,7 +18,7 @@ log = { version = "0.4.14", optional = true } embedded-io-async = { version = "0.5.0" } embassy-net-driver-channel = { version = "0.1.0", path = "../embassy-net-driver-channel" } embassy-futures = { version = "0.1.0", path = "../embassy-futures" } -ppproto = { version = "0.1.1"} +ppproto = { version = "0.1.2"} embassy-sync = { version = "0.2.0", path = "../embassy-sync" } [package.metadata.embassy_docs] diff --git a/embassy-net-ppp/src/lib.rs b/embassy-net-ppp/src/lib.rs index ca87fbae..66496ee0 100644 --- a/embassy-net-ppp/src/lib.rs +++ b/embassy-net-ppp/src/lib.rs @@ -53,6 +53,8 @@ pub enum RunError { WriteZero, /// Writing to the serial got EOF. Eof, + /// PPP protocol was terminated by the peer + Terminated, } impl From> for RunError { @@ -128,6 +130,9 @@ impl<'d> Runner<'d> { let status = ppp.status(); match status.phase { + ppproto::Phase::Dead => { + return Err(RunError::Terminated); + } ppproto::Phase::Open => { if !was_up { on_ipv4_up(status.ipv4.unwrap()); From 6c165f8dc03455863bc123101d4f4a0dabdfcfbf Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Mon, 28 Aug 2023 01:53:15 +0200 Subject: [PATCH 091/106] sync/pipe: impl BufRead. --- embassy-sync/src/pipe.rs | 310 +++++++++++++++++++++----------- embassy-sync/src/ring_buffer.rs | 46 ++--- examples/rp/src/bin/pio_uart.rs | 10 +- 3 files changed, 233 insertions(+), 133 deletions(-) diff --git a/embassy-sync/src/pipe.rs b/embassy-sync/src/pipe.rs index 21d451ea..ec0cbbf2 100644 --- a/embassy-sync/src/pipe.rs +++ b/embassy-sync/src/pipe.rs @@ -1,7 +1,8 @@ //! Async byte stream pipe. -use core::cell::RefCell; +use core::cell::{RefCell, UnsafeCell}; use core::future::Future; +use core::ops::Range; use core::pin::Pin; use core::task::{Context, Poll}; @@ -82,17 +83,6 @@ where pipe: &'p Pipe, } -impl<'p, M, const N: usize> Clone for Reader<'p, M, N> -where - M: RawMutex, -{ - fn clone(&self) -> Self { - Reader { pipe: self.pipe } - } -} - -impl<'p, M, const N: usize> Copy for Reader<'p, M, N> where M: RawMutex {} - impl<'p, M, const N: usize> Reader<'p, M, N> where M: RawMutex, @@ -110,6 +100,29 @@ where pub fn try_read(&self, buf: &mut [u8]) -> Result { self.pipe.try_read(buf) } + + /// Return the contents of the internal buffer, filling it with more data from the inner reader if it is empty. + /// + /// If no bytes are currently available to read, this function waits until at least one byte is available. + /// + /// If the reader is at end-of-file (EOF), an empty slice is returned. + pub fn fill_buf(&mut self) -> FillBufFuture<'_, M, N> { + FillBufFuture { pipe: Some(self.pipe) } + } + + /// Try returning contents of the internal buffer. + /// + /// If no bytes are currently available to read, this function returns `Err(TryReadError::Empty)`. + /// + /// If the reader is at end-of-file (EOF), an empty slice is returned. + pub fn try_fill_buf(&mut self) -> Result<&[u8], TryReadError> { + unsafe { self.pipe.try_fill_buf_with_context(None) } + } + + /// Tell this buffer that `amt` bytes have been consumed from the buffer, so they should no longer be returned in calls to `fill_buf`. + pub fn consume(&mut self, amt: usize) { + self.pipe.consume(amt) + } } /// Future returned by [`Pipe::read`] and [`Reader::read`]. @@ -138,6 +151,35 @@ where impl<'p, M, const N: usize> Unpin for ReadFuture<'p, M, N> where M: RawMutex {} +/// Future returned by [`Pipe::fill_buf`] and [`Reader::fill_buf`]. +#[must_use = "futures do nothing unless you `.await` or poll them"] +pub struct FillBufFuture<'p, M, const N: usize> +where + M: RawMutex, +{ + pipe: Option<&'p Pipe>, +} + +impl<'p, M, const N: usize> Future for FillBufFuture<'p, M, N> +where + M: RawMutex, +{ + type Output = &'p [u8]; + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + let pipe = self.pipe.take().unwrap(); + match unsafe { pipe.try_fill_buf_with_context(Some(cx)) } { + Ok(buf) => Poll::Ready(buf), + Err(TryReadError::Empty) => { + self.pipe = Some(pipe); + Poll::Pending + } + } + } +} + +impl<'p, M, const N: usize> Unpin for FillBufFuture<'p, M, N> where M: RawMutex {} + /// Error returned by [`try_read`](Pipe::try_read). #[derive(PartialEq, Eq, Clone, Copy, Debug)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] @@ -162,67 +204,24 @@ struct PipeState { write_waker: WakerRegistration, } -impl PipeState { - const fn new() -> Self { - PipeState { - buffer: RingBuffer::new(), - read_waker: WakerRegistration::new(), - write_waker: WakerRegistration::new(), - } +#[repr(transparent)] +struct Buffer(UnsafeCell<[u8; N]>); + +impl Buffer { + unsafe fn get<'a>(&self, r: Range) -> &'a [u8] { + let p = self.0.get() as *const u8; + core::slice::from_raw_parts(p.add(r.start), r.end - r.start) } - fn clear(&mut self) { - self.buffer.clear(); - self.write_waker.wake(); - } - - fn try_read(&mut self, buf: &mut [u8]) -> Result { - self.try_read_with_context(None, buf) - } - - fn try_read_with_context(&mut self, cx: Option<&mut Context<'_>>, buf: &mut [u8]) -> Result { - if self.buffer.is_full() { - self.write_waker.wake(); - } - - let available = self.buffer.pop_buf(); - if available.is_empty() { - if let Some(cx) = cx { - self.read_waker.register(cx.waker()); - } - return Err(TryReadError::Empty); - } - - let n = available.len().min(buf.len()); - buf[..n].copy_from_slice(&available[..n]); - self.buffer.pop(n); - Ok(n) - } - - fn try_write(&mut self, buf: &[u8]) -> Result { - self.try_write_with_context(None, buf) - } - - fn try_write_with_context(&mut self, cx: Option<&mut Context<'_>>, buf: &[u8]) -> Result { - if self.buffer.is_empty() { - self.read_waker.wake(); - } - - let available = self.buffer.push_buf(); - if available.is_empty() { - if let Some(cx) = cx { - self.write_waker.register(cx.waker()); - } - return Err(TryWriteError::Full); - } - - let n = available.len().min(buf.len()); - available[..n].copy_from_slice(&buf[..n]); - self.buffer.push(n); - Ok(n) + unsafe fn get_mut<'a>(&self, r: Range) -> &'a mut [u8] { + let p = self.0.get() as *mut u8; + core::slice::from_raw_parts_mut(p.add(r.start), r.end - r.start) } } +unsafe impl Send for Buffer {} +unsafe impl Sync for Buffer {} + /// A bounded byte-oriented pipe for communicating between asynchronous tasks /// with backpressure. /// @@ -234,6 +233,7 @@ pub struct Pipe where M: RawMutex, { + buf: Buffer, inner: Mutex>>, } @@ -252,7 +252,12 @@ where /// ``` pub const fn new() -> Self { Self { - inner: Mutex::new(RefCell::new(PipeState::new())), + buf: Buffer(UnsafeCell::new([0; N])), + inner: Mutex::new(RefCell::new(PipeState { + buffer: RingBuffer::new(), + read_waker: WakerRegistration::new(), + write_waker: WakerRegistration::new(), + })), } } @@ -261,21 +266,91 @@ where } fn try_read_with_context(&self, cx: Option<&mut Context<'_>>, buf: &mut [u8]) -> Result { - self.lock(|c| c.try_read_with_context(cx, buf)) + self.inner.lock(|rc: &RefCell>| { + let s = &mut *rc.borrow_mut(); + + if s.buffer.is_full() { + s.write_waker.wake(); + } + + let available = unsafe { self.buf.get(s.buffer.pop_buf()) }; + if available.is_empty() { + if let Some(cx) = cx { + s.read_waker.register(cx.waker()); + } + return Err(TryReadError::Empty); + } + + let n = available.len().min(buf.len()); + buf[..n].copy_from_slice(&available[..n]); + s.buffer.pop(n); + Ok(n) + }) + } + + // safety: While the returned slice is alive, + // no `read` or `consume` methods in the pipe must be called. + unsafe fn try_fill_buf_with_context(&self, cx: Option<&mut Context<'_>>) -> Result<&[u8], TryReadError> { + self.inner.lock(|rc: &RefCell>| { + let s = &mut *rc.borrow_mut(); + + if s.buffer.is_full() { + s.write_waker.wake(); + } + + let available = unsafe { self.buf.get(s.buffer.pop_buf()) }; + if available.is_empty() { + if let Some(cx) = cx { + s.read_waker.register(cx.waker()); + } + return Err(TryReadError::Empty); + } + + Ok(available) + }) + } + + fn consume(&self, amt: usize) { + self.inner.lock(|rc: &RefCell>| { + let s = &mut *rc.borrow_mut(); + let available = s.buffer.pop_buf(); + assert!(amt <= available.len()); + s.buffer.pop(amt); + }) } fn try_write_with_context(&self, cx: Option<&mut Context<'_>>, buf: &[u8]) -> Result { - self.lock(|c| c.try_write_with_context(cx, buf)) + self.inner.lock(|rc: &RefCell>| { + let s = &mut *rc.borrow_mut(); + + if s.buffer.is_empty() { + s.read_waker.wake(); + } + + let available = unsafe { self.buf.get_mut(s.buffer.push_buf()) }; + if available.is_empty() { + if let Some(cx) = cx { + s.write_waker.register(cx.waker()); + } + return Err(TryWriteError::Full); + } + + let n = available.len().min(buf.len()); + available[..n].copy_from_slice(&buf[..n]); + s.buffer.push(n); + Ok(n) + }) } - /// Get a writer for this pipe. - pub fn writer(&self) -> Writer<'_, M, N> { - Writer { pipe: self } - } - - /// Get a reader for this pipe. - pub fn reader(&self) -> Reader<'_, M, N> { - Reader { pipe: self } + /// Split this pipe into a BufRead-capable reader and a writer. + /// + /// The reader and writer borrow the current pipe mutably, so it is not + /// possible to use it directly while they exist. This is needed because + /// implementing `BufRead` requires there is a single reader. + /// + /// The writer is cloneable, the reader is not. + pub fn split(&mut self) -> (Reader<'_, M, N>, Writer<'_, M, N>) { + (Reader { pipe: self }, Writer { pipe: self }) } /// Write some bytes to the pipe. @@ -312,7 +387,7 @@ where /// or return an error if the pipe is empty. See [`write`](Self::write) for a variant /// that waits instead of returning an error. pub fn try_write(&self, buf: &[u8]) -> Result { - self.lock(|c| c.try_write(buf)) + self.try_write_with_context(None, buf) } /// Read some bytes from the pipe. @@ -339,12 +414,17 @@ where /// or return an error if the pipe is empty. See [`read`](Self::read) for a variant /// that waits instead of returning an error. pub fn try_read(&self, buf: &mut [u8]) -> Result { - self.lock(|c| c.try_read(buf)) + self.try_read_with_context(None, buf) } /// Clear the data in the pipe's buffer. pub fn clear(&self) { - self.lock(|c| c.clear()) + self.inner.lock(|rc: &RefCell>| { + let s = &mut *rc.borrow_mut(); + + s.buffer.clear(); + s.write_waker.wake(); + }) } /// Return whether the pipe is full (no free space in the buffer) @@ -433,6 +513,16 @@ mod io_impls { } } + impl embedded_io_async::BufRead for Reader<'_, M, N> { + async fn fill_buf(&mut self) -> Result<&[u8], Self::Error> { + Ok(Reader::fill_buf(self).await) + } + + fn consume(&mut self, amt: usize) { + Reader::consume(self, amt) + } + } + impl embedded_io_async::ErrorType for Writer<'_, M, N> { type Error = Infallible; } @@ -457,43 +547,39 @@ mod tests { use super::*; use crate::blocking_mutex::raw::{CriticalSectionRawMutex, NoopRawMutex}; - fn capacity(c: &PipeState) -> usize { - N - c.buffer.len() - } - #[test] fn writing_once() { - let mut c = PipeState::<3>::new(); + let c = Pipe::::new(); assert!(c.try_write(&[1]).is_ok()); - assert_eq!(capacity(&c), 2); + assert_eq!(c.free_capacity(), 2); } #[test] fn writing_when_full() { - let mut c = PipeState::<3>::new(); + let c = Pipe::::new(); assert_eq!(c.try_write(&[42]), Ok(1)); assert_eq!(c.try_write(&[43]), Ok(1)); assert_eq!(c.try_write(&[44]), Ok(1)); assert_eq!(c.try_write(&[45]), Err(TryWriteError::Full)); - assert_eq!(capacity(&c), 0); + assert_eq!(c.free_capacity(), 0); } #[test] fn receiving_once_with_one_send() { - let mut c = PipeState::<3>::new(); + let c = Pipe::::new(); assert!(c.try_write(&[42]).is_ok()); let mut buf = [0; 16]; assert_eq!(c.try_read(&mut buf), Ok(1)); assert_eq!(buf[0], 42); - assert_eq!(capacity(&c), 3); + assert_eq!(c.free_capacity(), 3); } #[test] fn receiving_when_empty() { - let mut c = PipeState::<3>::new(); + let c = Pipe::::new(); let mut buf = [0; 16]; assert_eq!(c.try_read(&mut buf), Err(TryReadError::Empty)); - assert_eq!(capacity(&c), 3); + assert_eq!(c.free_capacity(), 3); } #[test] @@ -506,13 +592,37 @@ mod tests { } #[test] - fn cloning() { - let c = Pipe::::new(); - let r1 = c.reader(); - let w1 = c.writer(); + fn read_buf() { + let mut c = Pipe::::new(); + let (mut r, w) = c.split(); + assert!(w.try_write(&[42, 43]).is_ok()); + let buf = r.try_fill_buf().unwrap(); + assert_eq!(buf, &[42, 43]); + let buf = r.try_fill_buf().unwrap(); + assert_eq!(buf, &[42, 43]); + r.consume(1); + let buf = r.try_fill_buf().unwrap(); + assert_eq!(buf, &[43]); + r.consume(1); + assert_eq!(r.try_fill_buf(), Err(TryReadError::Empty)); + assert_eq!(w.try_write(&[44, 45, 46]), Ok(1)); + assert_eq!(w.try_write(&[45, 46]), Ok(2)); + let buf = r.try_fill_buf().unwrap(); + assert_eq!(buf, &[44]); // only one byte due to wraparound. + r.consume(1); + let buf = r.try_fill_buf().unwrap(); + assert_eq!(buf, &[45, 46]); + assert!(w.try_write(&[47]).is_ok()); + let buf = r.try_fill_buf().unwrap(); + assert_eq!(buf, &[45, 46, 47]); + r.consume(3); + } - let _ = r1.clone(); - let _ = w1.clone(); + #[test] + fn writer_is_cloneable() { + let mut c = Pipe::::new(); + let (_r, w) = c.split(); + let _ = w.clone(); } #[futures_test::test] diff --git a/embassy-sync/src/ring_buffer.rs b/embassy-sync/src/ring_buffer.rs index 52108402..d95ffa7c 100644 --- a/embassy-sync/src/ring_buffer.rs +++ b/embassy-sync/src/ring_buffer.rs @@ -1,5 +1,6 @@ +use core::ops::Range; + pub struct RingBuffer { - buf: [u8; N], start: usize, end: usize, empty: bool, @@ -8,27 +9,26 @@ pub struct RingBuffer { impl RingBuffer { pub const fn new() -> Self { Self { - buf: [0; N], start: 0, end: 0, empty: true, } } - pub fn push_buf(&mut self) -> &mut [u8] { + pub fn push_buf(&mut self) -> Range { if self.start == self.end && !self.empty { trace!(" ringbuf: push_buf empty"); - return &mut self.buf[..0]; + return 0..0; } let n = if self.start <= self.end { - self.buf.len() - self.end + N - self.end } else { self.start - self.end }; trace!(" ringbuf: push_buf {:?}..{:?}", self.end, self.end + n); - &mut self.buf[self.end..self.end + n] + self.end..self.end + n } pub fn push(&mut self, n: usize) { @@ -41,20 +41,20 @@ impl RingBuffer { self.empty = false; } - pub fn pop_buf(&mut self) -> &mut [u8] { + pub fn pop_buf(&mut self) -> Range { if self.empty { trace!(" ringbuf: pop_buf empty"); - return &mut self.buf[..0]; + return 0..0; } let n = if self.end <= self.start { - self.buf.len() - self.start + N - self.start } else { self.end - self.start }; trace!(" ringbuf: pop_buf {:?}..{:?}", self.start, self.start + n); - &mut self.buf[self.start..self.start + n] + self.start..self.start + n } pub fn pop(&mut self, n: usize) { @@ -93,8 +93,8 @@ impl RingBuffer { } fn wrap(&self, n: usize) -> usize { - assert!(n <= self.buf.len()); - if n == self.buf.len() { + assert!(n <= N); + if n == N { 0 } else { n @@ -110,37 +110,29 @@ mod tests { fn push_pop() { let mut rb: RingBuffer<4> = RingBuffer::new(); let buf = rb.push_buf(); - assert_eq!(4, buf.len()); - buf[0] = 1; - buf[1] = 2; - buf[2] = 3; - buf[3] = 4; + assert_eq!(0..4, buf); rb.push(4); let buf = rb.pop_buf(); - assert_eq!(4, buf.len()); - assert_eq!(1, buf[0]); + assert_eq!(0..4, buf); rb.pop(1); let buf = rb.pop_buf(); - assert_eq!(3, buf.len()); - assert_eq!(2, buf[0]); + assert_eq!(1..4, buf); rb.pop(1); let buf = rb.pop_buf(); - assert_eq!(2, buf.len()); - assert_eq!(3, buf[0]); + assert_eq!(2..4, buf); rb.pop(1); let buf = rb.pop_buf(); - assert_eq!(1, buf.len()); - assert_eq!(4, buf[0]); + assert_eq!(3..4, buf); rb.pop(1); let buf = rb.pop_buf(); - assert_eq!(0, buf.len()); + assert_eq!(0..0, buf); let buf = rb.push_buf(); - assert_eq!(4, buf.len()); + assert_eq!(0..4, buf); } } diff --git a/examples/rp/src/bin/pio_uart.rs b/examples/rp/src/bin/pio_uart.rs index 707c99b7..aa9e52cb 100644 --- a/examples/rp/src/bin/pio_uart.rs +++ b/examples/rp/src/bin/pio_uart.rs @@ -91,13 +91,11 @@ async fn main(_spawner: Spawner) { 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 mut usb_pipe: Pipe = Pipe::new(); + let (mut usb_pipe_reader, mut usb_pipe_writer) = usb_pipe.split(); - let uart_pipe: Pipe = Pipe::new(); - let mut uart_pipe_writer = uart_pipe.writer(); - let mut uart_pipe_reader = uart_pipe.reader(); + let mut uart_pipe: Pipe = Pipe::new(); + let (mut uart_pipe_reader, mut uart_pipe_writer) = uart_pipe.split(); let (mut usb_tx, mut usb_rx) = class.split(); From 5e613d9abbb945e7fc7d4c895d645bfad6a3d2c8 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Wed, 30 Aug 2023 01:37:18 +0200 Subject: [PATCH 092/106] Sync all fmt.rs files. --- cyw43/src/fmt.rs | 18 ++++++----- embassy-boot/boot/src/fmt.rs | 45 +++++++++++++++++++++++---- embassy-boot/nrf/src/fmt.rs | 45 +++++++++++++++++++++++---- embassy-boot/rp/src/fmt.rs | 45 +++++++++++++++++++++++---- embassy-boot/stm32/src/fmt.rs | 45 +++++++++++++++++++++++---- embassy-executor/src/fmt.rs | 45 +++++++++++++++++++++++---- embassy-futures/src/fmt.rs | 45 +++++++++++++++++++++++---- embassy-hal-internal/src/fmt.rs | 45 +++++++++++++++++++++++---- embassy-lora/src/fmt.rs | 45 +++++++++++++++++++++++---- embassy-net-driver-channel/src/fmt.rs | 45 +++++++++++++++++++++++---- embassy-net-enc28j60/src/fmt.rs | 45 +++++++++++++++++++++++---- embassy-net-esp-hosted/src/fmt.rs | 5 +-- embassy-net-ppp/src/fmt.rs | 5 +-- embassy-net/src/fmt.rs | 45 +++++++++++++++++++++++---- embassy-nrf/src/fmt.rs | 45 +++++++++++++++++++++++---- embassy-rp/src/fmt.rs | 45 +++++++++++++++++++++++---- embassy-stm32-wpan/src/fmt.rs | 45 +++++++++++++++++++++++---- embassy-stm32/src/fmt.rs | 45 +++++++++++++++++++++++---- embassy-sync/src/fmt.rs | 45 +++++++++++++++++++++++---- embassy-time/src/fmt.rs | 45 +++++++++++++++++++++++---- embassy-usb/src/fmt.rs | 45 +++++++++++++++++++++++---- 21 files changed, 719 insertions(+), 119 deletions(-) diff --git a/cyw43/src/fmt.rs b/cyw43/src/fmt.rs index 9534c101..78e583c1 100644 --- a/cyw43/src/fmt.rs +++ b/cyw43/src/fmt.rs @@ -83,14 +83,17 @@ macro_rules! todo { }; } +#[cfg(not(feature = "defmt"))] macro_rules! unreachable { ($($x:tt)*) => { - { - #[cfg(not(feature = "defmt"))] - ::core::unreachable!($($x)*); - #[cfg(feature = "defmt")] - ::defmt::unreachable!($($x)*); - } + ::core::unreachable!($($x)*) + }; +} + +#[cfg(feature = "defmt")] +macro_rules! unreachable { + ($($x:tt)*) => { + ::defmt::unreachable!($($x)*) }; } @@ -226,7 +229,8 @@ impl Try for Result { } } -pub struct Bytes<'a>(pub &'a [u8]); +#[allow(unused)] +pub(crate) struct Bytes<'a>(pub &'a [u8]); impl<'a> Debug for Bytes<'a> { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { diff --git a/embassy-boot/boot/src/fmt.rs b/embassy-boot/boot/src/fmt.rs index 06697081..78e583c1 100644 --- a/embassy-boot/boot/src/fmt.rs +++ b/embassy-boot/boot/src/fmt.rs @@ -1,6 +1,8 @@ #![macro_use] #![allow(unused_macros)] +use core::fmt::{Debug, Display, LowerHex}; + #[cfg(all(feature = "defmt", feature = "log"))] compile_error!("You may not enable both `defmt` and `log` features."); @@ -81,14 +83,17 @@ macro_rules! todo { }; } +#[cfg(not(feature = "defmt"))] macro_rules! unreachable { ($($x:tt)*) => { - { - #[cfg(not(feature = "defmt"))] - ::core::unreachable!($($x)*); - #[cfg(feature = "defmt")] - ::defmt::unreachable!($($x)*); - } + ::core::unreachable!($($x)*) + }; +} + +#[cfg(feature = "defmt")] +macro_rules! unreachable { + ($($x:tt)*) => { + ::defmt::unreachable!($($x)*) }; } @@ -223,3 +228,31 @@ impl Try for Result { self } } + +#[allow(unused)] +pub(crate) struct Bytes<'a>(pub &'a [u8]); + +impl<'a> Debug for Bytes<'a> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{:#02x?}", self.0) + } +} + +impl<'a> Display for Bytes<'a> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{:#02x?}", self.0) + } +} + +impl<'a> LowerHex for Bytes<'a> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{:#02x?}", self.0) + } +} + +#[cfg(feature = "defmt")] +impl<'a> defmt::Format for Bytes<'a> { + fn format(&self, fmt: defmt::Formatter) { + defmt::write!(fmt, "{:02x}", self.0) + } +} diff --git a/embassy-boot/nrf/src/fmt.rs b/embassy-boot/nrf/src/fmt.rs index 06697081..78e583c1 100644 --- a/embassy-boot/nrf/src/fmt.rs +++ b/embassy-boot/nrf/src/fmt.rs @@ -1,6 +1,8 @@ #![macro_use] #![allow(unused_macros)] +use core::fmt::{Debug, Display, LowerHex}; + #[cfg(all(feature = "defmt", feature = "log"))] compile_error!("You may not enable both `defmt` and `log` features."); @@ -81,14 +83,17 @@ macro_rules! todo { }; } +#[cfg(not(feature = "defmt"))] macro_rules! unreachable { ($($x:tt)*) => { - { - #[cfg(not(feature = "defmt"))] - ::core::unreachable!($($x)*); - #[cfg(feature = "defmt")] - ::defmt::unreachable!($($x)*); - } + ::core::unreachable!($($x)*) + }; +} + +#[cfg(feature = "defmt")] +macro_rules! unreachable { + ($($x:tt)*) => { + ::defmt::unreachable!($($x)*) }; } @@ -223,3 +228,31 @@ impl Try for Result { self } } + +#[allow(unused)] +pub(crate) struct Bytes<'a>(pub &'a [u8]); + +impl<'a> Debug for Bytes<'a> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{:#02x?}", self.0) + } +} + +impl<'a> Display for Bytes<'a> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{:#02x?}", self.0) + } +} + +impl<'a> LowerHex for Bytes<'a> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{:#02x?}", self.0) + } +} + +#[cfg(feature = "defmt")] +impl<'a> defmt::Format for Bytes<'a> { + fn format(&self, fmt: defmt::Formatter) { + defmt::write!(fmt, "{:02x}", self.0) + } +} diff --git a/embassy-boot/rp/src/fmt.rs b/embassy-boot/rp/src/fmt.rs index 06697081..78e583c1 100644 --- a/embassy-boot/rp/src/fmt.rs +++ b/embassy-boot/rp/src/fmt.rs @@ -1,6 +1,8 @@ #![macro_use] #![allow(unused_macros)] +use core::fmt::{Debug, Display, LowerHex}; + #[cfg(all(feature = "defmt", feature = "log"))] compile_error!("You may not enable both `defmt` and `log` features."); @@ -81,14 +83,17 @@ macro_rules! todo { }; } +#[cfg(not(feature = "defmt"))] macro_rules! unreachable { ($($x:tt)*) => { - { - #[cfg(not(feature = "defmt"))] - ::core::unreachable!($($x)*); - #[cfg(feature = "defmt")] - ::defmt::unreachable!($($x)*); - } + ::core::unreachable!($($x)*) + }; +} + +#[cfg(feature = "defmt")] +macro_rules! unreachable { + ($($x:tt)*) => { + ::defmt::unreachable!($($x)*) }; } @@ -223,3 +228,31 @@ impl Try for Result { self } } + +#[allow(unused)] +pub(crate) struct Bytes<'a>(pub &'a [u8]); + +impl<'a> Debug for Bytes<'a> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{:#02x?}", self.0) + } +} + +impl<'a> Display for Bytes<'a> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{:#02x?}", self.0) + } +} + +impl<'a> LowerHex for Bytes<'a> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{:#02x?}", self.0) + } +} + +#[cfg(feature = "defmt")] +impl<'a> defmt::Format for Bytes<'a> { + fn format(&self, fmt: defmt::Formatter) { + defmt::write!(fmt, "{:02x}", self.0) + } +} diff --git a/embassy-boot/stm32/src/fmt.rs b/embassy-boot/stm32/src/fmt.rs index 06697081..78e583c1 100644 --- a/embassy-boot/stm32/src/fmt.rs +++ b/embassy-boot/stm32/src/fmt.rs @@ -1,6 +1,8 @@ #![macro_use] #![allow(unused_macros)] +use core::fmt::{Debug, Display, LowerHex}; + #[cfg(all(feature = "defmt", feature = "log"))] compile_error!("You may not enable both `defmt` and `log` features."); @@ -81,14 +83,17 @@ macro_rules! todo { }; } +#[cfg(not(feature = "defmt"))] macro_rules! unreachable { ($($x:tt)*) => { - { - #[cfg(not(feature = "defmt"))] - ::core::unreachable!($($x)*); - #[cfg(feature = "defmt")] - ::defmt::unreachable!($($x)*); - } + ::core::unreachable!($($x)*) + }; +} + +#[cfg(feature = "defmt")] +macro_rules! unreachable { + ($($x:tt)*) => { + ::defmt::unreachable!($($x)*) }; } @@ -223,3 +228,31 @@ impl Try for Result { self } } + +#[allow(unused)] +pub(crate) struct Bytes<'a>(pub &'a [u8]); + +impl<'a> Debug for Bytes<'a> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{:#02x?}", self.0) + } +} + +impl<'a> Display for Bytes<'a> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{:#02x?}", self.0) + } +} + +impl<'a> LowerHex for Bytes<'a> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{:#02x?}", self.0) + } +} + +#[cfg(feature = "defmt")] +impl<'a> defmt::Format for Bytes<'a> { + fn format(&self, fmt: defmt::Formatter) { + defmt::write!(fmt, "{:02x}", self.0) + } +} diff --git a/embassy-executor/src/fmt.rs b/embassy-executor/src/fmt.rs index 06697081..78e583c1 100644 --- a/embassy-executor/src/fmt.rs +++ b/embassy-executor/src/fmt.rs @@ -1,6 +1,8 @@ #![macro_use] #![allow(unused_macros)] +use core::fmt::{Debug, Display, LowerHex}; + #[cfg(all(feature = "defmt", feature = "log"))] compile_error!("You may not enable both `defmt` and `log` features."); @@ -81,14 +83,17 @@ macro_rules! todo { }; } +#[cfg(not(feature = "defmt"))] macro_rules! unreachable { ($($x:tt)*) => { - { - #[cfg(not(feature = "defmt"))] - ::core::unreachable!($($x)*); - #[cfg(feature = "defmt")] - ::defmt::unreachable!($($x)*); - } + ::core::unreachable!($($x)*) + }; +} + +#[cfg(feature = "defmt")] +macro_rules! unreachable { + ($($x:tt)*) => { + ::defmt::unreachable!($($x)*) }; } @@ -223,3 +228,31 @@ impl Try for Result { self } } + +#[allow(unused)] +pub(crate) struct Bytes<'a>(pub &'a [u8]); + +impl<'a> Debug for Bytes<'a> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{:#02x?}", self.0) + } +} + +impl<'a> Display for Bytes<'a> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{:#02x?}", self.0) + } +} + +impl<'a> LowerHex for Bytes<'a> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{:#02x?}", self.0) + } +} + +#[cfg(feature = "defmt")] +impl<'a> defmt::Format for Bytes<'a> { + fn format(&self, fmt: defmt::Formatter) { + defmt::write!(fmt, "{:02x}", self.0) + } +} diff --git a/embassy-futures/src/fmt.rs b/embassy-futures/src/fmt.rs index 06697081..78e583c1 100644 --- a/embassy-futures/src/fmt.rs +++ b/embassy-futures/src/fmt.rs @@ -1,6 +1,8 @@ #![macro_use] #![allow(unused_macros)] +use core::fmt::{Debug, Display, LowerHex}; + #[cfg(all(feature = "defmt", feature = "log"))] compile_error!("You may not enable both `defmt` and `log` features."); @@ -81,14 +83,17 @@ macro_rules! todo { }; } +#[cfg(not(feature = "defmt"))] macro_rules! unreachable { ($($x:tt)*) => { - { - #[cfg(not(feature = "defmt"))] - ::core::unreachable!($($x)*); - #[cfg(feature = "defmt")] - ::defmt::unreachable!($($x)*); - } + ::core::unreachable!($($x)*) + }; +} + +#[cfg(feature = "defmt")] +macro_rules! unreachable { + ($($x:tt)*) => { + ::defmt::unreachable!($($x)*) }; } @@ -223,3 +228,31 @@ impl Try for Result { self } } + +#[allow(unused)] +pub(crate) struct Bytes<'a>(pub &'a [u8]); + +impl<'a> Debug for Bytes<'a> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{:#02x?}", self.0) + } +} + +impl<'a> Display for Bytes<'a> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{:#02x?}", self.0) + } +} + +impl<'a> LowerHex for Bytes<'a> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{:#02x?}", self.0) + } +} + +#[cfg(feature = "defmt")] +impl<'a> defmt::Format for Bytes<'a> { + fn format(&self, fmt: defmt::Formatter) { + defmt::write!(fmt, "{:02x}", self.0) + } +} diff --git a/embassy-hal-internal/src/fmt.rs b/embassy-hal-internal/src/fmt.rs index 06697081..78e583c1 100644 --- a/embassy-hal-internal/src/fmt.rs +++ b/embassy-hal-internal/src/fmt.rs @@ -1,6 +1,8 @@ #![macro_use] #![allow(unused_macros)] +use core::fmt::{Debug, Display, LowerHex}; + #[cfg(all(feature = "defmt", feature = "log"))] compile_error!("You may not enable both `defmt` and `log` features."); @@ -81,14 +83,17 @@ macro_rules! todo { }; } +#[cfg(not(feature = "defmt"))] macro_rules! unreachable { ($($x:tt)*) => { - { - #[cfg(not(feature = "defmt"))] - ::core::unreachable!($($x)*); - #[cfg(feature = "defmt")] - ::defmt::unreachable!($($x)*); - } + ::core::unreachable!($($x)*) + }; +} + +#[cfg(feature = "defmt")] +macro_rules! unreachable { + ($($x:tt)*) => { + ::defmt::unreachable!($($x)*) }; } @@ -223,3 +228,31 @@ impl Try for Result { self } } + +#[allow(unused)] +pub(crate) struct Bytes<'a>(pub &'a [u8]); + +impl<'a> Debug for Bytes<'a> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{:#02x?}", self.0) + } +} + +impl<'a> Display for Bytes<'a> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{:#02x?}", self.0) + } +} + +impl<'a> LowerHex for Bytes<'a> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{:#02x?}", self.0) + } +} + +#[cfg(feature = "defmt")] +impl<'a> defmt::Format for Bytes<'a> { + fn format(&self, fmt: defmt::Formatter) { + defmt::write!(fmt, "{:02x}", self.0) + } +} diff --git a/embassy-lora/src/fmt.rs b/embassy-lora/src/fmt.rs index 06697081..78e583c1 100644 --- a/embassy-lora/src/fmt.rs +++ b/embassy-lora/src/fmt.rs @@ -1,6 +1,8 @@ #![macro_use] #![allow(unused_macros)] +use core::fmt::{Debug, Display, LowerHex}; + #[cfg(all(feature = "defmt", feature = "log"))] compile_error!("You may not enable both `defmt` and `log` features."); @@ -81,14 +83,17 @@ macro_rules! todo { }; } +#[cfg(not(feature = "defmt"))] macro_rules! unreachable { ($($x:tt)*) => { - { - #[cfg(not(feature = "defmt"))] - ::core::unreachable!($($x)*); - #[cfg(feature = "defmt")] - ::defmt::unreachable!($($x)*); - } + ::core::unreachable!($($x)*) + }; +} + +#[cfg(feature = "defmt")] +macro_rules! unreachable { + ($($x:tt)*) => { + ::defmt::unreachable!($($x)*) }; } @@ -223,3 +228,31 @@ impl Try for Result { self } } + +#[allow(unused)] +pub(crate) struct Bytes<'a>(pub &'a [u8]); + +impl<'a> Debug for Bytes<'a> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{:#02x?}", self.0) + } +} + +impl<'a> Display for Bytes<'a> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{:#02x?}", self.0) + } +} + +impl<'a> LowerHex for Bytes<'a> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{:#02x?}", self.0) + } +} + +#[cfg(feature = "defmt")] +impl<'a> defmt::Format for Bytes<'a> { + fn format(&self, fmt: defmt::Formatter) { + defmt::write!(fmt, "{:02x}", self.0) + } +} diff --git a/embassy-net-driver-channel/src/fmt.rs b/embassy-net-driver-channel/src/fmt.rs index 06697081..78e583c1 100644 --- a/embassy-net-driver-channel/src/fmt.rs +++ b/embassy-net-driver-channel/src/fmt.rs @@ -1,6 +1,8 @@ #![macro_use] #![allow(unused_macros)] +use core::fmt::{Debug, Display, LowerHex}; + #[cfg(all(feature = "defmt", feature = "log"))] compile_error!("You may not enable both `defmt` and `log` features."); @@ -81,14 +83,17 @@ macro_rules! todo { }; } +#[cfg(not(feature = "defmt"))] macro_rules! unreachable { ($($x:tt)*) => { - { - #[cfg(not(feature = "defmt"))] - ::core::unreachable!($($x)*); - #[cfg(feature = "defmt")] - ::defmt::unreachable!($($x)*); - } + ::core::unreachable!($($x)*) + }; +} + +#[cfg(feature = "defmt")] +macro_rules! unreachable { + ($($x:tt)*) => { + ::defmt::unreachable!($($x)*) }; } @@ -223,3 +228,31 @@ impl Try for Result { self } } + +#[allow(unused)] +pub(crate) struct Bytes<'a>(pub &'a [u8]); + +impl<'a> Debug for Bytes<'a> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{:#02x?}", self.0) + } +} + +impl<'a> Display for Bytes<'a> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{:#02x?}", self.0) + } +} + +impl<'a> LowerHex for Bytes<'a> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{:#02x?}", self.0) + } +} + +#[cfg(feature = "defmt")] +impl<'a> defmt::Format for Bytes<'a> { + fn format(&self, fmt: defmt::Formatter) { + defmt::write!(fmt, "{:02x}", self.0) + } +} diff --git a/embassy-net-enc28j60/src/fmt.rs b/embassy-net-enc28j60/src/fmt.rs index 06697081..78e583c1 100644 --- a/embassy-net-enc28j60/src/fmt.rs +++ b/embassy-net-enc28j60/src/fmt.rs @@ -1,6 +1,8 @@ #![macro_use] #![allow(unused_macros)] +use core::fmt::{Debug, Display, LowerHex}; + #[cfg(all(feature = "defmt", feature = "log"))] compile_error!("You may not enable both `defmt` and `log` features."); @@ -81,14 +83,17 @@ macro_rules! todo { }; } +#[cfg(not(feature = "defmt"))] macro_rules! unreachable { ($($x:tt)*) => { - { - #[cfg(not(feature = "defmt"))] - ::core::unreachable!($($x)*); - #[cfg(feature = "defmt")] - ::defmt::unreachable!($($x)*); - } + ::core::unreachable!($($x)*) + }; +} + +#[cfg(feature = "defmt")] +macro_rules! unreachable { + ($($x:tt)*) => { + ::defmt::unreachable!($($x)*) }; } @@ -223,3 +228,31 @@ impl Try for Result { self } } + +#[allow(unused)] +pub(crate) struct Bytes<'a>(pub &'a [u8]); + +impl<'a> Debug for Bytes<'a> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{:#02x?}", self.0) + } +} + +impl<'a> Display for Bytes<'a> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{:#02x?}", self.0) + } +} + +impl<'a> LowerHex for Bytes<'a> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{:#02x?}", self.0) + } +} + +#[cfg(feature = "defmt")] +impl<'a> defmt::Format for Bytes<'a> { + fn format(&self, fmt: defmt::Formatter) { + defmt::write!(fmt, "{:02x}", self.0) + } +} diff --git a/embassy-net-esp-hosted/src/fmt.rs b/embassy-net-esp-hosted/src/fmt.rs index 91984bde..78e583c1 100644 --- a/embassy-net-esp-hosted/src/fmt.rs +++ b/embassy-net-esp-hosted/src/fmt.rs @@ -93,7 +93,7 @@ macro_rules! unreachable { #[cfg(feature = "defmt")] macro_rules! unreachable { ($($x:tt)*) => { - ::defmt::unreachable!($($x)*); + ::defmt::unreachable!($($x)*) }; } @@ -229,7 +229,8 @@ impl Try for Result { } } -pub struct Bytes<'a>(pub &'a [u8]); +#[allow(unused)] +pub(crate) struct Bytes<'a>(pub &'a [u8]); impl<'a> Debug for Bytes<'a> { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { diff --git a/embassy-net-ppp/src/fmt.rs b/embassy-net-ppp/src/fmt.rs index 91984bde..78e583c1 100644 --- a/embassy-net-ppp/src/fmt.rs +++ b/embassy-net-ppp/src/fmt.rs @@ -93,7 +93,7 @@ macro_rules! unreachable { #[cfg(feature = "defmt")] macro_rules! unreachable { ($($x:tt)*) => { - ::defmt::unreachable!($($x)*); + ::defmt::unreachable!($($x)*) }; } @@ -229,7 +229,8 @@ impl Try for Result { } } -pub struct Bytes<'a>(pub &'a [u8]); +#[allow(unused)] +pub(crate) struct Bytes<'a>(pub &'a [u8]); impl<'a> Debug for Bytes<'a> { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { diff --git a/embassy-net/src/fmt.rs b/embassy-net/src/fmt.rs index 06697081..78e583c1 100644 --- a/embassy-net/src/fmt.rs +++ b/embassy-net/src/fmt.rs @@ -1,6 +1,8 @@ #![macro_use] #![allow(unused_macros)] +use core::fmt::{Debug, Display, LowerHex}; + #[cfg(all(feature = "defmt", feature = "log"))] compile_error!("You may not enable both `defmt` and `log` features."); @@ -81,14 +83,17 @@ macro_rules! todo { }; } +#[cfg(not(feature = "defmt"))] macro_rules! unreachable { ($($x:tt)*) => { - { - #[cfg(not(feature = "defmt"))] - ::core::unreachable!($($x)*); - #[cfg(feature = "defmt")] - ::defmt::unreachable!($($x)*); - } + ::core::unreachable!($($x)*) + }; +} + +#[cfg(feature = "defmt")] +macro_rules! unreachable { + ($($x:tt)*) => { + ::defmt::unreachable!($($x)*) }; } @@ -223,3 +228,31 @@ impl Try for Result { self } } + +#[allow(unused)] +pub(crate) struct Bytes<'a>(pub &'a [u8]); + +impl<'a> Debug for Bytes<'a> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{:#02x?}", self.0) + } +} + +impl<'a> Display for Bytes<'a> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{:#02x?}", self.0) + } +} + +impl<'a> LowerHex for Bytes<'a> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{:#02x?}", self.0) + } +} + +#[cfg(feature = "defmt")] +impl<'a> defmt::Format for Bytes<'a> { + fn format(&self, fmt: defmt::Formatter) { + defmt::write!(fmt, "{:02x}", self.0) + } +} diff --git a/embassy-nrf/src/fmt.rs b/embassy-nrf/src/fmt.rs index 06697081..78e583c1 100644 --- a/embassy-nrf/src/fmt.rs +++ b/embassy-nrf/src/fmt.rs @@ -1,6 +1,8 @@ #![macro_use] #![allow(unused_macros)] +use core::fmt::{Debug, Display, LowerHex}; + #[cfg(all(feature = "defmt", feature = "log"))] compile_error!("You may not enable both `defmt` and `log` features."); @@ -81,14 +83,17 @@ macro_rules! todo { }; } +#[cfg(not(feature = "defmt"))] macro_rules! unreachable { ($($x:tt)*) => { - { - #[cfg(not(feature = "defmt"))] - ::core::unreachable!($($x)*); - #[cfg(feature = "defmt")] - ::defmt::unreachable!($($x)*); - } + ::core::unreachable!($($x)*) + }; +} + +#[cfg(feature = "defmt")] +macro_rules! unreachable { + ($($x:tt)*) => { + ::defmt::unreachable!($($x)*) }; } @@ -223,3 +228,31 @@ impl Try for Result { self } } + +#[allow(unused)] +pub(crate) struct Bytes<'a>(pub &'a [u8]); + +impl<'a> Debug for Bytes<'a> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{:#02x?}", self.0) + } +} + +impl<'a> Display for Bytes<'a> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{:#02x?}", self.0) + } +} + +impl<'a> LowerHex for Bytes<'a> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{:#02x?}", self.0) + } +} + +#[cfg(feature = "defmt")] +impl<'a> defmt::Format for Bytes<'a> { + fn format(&self, fmt: defmt::Formatter) { + defmt::write!(fmt, "{:02x}", self.0) + } +} diff --git a/embassy-rp/src/fmt.rs b/embassy-rp/src/fmt.rs index 06697081..78e583c1 100644 --- a/embassy-rp/src/fmt.rs +++ b/embassy-rp/src/fmt.rs @@ -1,6 +1,8 @@ #![macro_use] #![allow(unused_macros)] +use core::fmt::{Debug, Display, LowerHex}; + #[cfg(all(feature = "defmt", feature = "log"))] compile_error!("You may not enable both `defmt` and `log` features."); @@ -81,14 +83,17 @@ macro_rules! todo { }; } +#[cfg(not(feature = "defmt"))] macro_rules! unreachable { ($($x:tt)*) => { - { - #[cfg(not(feature = "defmt"))] - ::core::unreachable!($($x)*); - #[cfg(feature = "defmt")] - ::defmt::unreachable!($($x)*); - } + ::core::unreachable!($($x)*) + }; +} + +#[cfg(feature = "defmt")] +macro_rules! unreachable { + ($($x:tt)*) => { + ::defmt::unreachable!($($x)*) }; } @@ -223,3 +228,31 @@ impl Try for Result { self } } + +#[allow(unused)] +pub(crate) struct Bytes<'a>(pub &'a [u8]); + +impl<'a> Debug for Bytes<'a> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{:#02x?}", self.0) + } +} + +impl<'a> Display for Bytes<'a> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{:#02x?}", self.0) + } +} + +impl<'a> LowerHex for Bytes<'a> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{:#02x?}", self.0) + } +} + +#[cfg(feature = "defmt")] +impl<'a> defmt::Format for Bytes<'a> { + fn format(&self, fmt: defmt::Formatter) { + defmt::write!(fmt, "{:02x}", self.0) + } +} diff --git a/embassy-stm32-wpan/src/fmt.rs b/embassy-stm32-wpan/src/fmt.rs index 06697081..78e583c1 100644 --- a/embassy-stm32-wpan/src/fmt.rs +++ b/embassy-stm32-wpan/src/fmt.rs @@ -1,6 +1,8 @@ #![macro_use] #![allow(unused_macros)] +use core::fmt::{Debug, Display, LowerHex}; + #[cfg(all(feature = "defmt", feature = "log"))] compile_error!("You may not enable both `defmt` and `log` features."); @@ -81,14 +83,17 @@ macro_rules! todo { }; } +#[cfg(not(feature = "defmt"))] macro_rules! unreachable { ($($x:tt)*) => { - { - #[cfg(not(feature = "defmt"))] - ::core::unreachable!($($x)*); - #[cfg(feature = "defmt")] - ::defmt::unreachable!($($x)*); - } + ::core::unreachable!($($x)*) + }; +} + +#[cfg(feature = "defmt")] +macro_rules! unreachable { + ($($x:tt)*) => { + ::defmt::unreachable!($($x)*) }; } @@ -223,3 +228,31 @@ impl Try for Result { self } } + +#[allow(unused)] +pub(crate) struct Bytes<'a>(pub &'a [u8]); + +impl<'a> Debug for Bytes<'a> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{:#02x?}", self.0) + } +} + +impl<'a> Display for Bytes<'a> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{:#02x?}", self.0) + } +} + +impl<'a> LowerHex for Bytes<'a> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{:#02x?}", self.0) + } +} + +#[cfg(feature = "defmt")] +impl<'a> defmt::Format for Bytes<'a> { + fn format(&self, fmt: defmt::Formatter) { + defmt::write!(fmt, "{:02x}", self.0) + } +} diff --git a/embassy-stm32/src/fmt.rs b/embassy-stm32/src/fmt.rs index 06697081..78e583c1 100644 --- a/embassy-stm32/src/fmt.rs +++ b/embassy-stm32/src/fmt.rs @@ -1,6 +1,8 @@ #![macro_use] #![allow(unused_macros)] +use core::fmt::{Debug, Display, LowerHex}; + #[cfg(all(feature = "defmt", feature = "log"))] compile_error!("You may not enable both `defmt` and `log` features."); @@ -81,14 +83,17 @@ macro_rules! todo { }; } +#[cfg(not(feature = "defmt"))] macro_rules! unreachable { ($($x:tt)*) => { - { - #[cfg(not(feature = "defmt"))] - ::core::unreachable!($($x)*); - #[cfg(feature = "defmt")] - ::defmt::unreachable!($($x)*); - } + ::core::unreachable!($($x)*) + }; +} + +#[cfg(feature = "defmt")] +macro_rules! unreachable { + ($($x:tt)*) => { + ::defmt::unreachable!($($x)*) }; } @@ -223,3 +228,31 @@ impl Try for Result { self } } + +#[allow(unused)] +pub(crate) struct Bytes<'a>(pub &'a [u8]); + +impl<'a> Debug for Bytes<'a> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{:#02x?}", self.0) + } +} + +impl<'a> Display for Bytes<'a> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{:#02x?}", self.0) + } +} + +impl<'a> LowerHex for Bytes<'a> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{:#02x?}", self.0) + } +} + +#[cfg(feature = "defmt")] +impl<'a> defmt::Format for Bytes<'a> { + fn format(&self, fmt: defmt::Formatter) { + defmt::write!(fmt, "{:02x}", self.0) + } +} diff --git a/embassy-sync/src/fmt.rs b/embassy-sync/src/fmt.rs index 06697081..78e583c1 100644 --- a/embassy-sync/src/fmt.rs +++ b/embassy-sync/src/fmt.rs @@ -1,6 +1,8 @@ #![macro_use] #![allow(unused_macros)] +use core::fmt::{Debug, Display, LowerHex}; + #[cfg(all(feature = "defmt", feature = "log"))] compile_error!("You may not enable both `defmt` and `log` features."); @@ -81,14 +83,17 @@ macro_rules! todo { }; } +#[cfg(not(feature = "defmt"))] macro_rules! unreachable { ($($x:tt)*) => { - { - #[cfg(not(feature = "defmt"))] - ::core::unreachable!($($x)*); - #[cfg(feature = "defmt")] - ::defmt::unreachable!($($x)*); - } + ::core::unreachable!($($x)*) + }; +} + +#[cfg(feature = "defmt")] +macro_rules! unreachable { + ($($x:tt)*) => { + ::defmt::unreachable!($($x)*) }; } @@ -223,3 +228,31 @@ impl Try for Result { self } } + +#[allow(unused)] +pub(crate) struct Bytes<'a>(pub &'a [u8]); + +impl<'a> Debug for Bytes<'a> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{:#02x?}", self.0) + } +} + +impl<'a> Display for Bytes<'a> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{:#02x?}", self.0) + } +} + +impl<'a> LowerHex for Bytes<'a> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{:#02x?}", self.0) + } +} + +#[cfg(feature = "defmt")] +impl<'a> defmt::Format for Bytes<'a> { + fn format(&self, fmt: defmt::Formatter) { + defmt::write!(fmt, "{:02x}", self.0) + } +} diff --git a/embassy-time/src/fmt.rs b/embassy-time/src/fmt.rs index 06697081..78e583c1 100644 --- a/embassy-time/src/fmt.rs +++ b/embassy-time/src/fmt.rs @@ -1,6 +1,8 @@ #![macro_use] #![allow(unused_macros)] +use core::fmt::{Debug, Display, LowerHex}; + #[cfg(all(feature = "defmt", feature = "log"))] compile_error!("You may not enable both `defmt` and `log` features."); @@ -81,14 +83,17 @@ macro_rules! todo { }; } +#[cfg(not(feature = "defmt"))] macro_rules! unreachable { ($($x:tt)*) => { - { - #[cfg(not(feature = "defmt"))] - ::core::unreachable!($($x)*); - #[cfg(feature = "defmt")] - ::defmt::unreachable!($($x)*); - } + ::core::unreachable!($($x)*) + }; +} + +#[cfg(feature = "defmt")] +macro_rules! unreachable { + ($($x:tt)*) => { + ::defmt::unreachable!($($x)*) }; } @@ -223,3 +228,31 @@ impl Try for Result { self } } + +#[allow(unused)] +pub(crate) struct Bytes<'a>(pub &'a [u8]); + +impl<'a> Debug for Bytes<'a> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{:#02x?}", self.0) + } +} + +impl<'a> Display for Bytes<'a> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{:#02x?}", self.0) + } +} + +impl<'a> LowerHex for Bytes<'a> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{:#02x?}", self.0) + } +} + +#[cfg(feature = "defmt")] +impl<'a> defmt::Format for Bytes<'a> { + fn format(&self, fmt: defmt::Formatter) { + defmt::write!(fmt, "{:02x}", self.0) + } +} diff --git a/embassy-usb/src/fmt.rs b/embassy-usb/src/fmt.rs index 06697081..78e583c1 100644 --- a/embassy-usb/src/fmt.rs +++ b/embassy-usb/src/fmt.rs @@ -1,6 +1,8 @@ #![macro_use] #![allow(unused_macros)] +use core::fmt::{Debug, Display, LowerHex}; + #[cfg(all(feature = "defmt", feature = "log"))] compile_error!("You may not enable both `defmt` and `log` features."); @@ -81,14 +83,17 @@ macro_rules! todo { }; } +#[cfg(not(feature = "defmt"))] macro_rules! unreachable { ($($x:tt)*) => { - { - #[cfg(not(feature = "defmt"))] - ::core::unreachable!($($x)*); - #[cfg(feature = "defmt")] - ::defmt::unreachable!($($x)*); - } + ::core::unreachable!($($x)*) + }; +} + +#[cfg(feature = "defmt")] +macro_rules! unreachable { + ($($x:tt)*) => { + ::defmt::unreachable!($($x)*) }; } @@ -223,3 +228,31 @@ impl Try for Result { self } } + +#[allow(unused)] +pub(crate) struct Bytes<'a>(pub &'a [u8]); + +impl<'a> Debug for Bytes<'a> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{:#02x?}", self.0) + } +} + +impl<'a> Display for Bytes<'a> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{:#02x?}", self.0) + } +} + +impl<'a> LowerHex for Bytes<'a> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{:#02x?}", self.0) + } +} + +#[cfg(feature = "defmt")] +impl<'a> defmt::Format for Bytes<'a> { + fn format(&self, fmt: defmt::Formatter) { + defmt::write!(fmt, "{:02x}", self.0) + } +} From 989c98f316df3cde4512066e3682debb47d48161 Mon Sep 17 00:00:00 2001 From: xoviat Date: Tue, 29 Aug 2023 19:41:03 -0500 Subject: [PATCH 093/106] stm32/rtc: autocompute prescalers --- embassy-stm32/src/rcc/f4.rs | 1 + embassy-stm32/src/rcc/mod.rs | 6 ++- embassy-stm32/src/rtc/mod.rs | 72 +++++++++++++++--------------------- embassy-stm32/src/rtc/v2.rs | 6 +-- embassy-stm32/src/rtc/v3.rs | 6 +-- 5 files changed, 41 insertions(+), 50 deletions(-) diff --git a/embassy-stm32/src/rcc/f4.rs b/embassy-stm32/src/rcc/f4.rs index 10d3322a..c2c78a45 100644 --- a/embassy-stm32/src/rcc/f4.rs +++ b/embassy-stm32/src/rcc/f4.rs @@ -499,6 +499,7 @@ pub(crate) unsafe fn init(config: Config) { pllsai: None, rtc: rtc, + rtc_hse: None, }); } diff --git a/embassy-stm32/src/rcc/mod.rs b/embassy-stm32/src/rcc/mod.rs index 9f1b3b66..1ead60b1 100644 --- a/embassy-stm32/src/rcc/mod.rs +++ b/embassy-stm32/src/rcc/mod.rs @@ -78,8 +78,12 @@ pub struct Clocks { pub adc: Option, #[cfg(any(rcc_wb, rcc_f4, rcc_f410))] - /// Set only if the lsi or lse is configured + /// Set only if the lsi or lse is configured, indicates stop is supported pub rtc: Option, + + #[cfg(any(rcc_f4, rcc_f410))] + /// Set if the hse is configured, indicates stop is not supported + pub rtc_hse: Option, } #[cfg(feature = "low-power")] diff --git a/embassy-stm32/src/rtc/mod.rs b/embassy-stm32/src/rtc/mod.rs index 796fd7d9..3704e446 100644 --- a/embassy-stm32/src/rtc/mod.rs +++ b/embassy-stm32/src/rtc/mod.rs @@ -12,6 +12,7 @@ use embassy_sync::blocking_mutex::Mutex; pub use self::datetime::{DateTime, DayOfWeek, Error as DateTimeError}; use crate::rcc::bd::BackupDomain; pub use crate::rcc::RtcClockSource; +use crate::time::Hertz; /// refer to AN4759 to compare features of RTC2 and RTC3 #[cfg_attr(any(rtc_v1), path = "v1.rs")] @@ -84,47 +85,23 @@ impl core::ops::Sub for RtcInstant { /// RTC Abstraction pub struct Rtc { - rtc_config: RtcConfig, #[cfg(feature = "low-power")] stop_time: Mutex>>, } #[derive(Copy, Clone, PartialEq)] pub struct RtcConfig { - /// Asynchronous prescaler factor - /// This is the asynchronous division factor: - /// ck_apre frequency = RTCCLK frequency/(PREDIV_A+1) - /// ck_apre drives the subsecond register - async_prescaler: u8, - /// Synchronous prescaler factor - /// This is the synchronous division factor: - /// ck_spre frequency = ck_apre frequency/(PREDIV_S+1) - /// ck_spre must be 1Hz - sync_prescaler: u16, + /// The subsecond counter frequency; default is 256 + /// + /// A high counter frequency may impact stop power consumption + pub frequency: Hertz, } impl Default for RtcConfig { /// LSI with prescalers assuming 32.768 kHz. /// Raw sub-seconds in 1/256. fn default() -> Self { - RtcConfig { - async_prescaler: 127, - sync_prescaler: 255, - } - } -} - -impl RtcConfig { - /// Set the asynchronous prescaler of RTC config - pub fn async_prescaler(mut self, prescaler: u8) -> Self { - self.async_prescaler = prescaler; - self - } - - /// Set the synchronous prescaler of RTC config - pub fn sync_prescaler(mut self, prescaler: u16) -> Self { - self.sync_prescaler = prescaler; - self + RtcConfig { frequency: Hertz(256) } } } @@ -147,23 +124,36 @@ impl Default for RtcCalibrationCyclePeriod { impl Rtc { pub fn new(_rtc: impl Peripheral

, rtc_config: RtcConfig) -> Self { + use crate::rcc::get_freqs; + RTC::enable_peripheral_clk(); + BackupDomain::enable_rtc(); - #[cfg(not(feature = "low-power"))] - let mut rtc_struct = Self { rtc_config }; - - #[cfg(feature = "low-power")] - let mut rtc_struct = Self { - rtc_config, + let mut this = Self { + #[cfg(feature = "low-power")] stop_time: Mutex::const_new(CriticalSectionRawMutex::new(), Cell::new(None)), }; - BackupDomain::enable_rtc(); + #[cfg(any(rcc_wb, rcc_f4, rcc_f410))] + let freqs = unsafe { get_freqs() }; - rtc_struct.configure(rtc_config); - rtc_struct.rtc_config = rtc_config; + // Load the clock frequency from the rcc mod, if supported + #[cfg(any(rcc_wb, rcc_f4, rcc_f410))] + let frequency = match freqs.rtc { + Some(hertz) => hertz, + None => freqs.rtc_hse.unwrap(), + }; - rtc_struct + // Assume the default value, if not supported + #[cfg(not(any(rcc_wb, rcc_f4, rcc_f410)))] + let frequency = Hertz(32_768); + + let async_psc = ((frequency.0 / rtc_config.frequency.0) - 1) as u8; + let sync_psc = (rtc_config.frequency.0 - 1) as u16; + + this.configure(async_psc, sync_psc); + + this } /// Set the datetime to a new value. @@ -228,10 +218,6 @@ impl Rtc { }) } - pub fn get_config(&self) -> RtcConfig { - self.rtc_config - } - pub const BACKUP_REGISTER_COUNT: usize = RTC::BACKUP_REGISTER_COUNT; /// Read content of the backup register. diff --git a/embassy-stm32/src/rtc/v2.rs b/embassy-stm32/src/rtc/v2.rs index 49f66e95..63d9f09e 100644 --- a/embassy-stm32/src/rtc/v2.rs +++ b/embassy-stm32/src/rtc/v2.rs @@ -154,7 +154,7 @@ impl super::Rtc { /// Applies the RTC config /// It this changes the RTC clock source the time will be reset - pub(super) fn configure(&mut self, rtc_config: RtcConfig) { + pub(super) fn configure(&mut self, async_psc: u8, sync_psc: u16) { self.write(true, |rtc| { rtc.cr().modify(|w| { #[cfg(rtc_v2f2)] @@ -166,8 +166,8 @@ impl super::Rtc { }); rtc.prer().modify(|w| { - w.set_prediv_s(rtc_config.sync_prescaler); - w.set_prediv_a(rtc_config.async_prescaler); + w.set_prediv_s(sync_psc); + w.set_prediv_a(async_psc); }); }); } diff --git a/embassy-stm32/src/rtc/v3.rs b/embassy-stm32/src/rtc/v3.rs index 12952b15..c03b1071 100644 --- a/embassy-stm32/src/rtc/v3.rs +++ b/embassy-stm32/src/rtc/v3.rs @@ -8,7 +8,7 @@ use crate::rtc::sealed::Instance; impl super::Rtc { /// Applies the RTC config /// It this changes the RTC clock source the time will be reset - pub(super) fn configure(&mut self, rtc_config: RtcConfig) { + pub(super) fn configure(&mut self, async_psc: u8, sync_psc: u16) { self.write(true, |rtc| { rtc.cr().modify(|w| { w.set_fmt(Fmt::TWENTYFOURHOUR); @@ -17,8 +17,8 @@ impl super::Rtc { }); rtc.prer().modify(|w| { - w.set_prediv_s(rtc_config.sync_prescaler); - w.set_prediv_a(rtc_config.async_prescaler); + w.set_prediv_s(sync_psc); + w.set_prediv_a(async_psc); }); // TODO: configuration for output pins From 21681d8b4ee392ce3b4f68be76b6096abe104ad3 Mon Sep 17 00:00:00 2001 From: xoviat Date: Tue, 29 Aug 2023 19:44:43 -0500 Subject: [PATCH 094/106] rustfmt --- embassy-stm32/src/rtc/mod.rs | 1 + embassy-stm32/src/rtc/v2.rs | 2 +- embassy-stm32/src/rtc/v3.rs | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/embassy-stm32/src/rtc/mod.rs b/embassy-stm32/src/rtc/mod.rs index 3704e446..9db4f69c 100644 --- a/embassy-stm32/src/rtc/mod.rs +++ b/embassy-stm32/src/rtc/mod.rs @@ -124,6 +124,7 @@ impl Default for RtcCalibrationCyclePeriod { impl Rtc { pub fn new(_rtc: impl Peripheral

, rtc_config: RtcConfig) -> Self { + #[cfg(any(rcc_wb, rcc_f4, rcc_f410))] use crate::rcc::get_freqs; RTC::enable_peripheral_clk(); diff --git a/embassy-stm32/src/rtc/v2.rs b/embassy-stm32/src/rtc/v2.rs index 63d9f09e..482b6e75 100644 --- a/embassy-stm32/src/rtc/v2.rs +++ b/embassy-stm32/src/rtc/v2.rs @@ -1,6 +1,6 @@ use stm32_metapac::rtc::vals::{Init, Osel, Pol}; -use super::{sealed, RtcConfig}; +use super::sealed; use crate::pac::rtc::Rtc; use crate::peripherals::RTC; use crate::rtc::sealed::Instance; diff --git a/embassy-stm32/src/rtc/v3.rs b/embassy-stm32/src/rtc/v3.rs index c03b1071..a6b2655d 100644 --- a/embassy-stm32/src/rtc/v3.rs +++ b/embassy-stm32/src/rtc/v3.rs @@ -1,6 +1,6 @@ use stm32_metapac::rtc::vals::{Calp, Calw16, Calw8, Fmt, Init, Key, Osel, Pol, TampalrmPu, TampalrmType}; -use super::{sealed, RtcCalibrationCyclePeriod, RtcConfig}; +use super::{sealed, RtcCalibrationCyclePeriod}; use crate::pac::rtc::Rtc; use crate::peripherals::RTC; use crate::rtc::sealed::Instance; From 27dfced285f7f997d6a7679373052efb7ae84e01 Mon Sep 17 00:00:00 2001 From: xoviat Date: Tue, 29 Aug 2023 19:51:21 -0500 Subject: [PATCH 095/106] stm32: fix rcc wb --- embassy-stm32/src/rcc/mod.rs | 2 +- embassy-stm32/src/rcc/wb.rs | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/embassy-stm32/src/rcc/mod.rs b/embassy-stm32/src/rcc/mod.rs index 1ead60b1..0430e4a7 100644 --- a/embassy-stm32/src/rcc/mod.rs +++ b/embassy-stm32/src/rcc/mod.rs @@ -81,7 +81,7 @@ pub struct Clocks { /// Set only if the lsi or lse is configured, indicates stop is supported pub rtc: Option, - #[cfg(any(rcc_f4, rcc_f410))] + #[cfg(any(rcc_wb, rcc_f4, rcc_f410))] /// Set if the hse is configured, indicates stop is not supported pub rtc_hse: Option, } diff --git a/embassy-stm32/src/rcc/wb.rs b/embassy-stm32/src/rcc/wb.rs index 6a3eab70..6496b41e 100644 --- a/embassy-stm32/src/rcc/wb.rs +++ b/embassy-stm32/src/rcc/wb.rs @@ -271,6 +271,7 @@ pub(crate) fn compute_clocks(config: &Config) -> Clocks { apb1_tim: apb1_tim_clk, apb2_tim: apb2_tim_clk, rtc: rtc_clk, + rtc_hse: None, } } From 416ecc73d8211e348bf51a5cfe84075673b18963 Mon Sep 17 00:00:00 2001 From: xoviat Date: Tue, 29 Aug 2023 20:06:53 -0500 Subject: [PATCH 096/106] add qei draft --- embassy-stm32/src/timer/qei.rs | 142 +++++++++++++++++++++++++++++++++ 1 file changed, 142 insertions(+) create mode 100644 embassy-stm32/src/timer/qei.rs diff --git a/embassy-stm32/src/timer/qei.rs b/embassy-stm32/src/timer/qei.rs new file mode 100644 index 00000000..fa881472 --- /dev/null +++ b/embassy-stm32/src/timer/qei.rs @@ -0,0 +1,142 @@ +//! # Quadrature Encoder Interface +use crate::{ + gpio::PushPull, + pac, rcc, + timer::{CPin, General}, +}; + +pub trait QeiExt: Sized + Instance { + fn qei( + self, + pins: ( + impl Into<>::Ch>, + impl Into<>::Ch>, + ), + ) -> Qei; +} + +impl QeiExt for TIM { + fn qei( + self, + pins: ( + impl Into<>::Ch>, + impl Into<>::Ch>, + ), + ) -> Qei { + Qei::new(self, pins) + } +} + +/// Hardware quadrature encoder interface peripheral +pub struct Qei { + tim: TIM, + pins: ( + >::Ch, + >::Ch, + ), +} + +impl Qei { + /// Configures a TIM peripheral as a quadrature encoder interface input + pub fn new( + mut tim: TIM, + pins: ( + impl Into<>::Ch>, + impl Into<>::Ch>, + ), + ) -> Self { + // Enable and reset clock. + unsafe { + TIM::enable_unchecked(); + TIM::reset_unchecked(); + } + + let pins = (pins.0.into(), pins.1.into()); + tim.setup_qei(); + + Qei { tim, pins } + } + + /// Releases the TIM peripheral and QEI pins + #[allow(clippy::type_complexity)] + pub fn release( + self, + ) -> ( + TIM, + ( + >::Ch, + >::Ch, + ), + ) { + (self.tim, self.pins) + } + + /// Set current count number + pub fn set_count(&mut self, value: TIM::Width) -> &mut Self { + self.tim.write_count(value); + self + } +} + +impl embedded_hal::Qei for Qei { + type Count = TIM::Width; + + fn count(&self) -> Self::Count { + self.tim.read_count() + } + + fn direction(&self) -> embedded_hal::Direction { + if self.tim.read_direction() { + embedded_hal::Direction::Upcounting + } else { + embedded_hal::Direction::Downcounting + } + } +} + +pub trait Instance: crate::Sealed + rcc::Enable + rcc::Reset + General + CPin<0> + CPin<1> { + fn setup_qei(&mut self); + + fn read_direction(&self) -> bool; +} + +macro_rules! hal { + ($TIM:ty) => { + impl Instance for $TIM { + fn setup_qei(&mut self) { + // Configure TxC1 and TxC2 as captures + #[cfg(not(feature = "gpio-f410"))] + self.ccmr1_input().write(|w| w.cc1s().ti1().cc2s().ti2()); + #[cfg(feature = "gpio-f410")] + self.ccmr1_input() + .write(|w| unsafe { w.cc1s().bits(0b01).cc2s().bits(0b01) }); + // enable and configure to capture on rising edge + self.ccer.write(|w| { + w.cc1e().set_bit().cc1p().clear_bit(); + w.cc2e().set_bit().cc2p().clear_bit() + }); + self.smcr.write(|w| w.sms().encoder_mode_3()); + self.set_auto_reload(<$TIM as General>::Width::MAX as u32) + .unwrap(); + self.cr1.write(|w| w.cen().set_bit()); + } + + fn read_direction(&self) -> bool { + self.cr1.read().dir().bit_is_clear() + } + } + }; +} + +#[cfg(feature = "tim1")] +hal! { pac::TIM1 } +#[cfg(feature = "tim2")] +hal! { pac::TIM2 } +#[cfg(feature = "tim3")] +hal! { pac::TIM3 } +#[cfg(feature = "tim4")] +hal! { pac::TIM4 } +#[cfg(feature = "tim5")] +hal! { pac::TIM5 } +#[cfg(feature = "tim8")] +hal! { pac::TIM8 } From 98f55fa54dd4fd585e90211919f025a7025301a6 Mon Sep 17 00:00:00 2001 From: Frostie314159 Date: Wed, 30 Aug 2023 09:59:47 +0200 Subject: [PATCH 097/106] Reverted patch for lint fix. --- cyw43/src/events.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cyw43/src/events.rs b/cyw43/src/events.rs index ce0e7e37..a94c49a0 100644 --- a/cyw43/src/events.rs +++ b/cyw43/src/events.rs @@ -1,5 +1,5 @@ #![allow(dead_code)] -#![allow(non_camel_case_types, non_upper_case_globals)] +#![allow(non_camel_case_types)] use core::cell::RefCell; From 36ec9bcc1d4ed9beff2e866bcb5ea388538320bb Mon Sep 17 00:00:00 2001 From: Dion Dokter Date: Wed, 30 Aug 2023 19:35:15 +0200 Subject: [PATCH 098/106] Stm32 timer prevent hardfault --- embassy-stm32/src/timer/mod.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/embassy-stm32/src/timer/mod.rs b/embassy-stm32/src/timer/mod.rs index 4ffb2a28..b5ced45f 100644 --- a/embassy-stm32/src/timer/mod.rs +++ b/embassy-stm32/src/timer/mod.rs @@ -211,6 +211,7 @@ macro_rules! impl_basic_16bit_timer { use core::convert::TryInto; let f = frequency.0; let timer_f = Self::frequency().0; + assert!(f > 0); let pclk_ticks_per_timer_period = timer_f / f; let psc: u16 = unwrap!(((pclk_ticks_per_timer_period - 1) / (1 << 16)).try_into()); let arr: u16 = unwrap!((pclk_ticks_per_timer_period / (u32::from(psc) + 1)).try_into()); @@ -255,6 +256,7 @@ macro_rules! impl_32bit_timer { fn set_frequency(&mut self, frequency: Hertz) { use core::convert::TryInto; let f = frequency.0; + assert!(f > 0); let timer_f = Self::frequency().0; let pclk_ticks_per_timer_period = (timer_f / f) as u64; let psc: u16 = unwrap!(((pclk_ticks_per_timer_period - 1) / (1 << 32)).try_into()); From ae174fd0e0102ad77d18c33754dc5493e58dfdb5 Mon Sep 17 00:00:00 2001 From: Michael van Niekerk Date: Wed, 30 Aug 2023 21:42:27 +0200 Subject: [PATCH 099/106] RP2040: XOSC delay multiplier --- embassy-rp/src/clocks.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/embassy-rp/src/clocks.rs b/embassy-rp/src/clocks.rs index 7b25ecff..4637ae05 100644 --- a/embassy-rp/src/clocks.rs +++ b/embassy-rp/src/clocks.rs @@ -94,6 +94,7 @@ impl ClockConfig { post_div1: 6, post_div2: 5, }), + delay_multiplier: 1 }), ref_clk: RefClkConfig { src: RefClkSrc::Xosc, @@ -203,6 +204,7 @@ pub struct XoscConfig { pub hz: u32, pub sys_pll: Option, pub usb_pll: Option, + pub delay_multiplier: u32, } pub struct PllConfig { @@ -363,7 +365,7 @@ pub(crate) unsafe fn init(config: ClockConfig) { // start XOSC // datasheet mentions support for clock inputs into XIN, but doesn't go into // how this is achieved. pico-sdk doesn't support this at all. - start_xosc(config.hz); + start_xosc(config.hz, config.delay_multiplier); let pll_sys_freq = match config.sys_pll { Some(sys_pll_config) => configure_pll(pac::PLL_SYS, config.hz, sys_pll_config), @@ -624,12 +626,12 @@ pub fn clk_rtc_freq() -> u16 { CLOCKS.rtc.load(Ordering::Relaxed) } -fn start_xosc(crystal_hz: u32) { +fn start_xosc(crystal_hz: u32, delay_multiplier: u32) { pac::XOSC .ctrl() .write(|w| w.set_freq_range(pac::xosc::vals::CtrlFreqRange::_1_15MHZ)); - let startup_delay = ((crystal_hz / 1000) + 128) / 256; + let startup_delay = (((crystal_hz / 1000) + 128) * delay_multiplier) / 256; pac::XOSC.startup().write(|w| w.set_delay(startup_delay as u16)); pac::XOSC.ctrl().write(|w| { w.set_freq_range(pac::xosc::vals::CtrlFreqRange::_1_15MHZ); From 891f1758bcd2621148ffba163d054da4420416aa Mon Sep 17 00:00:00 2001 From: Michael van Niekerk Date: Wed, 30 Aug 2023 21:43:57 +0200 Subject: [PATCH 100/106] RP2040: XOSC delay multiplier --- embassy-rp/src/clocks.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/embassy-rp/src/clocks.rs b/embassy-rp/src/clocks.rs index 4637ae05..55a18cf6 100644 --- a/embassy-rp/src/clocks.rs +++ b/embassy-rp/src/clocks.rs @@ -94,7 +94,7 @@ impl ClockConfig { post_div1: 6, post_div2: 5, }), - delay_multiplier: 1 + delay_multiplier: 1, }), ref_clk: RefClkConfig { src: RefClkSrc::Xosc, From f69e8459c9a2362165df9dd603adb0ec6531d383 Mon Sep 17 00:00:00 2001 From: Michael van Niekerk Date: Wed, 30 Aug 2023 21:52:03 +0200 Subject: [PATCH 101/106] RP2040: Fixes as per PR --- embassy-rp/src/clocks.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/embassy-rp/src/clocks.rs b/embassy-rp/src/clocks.rs index 55a18cf6..c9b2190c 100644 --- a/embassy-rp/src/clocks.rs +++ b/embassy-rp/src/clocks.rs @@ -94,7 +94,7 @@ impl ClockConfig { post_div1: 6, post_div2: 5, }), - delay_multiplier: 1, + delay_multiplier: 128, }), ref_clk: RefClkConfig { src: RefClkSrc::Xosc, @@ -631,7 +631,7 @@ fn start_xosc(crystal_hz: u32, delay_multiplier: u32) { .ctrl() .write(|w| w.set_freq_range(pac::xosc::vals::CtrlFreqRange::_1_15MHZ)); - let startup_delay = (((crystal_hz / 1000) + 128) * delay_multiplier) / 256; + let startup_delay = ((crystal_hz / 1000 + delay_multiplier) + 128) / 256; pac::XOSC.startup().write(|w| w.set_delay(startup_delay as u16)); pac::XOSC.ctrl().write(|w| { w.set_freq_range(pac::xosc::vals::CtrlFreqRange::_1_15MHZ); From a76ff53fb396be26dfc5153e72c3e77c004afdf6 Mon Sep 17 00:00:00 2001 From: Michael van Niekerk Date: Wed, 30 Aug 2023 21:58:36 +0200 Subject: [PATCH 102/106] RP2040: Fixes as per PR --- embassy-rp/src/clocks.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/embassy-rp/src/clocks.rs b/embassy-rp/src/clocks.rs index c9b2190c..2c41befe 100644 --- a/embassy-rp/src/clocks.rs +++ b/embassy-rp/src/clocks.rs @@ -631,7 +631,7 @@ fn start_xosc(crystal_hz: u32, delay_multiplier: u32) { .ctrl() .write(|w| w.set_freq_range(pac::xosc::vals::CtrlFreqRange::_1_15MHZ)); - let startup_delay = ((crystal_hz / 1000 + delay_multiplier) + 128) / 256; + let startup_delay = (((crystal_hz / 1000) + 128) * delay_multiplier) / 256; pac::XOSC.startup().write(|w| w.set_delay(startup_delay as u16)); pac::XOSC.ctrl().write(|w| { w.set_freq_range(pac::xosc::vals::CtrlFreqRange::_1_15MHZ); From 83a976cf4bd963f39bd0d3e4ea56f4b35bd82031 Mon Sep 17 00:00:00 2001 From: Michael van Niekerk Date: Wed, 30 Aug 2023 21:59:41 +0200 Subject: [PATCH 103/106] RP2040: Fixes as per PR --- embassy-rp/src/clocks.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/embassy-rp/src/clocks.rs b/embassy-rp/src/clocks.rs index 2c41befe..22066546 100644 --- a/embassy-rp/src/clocks.rs +++ b/embassy-rp/src/clocks.rs @@ -631,7 +631,7 @@ fn start_xosc(crystal_hz: u32, delay_multiplier: u32) { .ctrl() .write(|w| w.set_freq_range(pac::xosc::vals::CtrlFreqRange::_1_15MHZ)); - let startup_delay = (((crystal_hz / 1000) + 128) * delay_multiplier) / 256; + let startup_delay = (((crystal_hz / 1000) * delay_multiplier) + 128) / 256; pac::XOSC.startup().write(|w| w.set_delay(startup_delay as u16)); pac::XOSC.ctrl().write(|w| { w.set_freq_range(pac::xosc::vals::CtrlFreqRange::_1_15MHZ); From 37694473824952574e0bd9332b8ef38d77a9bf55 Mon Sep 17 00:00:00 2001 From: kalkyl Date: Wed, 30 Aug 2023 23:20:38 +0200 Subject: [PATCH 104/106] rp: Fix write size in embassy-boot example app --- examples/boot/application/rp/src/bin/a.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/boot/application/rp/src/bin/a.rs b/examples/boot/application/rp/src/bin/a.rs index 15fdaca8..a4602a7e 100644 --- a/examples/boot/application/rp/src/bin/a.rs +++ b/examples/boot/application/rp/src/bin/a.rs @@ -38,7 +38,7 @@ async fn main(_s: Spawner) { let flash = Mutex::new(RefCell::new(flash)); let config = FirmwareUpdaterConfig::from_linkerfile_blocking(&flash); - let mut aligned = AlignedBuffer([0; 4]); + let mut aligned = AlignedBuffer([0; 1]); let mut updater = BlockingFirmwareUpdater::new(config, &mut aligned.0); Timer::after(Duration::from_secs(5)).await; From c10fb7c1c4ca40749494f4873c2144906c2f1a17 Mon Sep 17 00:00:00 2001 From: xoviat Date: Wed, 30 Aug 2023 18:10:26 -0500 Subject: [PATCH 105/106] stm32: implement qei --- embassy-stm32/src/timer/mod.rs | 1 + embassy-stm32/src/timer/qei.rs | 216 +++++++++++++-------------------- 2 files changed, 86 insertions(+), 131 deletions(-) diff --git a/embassy-stm32/src/timer/mod.rs b/embassy-stm32/src/timer/mod.rs index 4ffb2a28..6036a456 100644 --- a/embassy-stm32/src/timer/mod.rs +++ b/embassy-stm32/src/timer/mod.rs @@ -1,4 +1,5 @@ pub mod complementary_pwm; +pub mod qei; pub mod simple_pwm; use stm32_metapac::timer::vals; diff --git a/embassy-stm32/src/timer/qei.rs b/embassy-stm32/src/timer/qei.rs index fa881472..c0f9288a 100644 --- a/embassy-stm32/src/timer/qei.rs +++ b/embassy-stm32/src/timer/qei.rs @@ -1,142 +1,96 @@ -//! # Quadrature Encoder Interface -use crate::{ - gpio::PushPull, - pac, rcc, - timer::{CPin, General}, -}; +use core::marker::PhantomData; -pub trait QeiExt: Sized + Instance { - fn qei( - self, - pins: ( - impl Into<>::Ch>, - impl Into<>::Ch>, - ), - ) -> Qei; +use embassy_hal_internal::{into_ref, PeripheralRef}; + +use super::*; +use crate::gpio::sealed::AFType; +use crate::gpio::AnyPin; +use crate::Peripheral; + +pub enum Direction { + Upcounting, + Downcounting, } -impl QeiExt for TIM { - fn qei( - self, - pins: ( - impl Into<>::Ch>, - impl Into<>::Ch>, - ), - ) -> Qei { - Qei::new(self, pins) - } +pub struct Ch1; +pub struct Ch2; + +pub struct QeiPin<'d, Perip, Channel> { + _pin: PeripheralRef<'d, AnyPin>, + phantom: PhantomData<(Perip, Channel)>, } -/// Hardware quadrature encoder interface peripheral -pub struct Qei { - tim: TIM, - pins: ( - >::Ch, - >::Ch, - ), -} - -impl Qei { - /// Configures a TIM peripheral as a quadrature encoder interface input - pub fn new( - mut tim: TIM, - pins: ( - impl Into<>::Ch>, - impl Into<>::Ch>, - ), - ) -> Self { - // Enable and reset clock. - unsafe { - TIM::enable_unchecked(); - TIM::reset_unchecked(); - } - - let pins = (pins.0.into(), pins.1.into()); - tim.setup_qei(); - - Qei { tim, pins } - } - - /// Releases the TIM peripheral and QEI pins - #[allow(clippy::type_complexity)] - pub fn release( - self, - ) -> ( - TIM, - ( - >::Ch, - >::Ch, - ), - ) { - (self.tim, self.pins) - } - - /// Set current count number - pub fn set_count(&mut self, value: TIM::Width) -> &mut Self { - self.tim.write_count(value); - self - } -} - -impl embedded_hal::Qei for Qei { - type Count = TIM::Width; - - fn count(&self) -> Self::Count { - self.tim.read_count() - } - - fn direction(&self) -> embedded_hal::Direction { - if self.tim.read_direction() { - embedded_hal::Direction::Upcounting - } else { - embedded_hal::Direction::Downcounting - } - } -} - -pub trait Instance: crate::Sealed + rcc::Enable + rcc::Reset + General + CPin<0> + CPin<1> { - fn setup_qei(&mut self); - - fn read_direction(&self) -> bool; -} - -macro_rules! hal { - ($TIM:ty) => { - impl Instance for $TIM { - fn setup_qei(&mut self) { - // Configure TxC1 and TxC2 as captures - #[cfg(not(feature = "gpio-f410"))] - self.ccmr1_input().write(|w| w.cc1s().ti1().cc2s().ti2()); - #[cfg(feature = "gpio-f410")] - self.ccmr1_input() - .write(|w| unsafe { w.cc1s().bits(0b01).cc2s().bits(0b01) }); - // enable and configure to capture on rising edge - self.ccer.write(|w| { - w.cc1e().set_bit().cc1p().clear_bit(); - w.cc2e().set_bit().cc2p().clear_bit() +macro_rules! channel_impl { + ($new_chx:ident, $channel:ident, $pin_trait:ident) => { + impl<'d, Perip: CaptureCompare16bitInstance> QeiPin<'d, Perip, $channel> { + pub fn $new_chx(pin: impl Peripheral

> + 'd) -> Self { + into_ref!(pin); + critical_section::with(|_| { + pin.set_low(); + pin.set_as_af(pin.af_num(), AFType::Input); + #[cfg(gpio_v2)] + pin.set_speed(crate::gpio::Speed::VeryHigh); }); - self.smcr.write(|w| w.sms().encoder_mode_3()); - self.set_auto_reload(<$TIM as General>::Width::MAX as u32) - .unwrap(); - self.cr1.write(|w| w.cen().set_bit()); - } - - fn read_direction(&self) -> bool { - self.cr1.read().dir().bit_is_clear() + QeiPin { + _pin: pin.map_into(), + phantom: PhantomData, + } } } }; } -#[cfg(feature = "tim1")] -hal! { pac::TIM1 } -#[cfg(feature = "tim2")] -hal! { pac::TIM2 } -#[cfg(feature = "tim3")] -hal! { pac::TIM3 } -#[cfg(feature = "tim4")] -hal! { pac::TIM4 } -#[cfg(feature = "tim5")] -hal! { pac::TIM5 } -#[cfg(feature = "tim8")] -hal! { pac::TIM8 } +channel_impl!(new_ch1, Ch1, Channel1Pin); +channel_impl!(new_ch2, Ch2, Channel2Pin); + +pub struct SimplePwm<'d, T> { + _inner: PeripheralRef<'d, T>, +} + +impl<'d, T: CaptureCompare16bitInstance> SimplePwm<'d, T> { + pub fn new(tim: impl Peripheral

+ 'd, _ch1: QeiPin<'d, T, Ch1>, _ch2: QeiPin<'d, T, Ch2>) -> Self { + Self::new_inner(tim) + } + + fn new_inner(tim: impl Peripheral

+ 'd) -> Self { + into_ref!(tim); + + T::enable(); + ::reset(); + + // Configure TxC1 and TxC2 as captures + T::regs_gp16().ccmr_input(0).modify(|w| { + w.set_ccs(0, vals::CcmrInputCcs::TI4); + w.set_ccs(1, vals::CcmrInputCcs::TI4); + }); + + // enable and configure to capture on rising edge + T::regs_gp16().ccer().modify(|w| { + w.set_cce(0, true); + w.set_cce(1, true); + + w.set_ccp(0, false); + w.set_ccp(1, false); + }); + + T::regs_gp16().smcr().modify(|w| { + w.set_sms(vals::Sms::ENCODER_MODE_3); + }); + + T::regs_gp16().arr().modify(|w| w.set_arr(u16::MAX)); + T::regs_gp16().cr1().modify(|w| w.set_cen(true)); + + Self { _inner: tim } + } + + pub fn read_direction(&self) -> Direction { + match T::regs_gp16().cr1().read().dir() { + vals::Dir::DOWN => Direction::Downcounting, + vals::Dir::UP => Direction::Upcounting, + } + } + + pub fn count(&self) -> u16 { + T::regs_gp16().cnt().read().cnt() + } +} From b74645e25960c6d4160b5a150d2e6bf239cef9c8 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Fri, 1 Sep 2023 00:21:01 +0200 Subject: [PATCH 106/106] Delete .github/bors.toml --- .github/bors.toml | 4 ---- 1 file changed, 4 deletions(-) delete mode 100644 .github/bors.toml diff --git a/.github/bors.toml b/.github/bors.toml deleted file mode 100644 index 1ecc9d8d..00000000 --- a/.github/bors.toml +++ /dev/null @@ -1,4 +0,0 @@ -status = [ - "all", -] -delete_merged_branches = true